Imagine you go to a store to buy an apple. You wouldn’t hand the cashier your entire wallet, let them open it, dig around for a $5 bill, take it, and hand the wallet back to you. That’s a huge violation of your privacy! Instead, you take the $5 out yourself and hand it to the cashier.
The Law of Demeter says objects should act the same way. A class should only talk to its immediate friends, and shouldn’t reach “through” a friend to talk to a stranger.
In code, this usually looks like method chaining. If you do $a->getB()->getC()->doSomething(), you are violating the Law of Demeter.
A method is only allowed to call methods on:
$this (itself)If you call a method on anything else, it’s a violation!
Here, the OrderProcessor reaches through the Order to talk to the Customer, and then reaches through the Customer to talk to the Wallet.
class OrderProcessor {
public function process(Order $order): void {
// VIOLATION! We asked the Order for the Customer,
// then asked the Customer for the Wallet!
$wallet = $order->getCustomer()->getWallet();
if ($wallet->getBalance() > $order->getTotal()) {
$wallet->deduct($order->getTotal());
}
}
}
Instead of digging through the Order’s internal data, we should just ask the Order to do the work for us!
class OrderProcessor {
public function process(Order $order): void {
// GOOD! We only talk directly to the $order object,
// which was passed in as a parameter.
if ($order->canBePaid()) {
$order->pay();
}
}
}
There is no configurable threshold for this rule. Any chained method call that violates the Law of Demeter will be flagged.
If Phanalist flags your code for the Law of Demeter, it means you have too many dots or arrows in a row (e.g. $a->b()->c()). Tell your immediate friend what you want done, don’t ask them for their friends!