I am reading a book called Rails AntiPatterns and they talk about using delegation to to avoid breaking the Law of Demeter. Here is their prime example:
They believe that calling something like this in the controller is bad (and I agree)
@street = @invoice.customer.address.street
Their proposed solution is to do the following:
class Customer has_one :address belongs_to :invoice def street address.street end end class Invoice has_one :customer def customer_street customer.street end end @street = @invoice.customer_street
They are stating that since you only use one dot, you are not breaking the Law of Demeter here. I think this is incorrect, because you are still going through customer to go through address to get the invoice's street. I primarily got this idea from a blog post I read:
In the blog post the prime example is
class Wallet attr_accessor :cash end class Customer has_one :wallet # attribute delegation def cash @wallet.cash end end class Paperboy def collect_money(customer, due_amount) if customer.cash < due_ammount raise InsufficientFundsError else customer.cash -= due_amount @collected_amount += due_amount end end end
The blog post states that although there is only one dot
customer.cash instead of
customer.wallet.cash, this code still violates the Law of Demeter.
Now in the Paperboy collect_money method, we don't have two dots, we just have one in "customer.cash". Has this delegation solved our problem? Not at all. If we look at the behavior, a paperboy is still reaching directly into a customer's wallet to get cash out.
I completely understand and agree that this is still a violation and I need to create a method in
Wallet called withdraw that handles the payment for me and that I should call that method inside the
Customer class. What I don't get is that according to this process, my first example still violates the Law of Demeter because
Invoice is still reaching directly into
Customer to get the street.
Can somebody help me clear the confusion. I have been searching for the past 2 days trying to let this topic sink in, but it is still confusing.