The Law of Demeter, or Principle of Least Knowledge is a fairly simple design pattern, which, simply put means that an object should only talk to it’s immediate “friends”
The law states that a method M of and object O may only invoke the methods of the following kind:
1. a method on O itself
2. any parameters passed to M
3. any objects instantiated within M
4. any direct components of O
The classic example coined by David Bock used a Paperboy (one object) delivering a paper, then extracting money from a Customer’s (another object) Wallet (and another):
self.money += customer.wallet.take_out(10)
end
end
In the “real world” the Paperboy would ask the customer for the money who would then take it out for them, rather then the Paperboy reaching into the customer’s back pocket and getting it for themself.
Really we want something as follows:
self.money += customer.get_payment(10)
end
end
wallet.take_out(10)
end
end
This may all seem trivial and a waste of time, but what happens if some Customers want to pay by cheque? Those decisions should have an impact on the Paperboy, otherwise we end up with:
if customer.pay_by_cash?
self.money += customer.wallet.take_out(10)
elsif customer.pay_by_cheque?
self.money += customer.cheque_book.write_cheque(10)
end
end
end
Where as it makes more sense for the change to be contained within the Customer:
self.money += customer.get_payment(10)
end
end
if pay_by_cash?
wallet.take_out(10)
elsif pay_by_cheque?
cheque_book.write_cheque(10)
end
end
end
So what does this have to do with Rails and the delegate method? The delegate method adds a quick and simple way of following the Law of Demeter without having to do very much at all.
belongs_to :customer
end
has_many :orders
has_one :credit_card
has_one :bank_account
if pay_by_card?
credit_card
elsif pay_by_account?
bank_account
end
end
end
belongs_to :customer
end
belongs_to :customer
end
This setup means to get an Order’s payment we would have to say:
@order.customer.payment_method.withdraw(amount)
But if we simply change our objects as such:
belongs_to :customer
delegate :withdraw_payment, :to => :customer
end
has_many :orders
has_one :credit_card
has_one :bank_account
if pay_by_card?
credit_card.withdraw(amount)
elsif pay_by_account?
bank_account.withdraw(amount)
end
end
end
Now all we have to say is:
@order.withdraw_payment(amount)
So at any time, the details of how a payment is to be decided can be contained with the Customer. This is of course a simplistic example, but hopefully explains how you chould be using this handy feature.



Broken Window Policy of Programming
There comes a point in every software projects life where everything just feels wrong. No one wants to touch the code as it stinks and everyone working on the project just feels demotivated and would rather just go home then have to do anything more on it. On projects like this, when it comes to adding new features or bits of code, because everything else is such a mess, the changes are just hacked in rather than being properly thought out and coded up well.
We’ve all been there and the frustrating thing is that our opinion of the project, from good to bad, seems to happens over night. If you sit down and think back, you can probably pick out all the things that were just shoved in that eventually led to the project becoming a mess, but at the time we never chose to do anything about. It’s almost always a case of deferring better solutions or a round of refactoring to some point in the future. “I’ll knock this up now and come back to it later.”. The problem is that later never comes. This is the essence of technical debt. You may only go into debt by a fraction, but do it a few times and eventually all those fractions add up. Until one day when you go to check your balance, you find yourself swimming in the middle of the ocean with no land in sight.
Implementing a broken window policy can go a huge way towards keeping a project healthy. If there is a broken window (bad code) fix it as-soon-as-possible. It doesn’t have to be that instant (although if you can, you should), but fix it. Part of the policy also means trying not to break windows yourself. Write the best code you can, as often as you can. Set the benchmark of quality for the rest of the team, even if they don’t follow suit. The danger is that many people are very “me too” about things. “Well if such-and-such can do it like this, then so can I *hack* *hack* *hack*”.
Of course we all write crap from time to time. TBH most of the stuff I write is crap. But I honestly feel more motivated to work on code that’s been loved and looked after, rather than something that’s hanging together by a thread.