Growing Object-oriented software, guided by tests by Steve Freeman and Nat Pryce
Recommended to me by someone at work, this was a fantastic read. The introductory third of the book is a really good exposition of object-oriented design using test driven development. Rather than being a theoretical guide, this book seems to be full of practical advice and descriptions from the authors’ working experience. The majority of the book is a worked example of the development of a full application using the test driven methodology, starting with the walking skeleton, an initial implementation that exercises all of the components of the system in order to check that everything is correctly installed, and developing in very small steps and associated refactorings to get to a final application.
The authors are not fixated by unit testing a single class, but also emphasise integration tests that work between components (which seems a much more realistic goal to me). They use a “Tell don’t ask” style where the object is told to do something and takes the responsibility for the action, in turn calling on to collaborators, rather than using Java style property accesses to get an object from another object in order to tell the returned object to do some action. This was the first form of object orientation where the emphasis was on message passing between objects rather than the more typical function calling style. This leads to objects being tested by mocking their dependents, telling the object to do something and then checking that the interaction was correct. This contrasts with the more usual invasive style of setting up an object, calling a method on it and then accessing the private state to see if the right things happened. This style can be quite brittle in that you can’t change the implementation without changing the tests. With the style of this book, we can reimplement the object and still hope that the tests pass as the objects interacts as expected.
Objects require other objects which they use in one of three roles. Dependents are objects that have their methods called and are therefore the things that need to be mocked during tests so that we can test the interactions. Notifications are objects that need to be notified of changes of the object’s state, but in a fire-and-forget style so that the object doesn’t care how many listeners are present at any time. Adjustments are configuration type objects which customise the object for the system in which it is used.
The worked example is really good, showing in great detail how small steps can get us a long way, with the tests being maintained throughout. I’m hoping to get a chance to put some of this into practice in the near future.