aspose file tools*
The moose likes OO, Patterns, UML and Refactoring and the fly likes Return mutable collection? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "Return mutable collection?" Watch "Return mutable collection?" New topic
Author

Return mutable collection?

bujin wang
Ranch Hand

Joined: Jun 21, 2003
Posts: 48
Dear developers,
Suppose I have got a class A contains a list of B(components). Here is what I have implemented.

Ok, one of my friend comes in and has another idea of how to implement this:

and Here is his BCollection class:

According to him, that way we don't to have "A" around to operate on components. But to me, it's kind of breaking the encapsulation, which shoudl be avoided.
What do you guys think? Any strong reason why/why not doing this?

Thanks,
Bujin Wang
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
If managing Bs is A's main job, and A is the only place you can get Bs, I'd leave it as is. It occurs to me I just built an interface a lot like A yesterday but the actual add, remove and get operations were complex enough that I delegated them to a BCollection hidden inside A. In my case A does some other stuff, too, and it should maybe become a facade for several worker bees.
[ September 25, 2003: Message edited by: Stan James ]

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
bujin wang
Ranch Hand

Joined: Jun 21, 2003
Posts: 48
I will analog this problem to a real example:
You have got a house(in our case class "A"), there is a book shelf in your house which has a number of books on it(class Bs). You friends could borrow and return your books(lendBook, returnBook, getBookCount,etc.).
Implementation one says that in order to acess books on the bookshelf, you have to go through house.
Implementation two says that you don't have to go through house in order to borrow or return books. You directly ask the house that you want to access bookshelf and once house permits, all the bookshelf is yours.
I am kind of thinking implementation two gives too much permission for bookshelf, in that all the accesses are not monitor by house.
Anybody agree?
Bujin Wang
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Well, by looking at the implementations, it seems as if you just renamed A to BCollection and then put another class A between BCollection and its clients. What purpose does A serve in the refactored solution?


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
bujin wang
Ranch Hand

Joined: Jun 21, 2003
Posts: 48
I should ahve pointed out that in A, there are more other operations. B management is a small part of its responsibilities.
However BCollection is purely for managing Bs, as shown in code. It's kind of open a special door for Bs.
Bujin Wang
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by bujin wang:
I should ahve pointed out that in A, there are more other operations. B management is a small part of its responsibilities.

Then you do have two forces working here:
- the Single Responsibility Principles tells you that a class should only have to change for one reason. This would force you to encapsulate management of Bs into its own class.
- the Law Of Demeter tells you not to call methods on objects you asked to get from other objects, that is it discourages code of the form "foo.getX().doY()".
Personally, I find that the SRP is typically the stronger principle. Small classes are simply so much easier to maintain and much more reusable.
On the other hand, violating the LoD often makes unit testing much more complex and generally increases coupling in the system.
One way to cope with both principles is to put the add, remove etc. methods into A, but simply let them delegate to a BCollection. Wether the still increased interface size of A and the complexity of delegation is worth the hassle is hard to tell without knowing more about the code and how it gets used, though.
Did that help?
bujin wang
Ranch Hand

Joined: Jun 21, 2003
Posts: 48
I am kind of prefering your idea here, to leave the B management code inside A. I hope I have simpler reasons to convince my friend. Any easy to say reasons?
Bujin Wang
Donny Han
Greenhorn

Joined: Sep 29, 2003
Posts: 1
I prefer to seperate the case into A and B classes.
Let's use the house sample you gave, imp two still has to touch the house first, telling the house:"hey, give me the position of the book shelf, I want to do soemthing!"
And maybe, both A and B have some operations, you have to distinguish them, you need to gave different name for them if you put A and B in one class. OO is not just encapsulation, before we come to a conclusion, we have to have a overlook of whole thing. So I might be wrong with your situation.
bujin wang
Ranch Hand

Joined: Jun 21, 2003
Posts: 48
Please note that class A and B are just imagined classes. A has some behaviours like:
public void operation1();
public int operation2();
...
The main concern here is really whether we should seperate B management operations into another collection class "BCollection". And also is it a good idea to expose the internal components to another class(BCollection). Remember through BCollection, we have full control of components(Bs).
It's kind of giving somebody else full control of your book shelf without house's notice. I think the house should know every operation happened to bookshelf.
Jeroen Wenting
Ranch Hand

Joined: Oct 12, 2000
Posts: 5093
What I'd do is have A contain an instance of BCollection and methods to control operations on that Collection.
That way A operates as a proxy for BCollection and will at the same time control that what is added to the BCollection it controls is valid in its own context.
If you ever need an independent BCollection you can have it, but the one controlled by A should not be directly exposed unless it really doesn't belong inside A in the first place.


42
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by bujin wang:
Please note that class A and B are just imagined classes. A has some behaviours like:
public void operation1();
public int operation2();
...
The main concern here is really whether we should seperate B management operations into another collection class "BCollection". And also is it a good idea to expose the internal components to another class(BCollection). Remember through BCollection, we have full control of components(Bs).

And I don't think it can be answered in a generic way other than: it depends.

It's kind of giving somebody else full control of your book shelf without house's notice. I think the house should know every operation happened to bookshelf.

On the other hand, do you really want to change the implementation of the house every time you change the inventory? And what about the books - should I be able to get a direct handle on one? Why do I have a direct handle on the house - shouldn't I ask the street instead?
With all due respect, I don't think that this analogy or the abstract code example do help much. Show us some real code, than we can begin to argue!
bujin wang
Ranch Hand

Joined: Jun 21, 2003
Posts: 48
Ok, here I am explaining a real example. Bear with me here:
Suppose we need to model a book. A book contains pages, it also contains paragraphs. Let's don't worry about the actual words and characters. There is a authour, publisher and ISBN, content, index, appendex for this book as well. Although I have listed a bunch of items here, let's focus on how to handle pages and paragraphs. Don't worry about the possibility of page number changing,etc., that's too detailed.
First, let's see the first modeling options:
1) A book contains an array list holding the pages;
2) The book contains another array list holding paragraphs.
3) We have all pages, paragraphs related operations(includes mutable operations: addPage(), removePage(), addParagraph(), removeParagraph());
Here is the code(not compilable):

This option basically tights pages related operations and paragraph related operations with Book, which in my last post is class A.
Second, let's see how we could seperate page and paragraph related operations into differnt classes:

As you can see, for option two, the page and paragraph related operations are now moved to its collection classes. The book doesn't know anything about page and paragraph operations(add, remove).
Which way you think is more approprite?

Cheers,
Bujin Wang
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by bujin wang:
Ok, here I am explaining a real example.

That's better.
Actually, I have worked on something similar some months ago: we had reports consisting of several "parts" (a part could be one or more pages), each holding a number of "report elements" (text, diagrams, maps etc.).
Which way you think is more approprite?

Neither.
From the above it seems to me as if a book consists of pages, which consist of paragraphs (correct me if I am wrong). That is, a paragraph belongs to a page. Therefore I would put the page handling methods into the Book class, and the paragraph handling ones *into the Page class*.
But that would only be a preliminary design. The best design is very much affected by how the code is used. That's one of the things why Test Driven Development is so valuable - it makes you think about the interface of your classes *in the context of client code*.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Return mutable collection?