Law of Demeter
Talk to your immediate friends. Don't talk to strangers you only met through a friend.
A method may call operations on itself, on its own fields, on anything handed to it as a parameter, and on anything it creates on the spot. It may not call an operation on whatever some other call happened to hand back - that return value is a stranger, and reaching past it into a third object's business is the "train wreck" this principle is named for.
Why it exists
customer.getWallet().getCash().subtract(amount) compiles, works today, and quietly commits
OrderService to three facts it has no business knowing: that a Customer has a Wallet,
that a Wallet holds Cash, and that Cash supports subtract(). Change any one of those
three facts - Wallet switches from cash to a card balance, say - and this unrelated service
breaks, even though nobody touched OrderService on purpose. The chain of dots is a chain of
hidden dependencies, one per dot past the first.
A train wreck, and its fix
The fix is never "add more getters so the caller can keep reaching." It's the opposite: push the behavior down to whichever object already holds the data, and let the caller ask for the result instead of the parts. This is sometimes called "tell, don't ask" - tell the wallet to pay, don't ask it for its cash so you can subtract from it yourself.
Try it yourself: report.getCustomer().getAddress().getCity().toUpperCase() shows up in a
report footer. Rewrite it so report has exactly one thing to ask for, and decide which
object - Customer or Address - should own the formatting.
The cost of overapplying it
Taken too literally, Law of Demeter turns into "wrap every getter in a pass-through method,"
and a class ends up with a dozen one-line delegating methods that add a hop without adding
any actual behavior - the "middle-man" anti-pattern. The principle is about hiding
structure the caller shouldn't depend on, not about banning every method that happens to
return an object. order.getLineItems() returning a plain list for a caller to iterate is
fine; the violation is specifically reaching through that list into a third object's
internals as if you owned them.
How it relates to its neighbours
The train wreck is a coupling problem wearing a more specific name. A chain of four dots is four separate objects that a change anywhere can break - exactly the failure Coupling and Cohesion warns about, caught in one particular, grep-able shape: a line with more than one dot past the first.
Where you'll see it in the pattern catalog
Facade exists partly to give callers a Law-of-Demeter-friendly front door instead of reaching through a subsystem's internals to assemble a result themselves. Mediator solves the same family of problem one level up: instead of components chaining calls through each other to coordinate, they all talk to one hub, and no chain of dots ever forms in the first place.
Check yourself
customer.getWallet().getCash().subtract(amount) compiles fine and works today. What did it actually violate, and why does it matter later?