Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # This example is from Dan Manges's blog, dcmanges.com
- class Wallet ; attr_accessor :cash ; end
- class Customer
- # assume Customer's initialize() method sets the wallet attribute
- # to be a wallet instance full of money
- attr_accessor :wallet
- end
- class Paperboy
- def collect_money(customer, amount)
- # VIOLATION OF DEMETER: Paperboy may know about Customer, but
- # we're exposing things about implementation of Wallet too. Also,
- # we're handling the problem of "not enough cash" in Paperboy,
- # not in Wallet (where it arguably belongs)
- if customer.wallet.cash < amount
- raise InsufficientFundsError
- else
- customer.wallet.cash -= due_amount
- @collected_amount += due_amount
- end
- end
- end
- # Imagine testing the above code:
- describe "collecting money" do
- it "should raise error if customer doesn't have enough money" do
- # "Mock trainwreck" is a warning of a Demeter violation
- wallet = mock('wallet', :cash => 5.00)
- customer = mock('customer', :wallet => wallet)
- lambda { @paperboy.collect(customer, 10.00) }.should raise_error(...)
- end
- end
- # This is better: we *delegate* the cash attribute via Customer.
- # Now Paperboy only "talks to" Customer.
- class Customer
- def cash
- self.wallet.cash
- end
- end
- class Paperboy
- def collect_money(amount)
- if customer.cash >= amount
- customer.cash -= due_amount
- @collected_amount += due_amount
- else
- raise InsufficientFundsError
- end
- end
- end
- # This is the best, because the *behavior* is delegated. The implementation
- # of the behavior can now be changed without affecting Paperboy.
- class Wallet
- attr_reader :cash # no longer attr_accessor!
- def withdraw(amount)
- raise InsufficientFundsError if amount > cash
- cash -= amount
- amount
- end
- end
- class Customer
- # behavior delegation
- def pay(amount)
- wallet.withdraw(amount)
- end
- end
- class Paperboy
- def collect_money(customer, due_amount)
- @collected_amount += customer.pay(due_amount)
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement