• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Decoupling and Law of Demeter

 
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Andy/Dave,
PP has a section about writing "shy" code: "don't reveal yourself to others, and don't interact with too many people."
I would like to get your opinions on this one issue that has been discussed in this forum recently. The issue is regarding encapsulation and coupling in general and specifically, whether or not getters and setters break encapsulation.
As a matter of practicality, I use getters and setters when it's covenient and in the context of trivial and (probably) unchanging things. For non-trivial and changeable things, I pretty much go by the rule of not asking objects for information that I need to do something but rather ask the objects that have the information do something for me.
Anyway, the question was: given a Catalog class, which design breaks encapsulation and adds brittle coupling?
Design 1: have Catalog return a Collection of products in response to a getProducts() message
Design 2: have Catalog return a Product in response to a getProduct(aProductID)
Another point of discussion was whether a method like Catalog.getProduct(aProductID) maintained encapsulation more than a method like Catalog.doSomethingWith(Product).
I'm sure a lot of folks here would be interested to hear your opinions, especially from a pragmatic point of view.
Thanks,
Junilu
 
Ranch Hand
Posts: 338
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Now that is the kind of question that makes you go, hmmmm?
This debate rages on. . .
(goto google and search for: brittle coupling, and see what you get)
Andy/Dave
At what point do theoretical underpinnings detract from the task at hand?
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Andrew Shafer:

At what point do theoretical underpinnings detract from the task at hand?


All right, let me rephrase:
In your experience, have you found that getters and setters lead to code that suffers from "Feature Envy" or even code that is not particularly OO?
In more practical terms: in your experience, do getters and setters make it harder to refactor code?
 
Author
Posts: 55
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'll post more on this tomorrow, as it's dinner time here on the east coast, but in a nutshell:
I've not *personally* felt that getters/setters are bad. A common refactoring I experience is to replace a "simple" getter with a calculation, or to replace a "simple" setter with more complicated code. I get flexibility in the implementation without affecting the interface.
But much depends on the nature of the class, if the class is nothing BUT getters and setters then you may have a problem -- the thing is just a struct in class clothing :-)
/\ndy
 
Andy Hunt
Author
Posts: 55
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Andrew Shafer:

At what point do theoretical underpinnings detract from the task at hand?


Most of the time :-)
The typical consultant's answer, which I'll hide behind here, is: "it depends."
But it really does depend on the context. Many times these sorts of questions are akin to asking, "How long is a piece of string?"
That's a tough one to answer without more context.
More tomorrow...
/\ndy
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok, since Andy is having dinner and I'm still waiting for my wife to pick me up, I'll have a go at answering my own question.
Andrew, I hope this is practical enough for you
The Law of Demeter for functions states that any method of an object should call only methods belonging to:
1) itself
2) any parameters that were passed in to the method
3) any objects it created
4) any directly held component objects


"Because following the Law of Demeter reduces the size of the response set in the calling class, it follows that classes designed in this way will also tend to have fewer errors."
--Pragmatic Programmer, pg. 141


An object that uses a method like Catalog.getProduct(anIdentifier) that returns a Product in all likelihood does not follow the Law of Demeter. Furthermore, the Catalog is revealing something of itself to others.
I should add that the PP advises

"you must balance the pros and cons of your particular application... In fact, by reversing the Law of Demeter and tightly coupling several modules, you may realize an important performance gain. As long as it is well known and acceptable for those modules to be coupled, you design is fine."


As for your question in your other post, Andrew, I think what you will get from reading the PP is a heck of a lot of good advice.
Junilu
 
Ranch Hand
Posts: 1157
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am watching this thread with interest - this is one of my best threads - Thanks Junilu and all the contributors.
-- Sandeep
 
