Note that there are some explanatory texts on larger screens.

plurals
  1. POHow do the Law of Demeter and composition with collections work together?
    primarykey
    data
    text
    <p>I have read nearly all of the questions tagged Law-of-Demeter. My specific question is not answered in any of these other questions, though it is very similar. Mainly my question is when you have an object with layers of composition, but the need to retrieve property values from the various objects, how do you achieve this and why take one approach over another?</p> <p>Let's say you have a pretty standard object composed of other objects, like this:</p> <pre><code>public class Customer { private String name; private ContactInfo primaryAddress; private ContactInfo workAddress; private Interests hobbies; //Etc... public getPrimaryAddress() { return primaryAddress; } public getWorkAddress() { return workAddress; } public getHobbies() { return hobbies; } //Etc... } private ContactInfo { private String phoneNumber; private String emailAddress; //Etc... public getPhoneNumber() { return phoneNumber; } public getEmailAddress() { return emailAddress; } //Etc... } private Interests { private List listOfInterests; } </code></pre> <p>The following would both violate the Law of Demeter:</p> <pre><code>System.out.println("Phone: " + customer.getPrimaryAddress().getPhoneNumber()); System.out.println("Hobbies: " + customer.getHobbies().getListOfInterests().toString()); </code></pre> <p>This also would violate the Law of Demeter, I think (clarification?):</p> <pre><code>ContactInfo customerPrimaryAddress = customer.getPrimaryAddress(); System.out.println("Phone: " + customerPrimaryAddress.getPhoneNumber()); </code></pre> <p>So presumably, you would then add a "getPrimaryPhoneNumber()" method to Customer:</p> <pre><code>public getPrimaryPhoneNumber() { return primaryAddress.getPhoneNumber(); } </code></pre> <p>And then simply call: System.out.println("Phone: " + customer.getPrimaryPhoneNumber());</p> <p>But doing this over time seems like it would actually provide a lot of problems and work against the intention of the Law of Demeter. It makes the Customer class into a huge bag of getters and setters that has way too much knowledge about its own internal classes. For instance, it seems possible that the Customer object will one day have various addresses (not just a "primary" and a "work" address). Perhaps even the Customer class will simply have a List (or other collection) of ContactInfo objects rather than specific named ContactInfo objects. How do you continue following the Law of Demeter in that case? It would seem to defeat the purpose of the abstraction. For example, this seems reasonable in such a case where a Customer has a List of ContactInfo items:</p> <pre><code>Customer.getSomeParticularAddress(addressType).getPhoneNumber(); </code></pre> <p>This seems like it can get even crazier when you think about some people having a mobile phone and a landline phone, and then ContactInfo has to have a collection of phone numbers.</p> <pre><code>Customer.getSomeParticularAddress(addressType).getSomePhoneNumber(phoneType).getPhoneNumber(); </code></pre> <p>In which case, not only are we referring to objects within objects within objects, but we also have to know what the valid addressType's and phoneType's are. I can definitely see a problem with this, but I am not sure how to avoid it. Especially when whatever class is calling this, probably does know that they want to pull the "mobile" phone number for the "primary" address of the customer in question. </p> <p>How could this be refactored to comply with the Law of Demeter and why would that be good?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload