Which would be the better approach?

Hello!

I'm a working java professional, but has taken on some courses on the local University.

Of course there is a difference in how things are solved in theory and practise, but it makes

me wonder what the "best" solutions to some problems are...

Consider the following structure:

class Book{

private List chapters;

}

class Chapter{

private List pages;

private Book book;

public Book getBook(){

return this.book;

}

}

class Page{

private List chars;

private Chapter chapter;

public Chapter getChapter(){

return this.chapter;

}

}

class Char{

private Page page;

public Page getPage(){

return this.page;

}

publicvoid method(){

// blabla

}

}

Check out the "method" in class Char. Say I would like to have a reference to the Book that this character is in. I would say that I have two choices:

1. call getPage().getChapter().getBook()

2. put a getBook() in each of the classes

Where I come from it is a bad thing to "expose structure", the first example exposes structure.

But, it is also a bad thing to let classes do things that they aren't responsible for (cohesion).

What solution would you prefer?

[2366 byte] By [ronniebahlstena] at [2007-9-29 19:48:01]
# 1

Hi,

I would prefer 1. For the following reasons:

a) Why is it a bad thing to expose this structure? If the structure shouldn't be exposed then maybe you shouldn't be using so many classes?

b) Keep things simple. If this is not possible it's easier to add complexity than it is to remove it.

If you really want to 'hide' the structure there is another alternative.

You could create a "Books" static utility class with varous overloaded methods:

public Book getBook( Chapter chapter ) {...}

public Book getBook( Page page ) {...}

and use

Book bookThatContainsThingy = Books.getBook( thingy );

for various thingy objects. Using such a static utility class would probably make more sense if Book, Chapter, etc. were interfaces rather than classes.

Hope this makes sense,

Ol.

0sa at 2007-7-15 21:34:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

Hi,

Oops. That should be:

public static Book getBook( Chapter chapter ) {...}

public static Book getBook( Page page ) {...}

Ol.

0sa at 2007-7-15 21:34:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

Create a BookItem class which contains the book owner:

class Book {...}

class BookItem {

private Book book;

public Book getBook() {

return book;

}

}

class Chapter extends BookItem {...}

class Page extends BookItem {...}

class Character extends BookItem {...}

lwiklendta at 2007-7-15 21:34:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

Hi!

With getPage().getChapter().getBook() surely you are having too high coupling and also exposure.

In just one code line you are coupling to three classes and also violating twice De Meter assumption about not accessing class internal structures as character accesses to chapter through Page and to Book through Chapter.

The problem is in the main design idea i think...you are just designing data structures as if you would be designing db entities, with double dispatches between all classes as you would connect db tables with joins but this ends with no real reusability, think to this.... you can't reuse any of your classes without carrying all of the others.

For example why a character should be linked to a book, a character can be an actor of many books but it's not connected to a specific book. A character class should be reusable in movies, lyrichs, books, dreams. Why you want a Chapter to know what is a book? In concrete that means that every time you modify the book class you must recompile also the chapter cause it's directly connected to the book class and also you can use your Chapter class only within your Book class, it's not reusable at all.

You want to search characters within books? ok you just need an external components that will enter the library and ask to any book what's it about and which characters play in it if it is a characters book,

so everyone will just expose services for the data it's responsible for.

bennyfiora at 2007-7-15 21:34:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

I agree that the original design is inherently highly coupled. For example, you have a Chapter object referencing a list of Page objects, but each Page object contains a reference to 'back up the chain', so to speak, to it's chapter. Having had to try to maintain someone else's code where they did this it was nightmarish.

I agree that the classes have not been abstracted correctly. They seem to stem directly form tables in an RDB. Rarely does RDB table structure map to OO. We often encounter this problem where I work as well (that is, inexperienced designers trying to replicate the physical structure rather than the logical structure, or business entities).

I like the idea of the utility classes.

DavisonTa at 2007-7-15 21:34:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

How bout this...using composition -- characters, pages, and chapters are all part of a book. This is closer to modeling real world objects.

public interface Book {

public void createChapter(...);

public void createPage(...);

public void findChapter(...);

public void findPage();

...

}

public final class TextBook implements Book {

private Collection chapters;

private Collection pages;

private Collection characters;

class Chapter { .....}

class Pages { .....}

class Char { .....}

// Methods for creating and managing book elements go here

}

cvelez69a at 2007-7-15 21:34:56 > top of Java-index,Other Topics,Patterns & OO Design...