Author
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Let me sneak in with my 2 cents worth while Andy's having his dessert.
You ask two interesting questions. The first is about getters and setters, the second about Demeter and collections. Let's look at accessor methods first.
The best advice when it comes to accessors comes from Bertrand Meyer. His Uniform Access Principle basically states that you shouldn't be able to tell if the attribute you are fetching from an object is just data, or whether it is the result of calculation. Why's tihs a good thing? In a nutshell, it gives you the freedom to change the object's internal implementation without affecting the rest of the world. Say you have a class that holds a set of values, and you want to be able to ask it some property of these values (say their standard deviation). You might start off by calculating this value every time you add someting to the class, and making this calculated property available as a public double std_dev;. Your class is integrated into the rest of the application, and everyone codes using obj.std_dev. Then someone comes to you and says "your class is really killing us in terms of performance. We add 10,000,000 numbers to it and then want to get the standard deviation. It looks like it calculates the standard deviation unnecessarily 9,999,999 times. OK, you think, I'll change it to calculate the standard deviation only when asked. You change the instance variable to a public function, and guess what? Everyone's code that uses you class breaks.
If instead you'd implemented it as an accessor to start with, you'd have the flexibility to experiment with multiple implementations, all without affecting anyone in the rest of the system.
Do I personally always use accessors? No, but the only times I expose data diretly are (1) when I'm writing a data-only class, and (2) when that's the actual real-world semantics of the attribute. All other times I use accessors, just because it lets me rock-n-roll behind my interface.
One last point: It's unfortunate that Java syntax distinguishes between access to instance variables and access to instance methods. Some languages make that transparent. In Eiffel, for example, you declare in the class definition whether an attribute is a direct access to data, or whether it is implemented via a method. It becomes transparent from the outside. In Ruby, attributes are always implemented by methods, but it generates those methods for you when you just want to export an instance variable. It also lets you assign to attributes accessed via these methods: it has methods that can be lvalues.
Anyway, the second point was about Demeter and collections, and that'll be the next reply...
 
Dave Thomas
Author
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Now on to collections and Demeter.
First, an observation. The Law of Demeter is probably badly named. In no sense is it really a law. Instead, I'd rather call it the Test Of Demeter, because by looking at its principles you can judge how well decoupled your code is, and by considering it as you write, you can produce far less brittle designs.
Demeter is interesting with collections. If you stick a bunch of objects into a Vector, can you thereafter only access those object's attributes via the Vector? My opinion is that it depends.
If the collection of objects represents some entity in your design, then I'd say the answer is yes. For example, if you have a shopping cart, and you add items to it as they are bought, then clearly the collection is a significant object in your system. Here, Demeter applies. If you want to find the total value of items in the cart, you'd say cart.getTotal() rather than iterating through each item and writing total = total + cart.itemAt(i).total() (or whatever). This is good decoupling. It leaves the Cart class free to implement things the way it wants.
Alternatively, things may be stored in containers and also accessed as individual items. The various AWT and Swing containers are common examples of this. Your button is an object in its own right, and you are free to make calls to it, but at the same time it's part of some bigger panel. This gets trickier, but can be reconciled with Demeter as long as you don't keep an external reference to that button once it is in the larger container. Instead, the button acts autonomously while it is inside the container, handling events for itself, and passing a reference to itself out while those events are being handled. Demeter isn't being broken (except possibly by the underlying operating system) because our code is not telling the button what to do by getting a reference to it from the container.
As I said, Demeter isn't really a law. But if you keep Demeter in the back of your mind as you code, you'll find yourself writing far tidier interfaces, and designing objects with far more delineated purposes. That that improves code clarity, reduces coupling, and greatly eases maintenance.

Dave
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Dave Thomas:
As I said, Demeter isn't really a law. But if you keep Demeter in the back of your mind as you code, you'll find yourself writing far tidier interfaces, and designing objects with far more delineated purposes. That that improves code clarity, reduces coupling, and greatly eases maintenance.
Dave


So, I guess bottom line is (and we go back to the standard consultant's defense): "It depends." And I agree, you have to weigh the pros and cons and look at it in the context of your application.
Thanks!
Junilu
 
Desai Sandeep
Ranch Hand
Posts: 1157
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Junilu,
Going by the example of the cart which Dave has given, can we say the following in the Catalog and Product case :

  1. Design#1 - getProducts() - will break encapsulation and adds brittle coupling.Reason - If the Catalog needs to know the details of the Product, it will have to invoke calls to Product methods
  2. Design#2 - getProduct(id) - maintains encapsulation and makes future design easier, as we really don't know the internal representation of the Object that is being fetched, following the
    "Uniform Access Principle".

  3. Please let me know your views on this.
    Thanks in advance,
    Sandeep


 
Dave Thomas
Author
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by JUNILU LACAR:
So, I guess bottom line is (and we go back to the standard consultant's defense): "It depends." And I agree, you have to weigh the pros and cons and look at it in the context of your application.


I think it's slightly stronger than "it depends", in that simply knowing about the LoD will make you think more about your design. You can then conciously choose to follow it, or choose to break it. If you break it, then we recommend going the whole hog and tightly coupling those objects into a little constellation of objects. From the outside, treat these as a lump, and then work to decouple them from the rest of the system. -- Dave
 
Desai Sandeep
Ranch Hand
Posts: 1157
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Dave,
This is the problem we are referring to:
In design #1, the Catalog object has a getProducts() method, which returns a collection object, such as a Dictionary or array, containing all the Products the company sells. In design #2, the Catalog object has a getProductNumbered(anIdentifier) method, which returns the Product with the specified unique identifier. Considering the objects returned,which of the following BEST characterizes the two designs?
a) Both designs maintain the objects' encapsulation and reduce coupling by accessing state data via methods only and not directly.
b) Both designs break the objects' encapsulation, adding brittle coupling.
c) Design #1 breaks the encapsulation of the Catalog, adding brittle coupling. Design #2 maintains the encapsulation of the Catalog, making future design changes easier
Choose one answer

Please let us know your views on the correct answer.
Thanks in advance,
Sandeep
 
Desai Sandeep
Ranch Hand
Posts: 1157
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Originally posted by Dave Thomas:
You change the instance variable to a public function,
and guess what? Everyone's code that uses you class breaks.


If I have to describe in one word for the above, would it be correct to say it is "Refactoring" that is going to decide low coupling and encapsulation?
If that is correct,I think the answer (please refer to my above post) would be C.
Reasons:

  1. Design#1 - Catalog.getProducts(),means if we make a change in the Product class, say adding one more attribute, the Catalog class would be affected also.Hence, coupling is high and brittle.
  2. Design#2 - Catalog.getProductNumbered(anIdentifier), would mean Catalog is delegating/invoking a method of the Product- Hence changing the Product definition would most probably not require any change to Catalog.Hence, it is a case of low coupling.

  3. I am not sure on encapsulation in both the cases.Please care to explain taking the above problem as an example.
    Also, is it correct to say "Low coupling means encapsulation is maintained".
    Thanks in advance,
    Sandeep
 
Dave Thomas
Author
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK, if you're pushing for an absolute answer:
Neither of the two solutions is good, and both would lead me to wonder about the design of the system that led me to this point. For the getproducts solution, I'd wonder why I needed to duplicate functionality that the catalogue itself possesses. The catalogue is already a collection of products: why make another?
For the getProduct(i) solution, I'd wonder what I was about to do with this product. Once I put the product in the catalogue, I would assume that the catalog was maintaining it: why would I want to break that trust and hack the element behind the catalogue's back? Say the catalogue maintained some values based on the availability or price of individual products. Manipulating those products without the catalogue being involved would be a mistake. Perhaps if read-only access to product objects was required I'd sub-class Product into something that was a data-only object and have getProduct(i) return an object of this class. It depends.
So the answer would be to ask "why are you asking the question?". Why do you need to get individual products out of the catalogue in the first place, and what do you plan to do with them over time? Based on the answer, we'd then devise a proper solution.
Dave
 
Desai Sandeep
Ranch Hand
Posts: 1157
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Dave,
Thanks a lot for the information.It has given me valuable insight.

As regards the problem, I had always assumed that the Catalog doesnot contain Products, since the problem does not make an explicit mention about it.(although it should be that way )
If the Catalog has to contain all the Products, then coupling would be high between the 2 classes.If I am correct, getProduct() symbolizes this.Hence,this method is suggestive of brittle coupling.
On the other hand, getProduct(id) might mean the Catalog does not have complete information about the Product object, hence it may be delegating it to ProductHelper to give Catalog this object.


Originally posted by Dave Thomas:
Why do you need to get individual products out of the catalogue in the first place, and what do you plan to do with them over time?


I believe, the customer may ask the Catalog about the Product (its details), if he wishes to know more about the Product before purchasing it.In that case,the Catalog, which may store limited information about the Product (probably its id!!) may invoke Catalog.getProduct(id) to get the Product object for more informational details upon request from the Customer.
The Product object would the final judge to decide which methods it will allow the client to invoke - it will make only those methods public.
In short, I believe getProducts() emphasizes on Catalog containing the Products and getProduct(id) emphasizes on the Catalog not having complete Product details in it.Hence, it is requesting for some more information from other classes.
Please let me know your views on this.
Also kindly let me know if we can assume "low coupling leads to maintaining encapsulation" and "high coupling breaks encapsulation".
Thanks in advance,
Sandeep
[This message has been edited by Desai Sandeep (edited May 23, 2001).]
 
Dave Thomas
Author
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Let's say I'm a real, paper catalog. I have pictures, descriptions, and prices. If a user wants to find out how much something costs, they ask the catalog:
catalog.getPriceOf(item_id);
This seems reasonable; knowing prices is part of what a catalog does. Take this approach, and you have the best of both worlds: no particular coupling at all.
Now, you might argue that this couples a Catalog and a Product. I'd disagree. Part of the Catalog's job is to know where to get prices. It may ask a product in a list of products it contains. It may go over the wire to a CORBA server somewhere. It may guess We don't much care. But to the extent that the Catalog is responsible, it makes the calls it needs to make. That's not coupling, it's a necessity.
So, I come back to previous answer: I probably wouldn't do it either way.

Then there's your encapsulation question:
Also kindly let me know if we can say "low coupling leads to maintaining encapsulation" and "high coupling breaks encapsulation"


If by encapsulation you mean the use of attribute accessors, I'd say no, we can't say this. In fact the two are largely causally unrelated.
Accessors let you decouple the internal implementation of an object by giving you the freedom to change the representation of your object's state without affecting your external interace. However, on a system-wide basis, this has no impact on the coupling of the system as a whole: you can chose to break Demeter by providing access to an object via an accessor, or by providing access via a method call. The effect is the same. Using accessors for encapsulation as you describe will make your systems more flexible. Designing your interfaces well will make them more decoupled.

Regards
Dave
 
Desai Sandeep
Ranch Hand
Posts: 1157
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Dave,
This is what I have understood from your posts.Please let me know, if I got it right this time .
A good design would be one in which the Customer would be able to request only the information that the Catalog exposes about the Product.We have to assume that the Customer is not aware of the Product object.Catalog is the only interface that the Customer would know of.
The methods that the Catalog expose could be implemented in a way calling/invoking the methods of the Product's class.Since these methods are the behaviour which the Catalog exposes to the client, invoking the Product methods would not mean high coupling.
In the problem, any of the getters would give the whole object to the Customer - The Customer may do anything (God knows what - This is what Junilu said, when he was explaining the same thing to me.He is correct ) with it.Infact this means the Customer would come to know about a Product object -this is exactly what one needs to avoid - just give specific details to the Customer which Catlog exposes, not the Product object as a whole - Is that correct?


Originally posted by Dave Thomas:
Designing your interfaces well will make them more decoupled.


In the problem context,if the Catalog is exposing the necessary information of the Product, ask "why would you want to get the Product object" - Hence do not use getProducts() or getProduct(id) method; instead use methods like getProductPrice(id).This will ensure less coupling between 2 classes.


Originally posted by Dave Thomas:
Using accessors for encapsulation as you describe will make your systems more flexible.


For the attributes of the Product, which the Catalog exposes, the Product getters may hide the internal details or show the details in a manner in which customer may desire.For example, internal representation of price could be "100 USD" but to the Customer getPrice() may reveal "Hundred Dollars".In this case encapsulation is maintained by the accessor.
Am not very clear on this:
How does getProducts() and getProduct(id) break encapsulation?
Thanks a lot for the information.
Regards,
Sandeep

 
Dave Thomas
Author
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Desai Sandeep:
just give specific details to the Customer which Catlog exposes, not the Product object as a whole - Is that correct?


Yes, that's what I'm advocating.

Am not very clear on this: How does getProducts() and getProduct(id) break encapsulation?


