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

The Talking Objects: A Tale About Message-Oriented Programming

kurko
October 19, 2012

The Talking Objects: A Tale About Message-Oriented Programming

Object-Oriented Programming has made a long way. Tons of materials are available since the 80's about OO design, yet communities such as Rails continue reinventing the wheel, struggling to find the best approaches to objects' architecture.

In this presentation I will talk about how the Forwarding Pattern, used by every single developer, creates a Dictatorial culture between objects in most situations and how we can leverage the use of the Delegation pattern to create decoupled designs. I will also talk about how Integrated tests are bad and how to use Contract tests to guide us in the quest of building better designed components.

kurko

October 19, 2012
Tweet

More Decks by kurko

Other Decks in Programming

Transcript

  1. OOP in Theory • OOP is not about classes •

    OOP is about the messages they send and receive • Regarding Object B, Object A should only care if it understands a message, not what it does nor how it does it. • This leads to less coupling between objects and greater flexibility quinta-feira, 27 de dezembro de 12
  2. OOP in Practice • Points of views: yours & objects’.

    • Think in objects like if they were living things • Think in objects in terms of roles! (Picturing them like if they were people helps defining roles.) • Impersonate objects, speaking out loud: “hey you, Object B, give me the list of employees” • Impersonate object B: “should I be searching for employees? No, so delegate!” quinta-feira, 27 de dezembro de 12
  3. Person Pencil Pen Person “says”: “write()” Developer’s point of view:

    thinking about classes someone speaking someone else yet another person pay_me() Object’s point of view: thinking about messages quinta-feira, 27 de dezembro de 12
  4. Don Corleone Unlucky guy Unlucky guy Unlucky guy Pay($100, :tomorrow)

    Forwarding (not delegation) a) Due to how Don speaks, all unlucky guys have to act in a certain way. In real life, objects don’t have the same behaviors, leading to duplication between them to comply with Don. b) Therefore, new unlucky guys have to have the same behavior, therefore the code will have lower flexibility, therefore being hard to maintain. c) Don is determining how unlucky guy behaves d) Every class is just a methods repository, no life. Just Mafia. It’s just methods calling methods. Pretty functional. f) Don depends on unlucky guys, in other words, Abstraction depends on Implementation. quinta-feira, 27 de dezembro de 12
  5. Don Corleone Forgetful Meticulous How much? Credit card? Cash? Pay

    me Inverting Dependencies quinta-feira, 27 de dezembro de 12
  6. Don Corleone Forgetful Meticulous Arrogant How much? Credit card? Cash?

    Pay me Inverting Dependencies quinta-feira, 27 de dezembro de 12
  7. Don Corleone Forgetful Meticulous Arrogant How much? Credit card? Cash?

    Try again next week Pay me Inverting Dependencies quinta-feira, 27 de dezembro de 12
  8. Don Corleone Forgetful Meticulous Arrogant How much? Credit card? Cash?

    Try again next week Pay me # Don forgetful.pay(self) # Forgetful def pay(person) person.how_much(self) end quinta-feira, 27 de dezembro de 12
  9. Objects have implicit contracts between them They expect others to

    understand them quinta-feira, 27 de dezembro de 12
  10. Hacking our brains Examples of how developers think He thinks

    in terms of classes. He thinks store is a class and affiliate is a class. He should think, “I’m saying ‘affiliate_user’ to store.” The current object should say, “Hey store, give me your owner’s address” The current object shouldn’t know the store has an affiliate user. quinta-feira, 27 de dezembro de 12
  11. Hacking our brains Examples of how developers think He finds

    it obscure because he has no clue about object’s nature. He only cares about his own point of view, not the object’s point of view. He thinks putting everything in the same methods repository... errr, class, is the best way to go. quinta-feira, 27 de dezembro de 12
  12. Later that day, he was struck by the dark side

    of the force Can you feel the anger? quinta-feira, 27 de dezembro de 12
  13. Why violating the Law of Demeter is (usually) bad? •

    If you need to change the D object, you’ll have to change A, B, C and D. One need, four changes • Certainly such codebase has duplication. So one need, four foreseable changes plus all other code depending on D. • Messy. Responsibilities badly defined. “I have to change X, where should I go?” or, “It’s frustrating that to change D, I have to change A, B and C” • You’re saying, “Hey A, pay_me(), considering you have B, C and D.” Violates SRP, Tell Don’t Ask and the known universe. variable = object_a.b.c.d.pay_me() quinta-feira, 27 de dezembro de 12
  14. • Make objects responsible for only one thing • Don’t

    be afraid of creating new objects Recap quinta-feira, 27 de dezembro de 12
  15. • Acceptance tests definition • Integrated tests definition • Unit

    tests definition quinta-feira, 27 de dezembro de 12
  16. Unit Tests problem Object under test Dependency Dependency Stubs Mocks

    Stubs Mocks What if this dependency changes its interface (e.g method name)? The tests continue to pass. A mock is an expectation on the implicit contracts between objects quinta-feira, 27 de dezembro de 12
  17. Integrated tests 11 nodes 11 nodes 11 nodes First test

    Second test quinta-feira, 27 de dezembro de 12
  18. Integrated tests 11 nodes 11 nodes 11 nodes First test

    Second test Third test quinta-feira, 27 de dezembro de 12
  19. • With 10 layers and 3 potential branch points at

    each layer, number of code paths: 3^10 > 59,000. • With 4 branches points per layer? 4^10 = 1,000,000. • With 3 branches and 12 layers? 3^12 = 530,000. • Even with one of your 12 layers having a single code path, 3^11 > 177,000. quinta-feira, 27 de dezembro de 12
  20. “And you wonder why you spend 70% of your time

    with support calls? Integrated tests are a scam. Unreliable, self-replicating time-wasters. They have to go.” J. B. (Joe) Rainsberger quinta-feira, 27 de dezembro de 12
  21. So, how can we have reliable Unit tests? Object under

    test Dependency Dependency Stubs Mocks Stubs Mocks quinta-feira, 27 de dezembro de 12
  22. So, how can we have reliable Unit tests? Object under

    test Dependency Dependency Stubs Mocks Stubs Mocks We add a new kind of test: we test explicitly the implicit contracts between objects. Contract Tests quinta-feira, 27 de dezembro de 12
  23. Don Corleone Forgetful Meticulous Arrogant How much? Credit card? Cash?

    Try again next week Pay me Objects have contracts between them Don Corleone expects Forgetful to undestand the “Pay me” message quinta-feira, 27 de dezembro de 12
  24. # spec/don_corleone_spec.rb require “don_corleone” require “contracts/unlucky_guy_contract” describe DonCorleone do #

    alias for it_should_behave_like it_obeys “an unlucky guy contract” it “asks Forgetful for payment” do forgetful = double # Whenever we define a stub/mock, we should # define a new contract forgetful.should_receive(:pay_me) don = DonCorleone.new(forgetful).get_money end end quinta-feira, 27 de dezembro de 12
  25. # spec/contracts/unlucky_guy_contract.rb require “forgetful” shared_examples “an unlucky guy contract” do

    it “responds to pay_me()” do # this is a contract expect do Forgetful.new.pay_me end.to_not raise_error NoMethodError end end quinta-feira, 27 de dezembro de 12