DISQUS

Dan Manges's Blog: Dan Manges - Misunderstanding the Law of Demeter

  • Jake Scruggs · 2 years ago
    Nice article with clear examples -- well done.
  • David Mathers · 2 years ago
    Excellent. I just learned of the Law of Demeter a few days ago via

    http://blog.jayfields.com/2006/05/law-of-demete...

    and thought "this is crazy talk." Thanks to your clear explanation I now see that the Law is useful and that the other example is a superficial misrepresentation.

    I think Jay Fields needs to read your blog.
  • Dave · 2 years ago
    Smashing summary, thanks.
  • Sam · 2 years ago
    Thanks for the explanation.

    What if I want nil returned when customer isn't defined? Eg.

    def customer_name
    @order.customer.name rescue nil
    end

    It looks like def_instance_delegator raises a Kernel exception when object doesn't exist. Is there a way to get the above behavior with Forwardable?
  • Joe · 1 year ago
    Great article on very important nuance when dealing with the LOD.
    ~~"there is a better solution that I will blog about later"
    Would like to see this.
  • Bryan Ray · 1 year ago
    Excellent post ... Thanks for the read, Dan.
  • Pramod · 1 year ago
    The best article I ever read on delegation... too good...
    Thanks a ton!!
  • Mark Needham · 1 year ago
    Hey, I really like this post - it's definitely the best explanation of the Law of Demeter I've read. Just found this paper on it too which seems pretty cool -> http://www.ccs.neu.edu/research/demeter/demeter...
  • Jaime Bellmyer · 1 year ago
    I was having trouble wrapping my head around the "why" to the Law of Demeter at first. I'll post my thoughts here in case they help someone else.

    Bottom line: as soon as you refer to self.customer.wallet, you have forced the paperboy to know and abide by the inner workings of the customer. What if you want to change that someday? Maybe our customer wants to write a check. Heck, maybe he wants to check his wallet first, and write a check if he doesn't have the payment in cash!

    Coding customer.pay(amount) means never caring how the customer will choose to pay in the future. You access the customer interface (the pay method) and go about your happy life. This code is tons more maintainable, because changing how a customer pays doesn't affect any other models that require payment.
  • Saurabh Hirani · 1 year ago
    Thanks for bringing out the idea that it is the behaviour and not the attribute which makes the difference during application of LOD.

    However, if I have an Order class whose purpose is to show the orders of a particular customer, can I not write something like:

    order.show(customer)

    show method of the class order takes a customer instance and as we can access customer attr and behaviour through show adhering by LOD is that not right?
  • Saurabh Hirani · 1 year ago
    How does the LOD hold when you are accessing the same object generated by the passed in object to the function:

    example

    Function in python to delete a node after a particular node in a linklist:

    def delafter(self, delafter_node):
    # delete the node after delafter_node
    # delafter_node is an instance of class node - hence by LOD we can call
    # delafter_node.get_next() which gives us the next node
    node2del = delafter_node.get_next()
    # node2del which is also the same type as that of delafter_node does not qualify for direct
    # call to node's get_next. Hence it calls we local proxy function - get_nextnode
    delafter_node.set_next(self.get_nextnode(node2del))
    info = self.get_nodeinfo(node2del)
    return info

    Now we have 2 objects - delafter_node and node2del - instance of the same class but for one we use a proxy function and for another we use the function of the class. Is this a bad practice? Hampers the readability.
  • Antti Tarvainen · 11 months ago
    I don't think the delegation example works. You would need to define method :cash= in addition to :cash in the Customer model.
  • bartiaco · 9 months ago
    @Antti

    attr_accessor defines both the setter and the getter method.
  • Gary · 4 months ago
    I think that the key is in the nature of the relationship between the two entities. If the Customer 'owns' the Wallet, then it is right and proper that the Paperboy does not help himself. The law of Demeter applies. In this case, perhaps the Customer should not expose the Wallet - he may keep his cash in his pocket. However, if the Customer, merely references the Wallet, and the Wallet is a stand alone entity, then there is no reason why the paperboy should not help himself. (As the wallet is stand alone, the Customer has no control over what heppens to the Wallet.) In this case the code simply becomes (using c#, sorry!)
    Wallet wallet = Customer.Wallet;
    wallet.cash ... etc.
    The law of Demeter is avoided and the intention is clear. Howevver, Customer.Wallet.cash is still a tempting shortcut.


    Unfortunately, most languages do not distinguish between ownership and referencing. However, it is an important conceptual distinction to make.
  • Ilya Paripsa · 3 months ago
    Great explanation & examples. Nice work!
  • Emerson Macedo · 1 month ago
    A DRY way to apply Law of Demeter with demeter gem

    http://github.com/emerleite/demeter
    http://gemcutter.org/gems/demeter
  • emerleite · 1 month ago
    A DRY way to apply Law of Demeter with demeter gem

    http://github.com/emerleite/demeter
    http://gemcutter.org/gems/demeter