Take Booch's definition of encapsulation: "Encapsulation is the process of hiding all of the details of an object that do not contribute to its essential characteristics." If we agree that a Catalog is free to implement things such as pricing in any manner that it sees fit, and indeed is responsible for pricing, then exposing the fact that it implements this pricing using Product objects breaks encapsulation. We don't need to know how it calculates a price.
If instead you don't mind increasing coupling by exporting the Product object, then the issue changes. Now your Catalog has a very muddy purpose: what exactly is it adding to the mix? Is it simply a collection? If so, then a getProduct(id) method doesn't break encapsulation: in fact it becomes an essential characteristic of the class.
So again it all comes back to the context in which you make the decision. The first option (catalog.getPrice(id)) is the most flexible, as it reduces coupling and is nicely encapsulated. The second option may well be adequate is a catalog is indeed just a collection. However, I'd worry about it's future flexibility.
The original question has a third option: catalog.getproducts(). In light of the arguments above, I'm thinking that there are no circumstances in which this would be a good way to go.
But, this is all just me pontificating. Tell me what you think. What factors do you consider when making these kinds of decision? Have you experience of this kind of issue causing problems in real life systems?

Dave

 
Desai Sandeep
Ranch Hand
Posts: 1157
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Dave,
Wow!!This is a great piece of info.
The Booch's definition definitely suggests, if the Catalog is handling/maintaining the details it wishes to expose to the Customer, the Customer should not be able to call methods on the Product Object.If he does so, he would by-pass the Catalog method implementations (and hence its internal representation) by invoking the Product methods directly - This is a threat to Catalog's encapsulation and it happens in both the designs - getProducts() and getProduct(id).
If the coupling is increased by exporting the Product object, then encapsulation would depend on the implemention of the method in question.If the method plays around with its own internal representation then encapsulation is maintained.On the other hand, if it delegates call to one of its helper classes (which may return a Product reference other that what the internal representation - Collection of Catalog stores!!), then encapsulation is broken.However, since coupling is increased in this case, one may face problems of flexibility.
Got it, Dave!! - "Coupling decides Flexibility!!"


Originally posted by Dave Thomas:
The original question has a third option: catalog.getproducts(). In light if the arguments above, I'm thinking that there are no circumstances in which this would be a good way to go.
But, this is all just me pontificating. Tell me what you think. What factors do you consider when making these kinds of decision? Have you experience of this kind of issue causing problems in real life systems?


I agree with you - Catalog.getProducts() really doesnot take us anywhere - It is a case of high coupling and encapsulation would be also broken since the Customer may play around with that Object and can easily make the Catalog's internal representation of a particular product out of sync.
Yes, I had faced a similar problem (long time back, though ), while designing an AddressBook Application for the intranet project for my firm.I had an Addressbook which stores addresses.Since AddressBook contains addresses, I had to take care that the addresses always stays in sync with what is being stored in the AddressBook's internal representation - a collection (java.util.List) of addresses.So the point was I could never provide a method, getAddresses() in the AddressBook class.Instead, I had to provide a method getAddressBook() on Singleton Pattern.All the clients would get only a single instance of AddressBook through this method.Any changes to the addresses in the AddressBook would be in its internal representation only using methods like updateAddress(String firstName) on the AddressBook's instance.The implementation of this method would give a call to the helper (I called it XMLManager, which writes the changes in the XML file) class to actually synchronize the data with the XML file.Hence, interface for my JSP/Servlet clients was always AddressBook.They were never aware of the source of data.This gave me an advantage of low coupling and high flexibility.Later on, we decided to switch the data from the XML file to Oracle DB.We realized no change was required for the clients.Also encapsulation of AddressBook was maintained, as we never were talking to Addresses directly!!
Dave, your posts has been extremely insightful for me.Hope you won't mind if I trouble you more through emails .Anyway, I still have one more day to brainstorm and come out with some more interesting questions.The following is one such question
What can we say about doSomeThingWith(Product) w.r.t. encapsulation and coupling?
If I am correct, again the implementation is going to decide if the encapsulation is maintained or broken.But can we say for sure that this is a case of high coupling or this also depends on the implementation of the method?What I understood is since it is necessity for the Catalog to collaborate with the Product, it should not be the case of high coupling.However, if the Catalog contains the Products, then collaboration with Product would certainly mean high coupling - Your views, please!!
Junilu, would be happy that I am leaning towards his answer B.I am equally happy that I am able to pin the answer down with some reasoning.I would be adding a last post to the Coupling Question to give a logical end to it.It will just contain a reference to this excellent post of yours .

Thanks,
Sandeep
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Desai Sandeep:

Junilu, would be happy that I am leaning towards his answer B.I am equally happy that I am able to pin the answer down with some reasoning.I would be adding a last post to the Coupling Question to give a logical end to it.It will just contain a reference to this excellent post of yours.


I'm just glad we can put this issue to rest At the same time, I can now see the point of view that you were arguing from before. Now, if the question had stated who would be calling getProducts() and getProduct(id), we probably would have agreed a whole lot sooner. That is, if these methods were private or even protected, then I would say that it was acceptable since LoD would probably not be broken. If the methods were public, then I would seriously reconsider the design depending on how the Product/s were used by the caller keeping LoD in mind.
wrt doSomethingWith(Product), again I submit that LoD would probably not be broken there because Product is passed as a parameter and LoD allows objects to invoke the methods of other objects passed as parameters. There is still coupling but it is not brittle.
Junilu

[This message has been edited by JUNILU LACAR (edited May 24, 2001).]
 
Desai Sandeep
Ranch Hand
Posts: 1157
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Junilu,
I just happened to read the JavaWorld article (Encapsulation is not InformationHiding).I suppose, you referred to this article sometime back in one of your posts.It is a great article .
It helped me solve the mystery of Catalog.doSomethingwith(Product).This quote was helpful:


From JavaWorld May 2001 - Encapsulation is not information hiding
[..] using append(Position) rather than setPosition(int,Position) further isolates design decision regarding the internal collection being used.



From this quote I infer Catalog.doSomethingWith(Product) would be a better design as:

  1. We are isolating the internal representation of the Catalog from the client, i.e. how the Product is stored internally in the Catalog is not known to the client.This is Information hiding, which Encapsulation facilitates.
  2. Coupling may not be brittle, as this may be one of the necessary things which the Catalog needs to do.
  3. As you correctly mentioned, Law of Demeter (LoD) allows calling methods on objects passed as parameters, and this principle is based on low coupling.

  4. This article condemns getProducts() on the following Information hiding rule:


    From JavaWorld May 2001 - Encapsulation is not information hiding
    Information hiding rule 3 : Don't expose a class internal Structure
    Clients should remain isolated from the design decisions driving the selection of internal class structure.For example, a client should not know whether a primitive array or an ArrayList is used to maintain an internal collection of objects.Internal structure is particularly apparent through the use of method names like getDataArray() or getTreeMap()


    getProducts() would certainly expose the design decision to the client - which is what we have to avoid!!
    This article condemns getProduct(id) on the following Information hiding rule:


    From JavaWorld May 2001 - Encapsulation is not information hiding
    Information hiding rule 4 : Don't expose implementation details of the class
    Don't allow clients to know or invisibly affect a class's implementation details.For example, a client should not be able to alter an internal calculation's result by changing the state of the objects used in that supposedly hidden calculation


    The customer getting the Product instance and making it out of sync, with what is stored in the Catalog internal representation is not desirable.Give the responsibility only to the Catalog to maintain the Product Object - That should be our principle.

    I think I got the following wrong for getProduct(id)


    Originally posted by Desai Sandeep:
    If the method plays around with its own internal representation then encapsulation is maintained.On the other hand, if it delegates call to one of its helper classes (which may return a Product reference other than what the internal representation stores - Collection of Products!!), then encapsulation is broken.


    It should be :
    If the method plays around with its own internal representation then to maintain encapsulation/information hiding, the method has to return a new reference of the Product, so that the internal representation of the Catalog is not disturbed.On the other hand, if it delegates call to one of its helper classes (which may return a Product reference other than what the internal representation stores - Collection of Products!!), then encapsulation is not broken.The reason being the same - The client would never get an opportunity to change the Catalog's internal representation.Yes, coupling would be brittle, as the client gets to know about the Product object.
    Thanks a lot,
    Sandeep
    [This message has been edited by Desai Sandeep (edited May 24, 2001).]
 
Story like this gets better after being told a few times. Or maybe it's just a tiny ad:
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic