Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Love of Demeter

Love of Demeter

What is Law of Demeter? Should we always respect it? What's the best recipe for a pizza? This presentation answers two of these three questions.

nbartlomiej

June 25, 2012
Tweet

More Decks by nbartlomiej

Other Decks in Programming

Transcript

  1. 1 class Wallet 2 include Mongoid::Document 3 4 5 6

    7 8 9 10 11 12 13 14 15 16 17 end
  2. 1 class Wallet 2 include Mongoid::Document 3 4 belongs_to :customer

    5 field :cash, type: Integer 6 7 8 9 10 11 12 13 14 15 16 17 end
  3. 1 class Wallet 2 include Mongoid::Document 3 4 belongs_to :customer

    5 field :cash, type: Integer 6 7 def store(amount) 8 update_attribute(:cash, cash + amount) 9 end 10 11 def take(amount) 12 if cash >= amount 13 update_attribute(:cash, cash - amount) 14 end 15 end 16 17 end
  4. 1 class Customer 2 include Mongoid::Document 3 4 has_one :wallet

    5 end 6 7 8 9 class PizzaMan 10 def collect_money(customer, amount) 11 # pending 12 end 13 end 14
  5. 1 class Customer 2 include Mongoid::Document 3 4 has_one :wallet

    5 end 6 7 8 9 class PizzaMan 10 def collect_money(customer, amount) 11 customer.wallet.take(amount) 12 end 13 end 14
  6. 1 class Customer 2 include Mongoid::Document 3 4 has_one :wallet

    5 6 def pay(amount) 7 wallet.take(amount) 8 end 9 end 10 11 12 13 14 15 16
  7. 1 class Customer 2 include Mongoid::Document 3 4 has_one :wallet

    5 6 def pay(amount) 7 wallet.take(amount) 8 end 9 end 10 11 12 class PizzaMan 13 def collect_money(customer, amount) 14 customer.pay(amount) 15 end 16 end
  8. In method, send messages only to: Self. Self method results,

    Self collection elements. Method parameters. Newly created objects.
  9. 1 class PizzaMan 2 @pizzas = [] 3 4 def

    tweet 5 Tweet.new("Tomatoes out, using jalapeños.") 6 end 7 8 def collect_money(customer, amount) 9 10 11 12 13 14 end 15 16 end
  10. 1 class PizzaMan 2 @pizzas = [] 3 4 def

    tweet 5 Tweet.new("Tomatoes out, using jalapeños.") 6 end 7 8 def collect_money(customer, amount) 9 tweet 10 11 12 13 14 end 15 16 end
  11. 1 class PizzaMan 2 @pizzas = [] 3 4 def

    tweet 5 Tweet.new("Tomatoes out, using jalapeños.") 6 end 7 8 def collect_money(customer, amount) 9 10 tweet.send! 11 12 13 14 end 15 16 end
  12. 1 class PizzaMan 2 @pizzas = [] 3 4 def

    tweet 5 Tweet.new("Tomatoes out, using jalapeños.") 6 end 7 8 def collect_money(customer, amount) 9 10 11 @pizzas.first.take_slice 12 13 14 end 15 16 end
  13. 1 class PizzaMan 2 @pizzas = [] 3 4 def

    tweet 5 Tweet.new("Tomatoes out, using jalapeños.") 6 end 7 8 def collect_money(customer, amount) 9 10 11 12 customer.pay(amount) 13 14 end 15 16 end
  14. 1 class PizzaMan 2 @pizzas = [] 3 4 def

    tweet 5 Tweet.new("Tomatoes out, using jalapeños.") 6 end 7 8 def collect_money(customer, amount) 9 10 11 12 13 Pizza.new(:marinara).add(:jalapeno) 14 end 15 16 end
  15. 1 2 3 4 5 6 7 8 9 10

    def collect_money(customer, amount) 11 customer.wallet.take(amount) 12 end 13 14
  16. 1 class Customer 2 include Mongoid::Document 3 4 has_one :wallet

    5 6 delegate :cash, to: :wallet, prefix: true 7 8 def wallet_cash=(amount) 9 wallet.cash = amount 10 wallet.save 11 end 12 end 13 14 15 16 17 18 19 20 21 22
  17. 1 class Customer 2 include Mongoid::Document 3 4 has_one :wallet

    5 6 delegate :cash, to: :wallet, prefix: true 7 8 def wallet_cash=(amount) 9 wallet.cash = amount 10 wallet.save 11 end 12 end 13 14 class PizzaMan 15 def collect_money(customer, amount) 16 if customer.wallet_cash >= amount 17 customer.wallet_cash -= amount 18 else 19 # See you later. 20 end 21 end 22 end
  18. #2 You should not (and cannot) Decouple all the things.

    source: http://hyperboleandahalf.blogspot.com/ 2010/06/this-is-why-ill-never-be-adult.html
  19. #2

  20. 1 def chains 2 order.customer.profile.location.country = "PL" 3 end 4

    5 def temp_variables 6 customer = customer.order 7 profile = customer.profile 8 location = profile.location 9 location.country = "PL" 10 end
  21. 1 def chains 2 order.customer.profile.location.country = "PL" 3 end 4

    5 def temp_variables 6 customer = customer.order 7 profile = customer.profile 8 location = profile.location 9 location.country = "PL" 10 end Refactor.
  22. 1 <div> 2 <%= customer.profile.avatar %> 3 <%= customer.profile.country %>

    4 <%= customer.profile.address %> 5 <%= customer.profile.phone %> 6 </div>
  23. 1 <div> 2 <%= customer.profile.avatar %> 3 <%= customer.profile.country %>

    4 <%= customer.profile.address %> 5 <%= customer.profile.phone %> 6 </div> Delegating? Partial?
  24. 1 class PizzaMan 2 def collect_money(customer, amount) 3 if customer.pays_with_credit_card?

    4 collect_from_credit_card(customer.credit_card, amount) 5 else 6 collect_cash(customer, amount) 7 end 8 end 9 10 def collect_cash(customer, amount) 11 # ... 12 end 13 14 def collect_from_credit_card(credit_card, amount) 15 # ... 16 end 17 end
  25. 1 class PizzaMan 2 def collect_money(customer, amount) 3 if customer.pays_with_credit_card?

    4 collect_from_credit_card(customer.credit_card, amount) 5 else 6 collect_cash(customer, amount) 7 end 8 end 9 10 def collect_cash(customer, amount) 11 # ... 12 end 13 14 def collect_from_credit_card(credit_card, amount) 15 # ... 16 end 17 end Use Structural Dependency?