1. Professor Karl Lieberherr work on Adaptive programming and the Law of Demeter
In 1987 Ian Holland at Northeastern University formulated a style rule for designing object-oriented systems called The Law of Demeter [3].
The Law of Demeter is best known in its formulation at the method level that pertains to how methods are written for a set of class definitions. Typical examples of violation for this formulation include method call chains such as dog.getBody().getTail().wag() that is colloquially known as a train wreck [4]. Conformance to this formulation of The Law of Demeter supports object encapsulation.
The formulation of the The Law of Demeter that applies to the structure of the classes, is less known. This formulation makes the notion of unnecessary coupling very explicit. Conformance to this formulation supports modularity and low coupling in object relationships, and it makes code less brittle in the face of changes in the relationships and in the related objects [4]. In other words, conformance to this formulation helps to overcome the one weakness of OO code. But how to achieve this conformance?
Between 1991 and 1996 Professor Karl Lieberherr [5] developed Adaptive Object-Oriented software programming and the Demeter Method [0], a concept that takes encapsulation to a new level. This work clearly identifies and describes the one weakness of OOP and provides a working solution.
The solution as shown here [1] conforms to the Law of Demeter and uses programming by composition so that each composite object shields other objects from changes in the composed objects and in their relationships. The solution also replaces hard-coded navigation paths used to traverse the object graph with higher-level navigation specifications. Automatic tools called Demeter Tools use the navigation specifications to regenerate and adapt the code that traverse the object graph and invoke the functions, whenever the object graph or an object structure changes.
Here I name this solution as: “Programming by Composition + Demeter Tools”.
2. Mock Objects and Growing object-oriented software, guided by tests
Thanks to Steve Freeman, Nat Pryce and Tim Mackinnon for reviewing 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”.