Table of content
- Abstract
- Which is the one weakness of OOP?
- How to overcome the one weakness of OOP? Solutions:
- 1. Professor Karl Lieberherr work on Adaptive programming and the Law of Demeter
- 2. Mock Objects and Growing object-oriented software, guided by tests
- 3. Less, The path to better design
- Comparing solutions
- References
Mock Objects and Growing object-oriented software, guided by tests
Thanks to Steve Freeman, Nat Pryce and Tim Mackinnon for commenting the draft of this post!
Between 1999 and 2010 a group of people from Connextra team first and then from Extreme Tuesday Club (Connextra team members: Tim Mackinnon, Tung Mac, Matthew Cooke, Iva More, Peter Marks, John Nolan; Extreme Tuesday Club members: Steve Freeman, Philip Craig, Oli Bye, Paul Simmons; Joe Walnes from ThoughtWorks and Nat Pryce) explored, experimented and developed a new way of writing object-oriented software that revolves around the practice of test-driven development (TDD), tests automation and a new technique called Mock Objects.
The full story is documented here too [10]. The initial work between 1999 and 2004 has been documented into two papers [6][7], and in 2010 in a new book [8] that summarised the whole experience produced by all the people involved.
The trigger for the discovery of the technique was when John Nolan set the challenge of writing code without getters and then favouring void methods over non-void ones. Later Peter Marks helped coin the name ‘Mock'.
The driver for the technique was literally a pragmatic way to practice TDD and write good tests without going against what was felt were good design principles, for example without exposing object internals for the sake of testing, or shying away from composition. The work was then inspired and influenced also by the Law of Demeter and Lieberherr’s work and also by [12][13].
Probably the most important effects on coding style were the development of the Mock Objects, and favouring composition over inheritance that led toward programming by composition. Programming by composition led to decouple object behaviour from the structure of the object graph. In addition to that, each composite object shields, to some degree, other objects from changes in the composed objects.
Programming by composition also led toward a design pattern that nowadays is called dependency injection [9] not to be confused with the dependency injection frameworks (a.k.a. IoC frameworks or IoC containers) that were never needed in the large Connextra code base. In turn dependency injection led to minimising objects’ dependencies and to decoupling dependencies.
Unlike the solution of Lieberherr, this solution does not use automatic tools for code generation.
Here I name this solution as: “Programming by Composition + Dependency Injection”.
A secondary effect on coding style was the tendency to push behaviour towards Visitor-like objects, objects resembling the Internal Iterator pattern [11] that have similarities with the Visitor pattern. A team member from Connextra remember using the Visitor-like pattern together with the Composite pattern used among other things to abstract away differences between the traversed objects.
The abstraction introduced with the Composite protects the code, to some degree, from changes in the object graph and in the structure of the object.
The Visitor-like design reverses the direction of an unstable dependency relationship (from a stable object to an unstable one), turning it into a stable relationship (from the unstable object acting as the "visitor" to the unstable one acting as the"element").
While the focus on this solution diminishes after the first paper, it is documented here because of a similarity with the solution presented by Sandi Metz.
Here I name this solution as: “Visitor-like + Composites”.
An interesting after thought about the technique of TDD with mocks from Tim Mackinnon: I can’t stress enough how most people have missed, and still do, that connection with CRC cards, mocks and role play. Mocks and the technique really came from the idea of working with a partner to act out what you expected the design/objects to do - and then “asserting” those interactions. That was the number one design point. For us, this was the aha moment.
On the same line Nat Pryce comments: There was quite a change in emphasis between the Endo-Testing paper and the Mock Roles, Not Objects paper and GOOS book. For example, the former recommended using mock objects to fake third-party APIs that are difficult or slow to use for real in tests, such as JDBC. The latter recommended *not* mocking third-party APIs, but rather discovering the appropriate interfaces for mocking from the need of client objects. Also the Mock Roles, Not Objects and GOOS style focused more on messages and protocols between objects.