Law of Demeter (Encapsulation)
By Karl Lieberherr (NEU, Boston), 1987 Examples here by David Bock
(www.javaguy.org)
Customer Class
private String firstName;
private String lastName;
private Wallet myWallet;
public Wallet getWallet() { return myWallet;
}
Class Wallet
private float value;
public float getTotalMoney() { return value;}
public void setTotalMoney(float newValue) {value = newValue;}
public void addMoney(float deposit) {value += deposit;}
public void subtractMoney(float debit)
{value -= debit;}
Paying the Paperboy
// some method in the Paperboy class payment = 2.0;
Wallet theWallet = myCustomer.getWALLET();
if (theWallet.getTotalMoney() > payment) {theWallet.subtractMoney(payment);
} else {
// … come back later to get money …
What’s wrong?
• Do you hand over your wallet to pay?
• Paperboy “exposed to more information than needed” (total amount, or credit cards, etc, in the wallet as well)
• Changes in the Wallet class: case of theft:
victim.setWallet(null)
– Reasonable
– But breaks “paying the paperboy” (and all other methods relying on proper wallets)
– Need lots of changes in several classes
Better Customer class
public float getPayment(float bill) { if (myWallet != null) {
if(myWallet.getTotalMoney() > bill) {
myWallet.subtractMoney(payment);
return payment;
} }
throw new OutOfMoneyException();
Or even better
public float getPayment(float bill) { Wallet theWallet = getWallet();
if (theWallet != null) {
if(theWallet.getTotalMoney() > bill) {
theWallet.subtractMoney(payment);
return payment;
} }
throw new OutOfMoneyException();
Paperboy payment code
// some method in the Paperboy class float payment = 2.0;
float paidAmount = 0.0;
try {
paidAmount = myCustomer.getPayment(payment);
} catch (OutOfMoneyException oome) { // …
}
Why better
• More complex, but
• Better model of the “real world”
• Wallet class changes only effect
Customer class, but not the Paperboy
• Can modify getPayment method easily
Drawbacks
• More (short) methods, delegation
• Efficiency?
• Not always appropriate (e.g. see
Drivers’s license example in the paper)
Law of Demeter
• “do not talk to strangers”
• A method should only invoke methods
– Of itself
– Its parameters
– Any object it creates
– Any direct component object
Indications of bad design
• Chained “get” statements
– Object.getX().getY().getTheValue();
– Person.getWallet().getDriversLicense();
• Lots of local/temporary objects:
– Wallet theWallet = person.getWallet();
– License = theWallet.getDriversLicense();
• Importing many classes:
– import java.util.*; is bad, make explicit, and see how many classes you import …