Growing Object Oriented Software Guided by Tests — Chapter 2 — TLDR
If you haven’t read chapter 1’s TLDR, I recommend starting here.
Ok, I know you can’t wait to get the gist of chapter 2 so let’s drill right in, with defining what’s an object oriented system.
An object oriented system: A web of collaborating objects.
What’s the difference between values and objects?
Values vs. Objects:
- A value represents some fixed quantity or measurement and it is immutable.
- An Object on the other hand is an identity that might change state over time. It models a computational process or a stateful behavior of the system.
The communication between the objects can be seen through tests. Don’t try to model your system based on the entities (objects) alone, but on the communication between them.
When you model a system, think of every object you wish to create in terms of this threesome:
- Who’s the Candidate? Which object do you wish to create?
- What’s the role of the object? Define the responsibilities it will have.
- Who are the objects’ collaborators? With which other objects will it communicate?
Tell, Don’t Ask
Each object should tell its neighbor object what it wants from it, by using the roles that the neighbor has.
Do not call your neighbor’s neighbors! That will be a violation of Demeter’s law.
If you’ll be good and follow the law, you’ll avoid a Train Wreck Code.
What’s Train Wreck Code?
A series of getters chained together like the carriages in a train. If you try to change the design of one object, you’ll cause ripples in remote parts of the codebase.
objectA.getObjectB.getObjectC
How should you do it then?
Don’t expose the internal structure of the neighbor object. Your object should ask its neighbor the question it really wants answered, instead of asking it for the information to help it figure out the answer itself.
Why?
Because:
- It will be easier to test
- The behavior of the neighbor’s role will be in the neighbor’s class where it belongs
- The behavior will have a name that explains it
How would you test such an object that doesn’t expose its state?
- Create mock instances of the neighboring objects
- Define the expectations — how would these neighbors be called?
- Assert that the mocked collaborators were correctly called as expected.
Pheeeew that was fast :)