Saturday, December 22, 2007

The Plum Pudding Model

The evolution of our understanding of the atom is a good metaphor for our understanding of object oriented domain modeling. Many projects have been successfully completed without strict adherence to Domain Driven Design. What price, if any, is imposed when developers consciously or unconsciously fail to create a good domain model? Have analogous situations occurred before?

In the early 1900s, J. J. Thompson, discoverer of the electron, and Ernest Rutherford proposed two different models of the structure of the atom. Thompson proposed the "plum pudding with raisins" model of the atom. With this structure, few interactions are expected and the behavior is uninteresting.

In an experiment, Ernest Rutherford showed that the Thompson model failed to account for the behavior of subatomic articles directed at gold foil. Rutherford's description of his results was, "It was almost as incredible as if you fired a fifteen inch (artillery) shell at a piece of tissue paper and it came back to hit you". This was certainly different from the expected uninteresting behavior. To better model the behavior seen in this experiment, Rutherford proposed a model of the atom with a dense, heavy core surrounded by orbiting, lightweight electrons.

The "plum pudding" design of Thompson's model is an almost homogeneous structure with each part of the model similar to other parts. This model of the atom is similar to OO designs which fail to assign discrete responsibilities to classes in the domain model. Models should have interesting behavior and unique components that combine this behavior with the attributes of the entity. The task of defining entities and assigning responsibilities to them has been identified as a major stumbling block in OO development.

Craig Larman describes the purpose and the technique for responsibility assignment in his book "Applying UML and Patterns". Larman identified the task of assigning responsibilities to classes as the critical exercise in object oriented modeling. That task cannot be done by a developer who doesn't know or isn't interested in the principles and goals of design.

"The critical design tool for software development is a mind well educated in design principles. It is not the UML or any other technology" Larman, Craig; Applying UML and Patterns - Third Edition

Kent Beck and Ward Cunningham recognized the problem almost twenty years ago: "The most difficult problem in teaching object-oriented programming is getting the learner to give up the global knowledge of control that is possible with procedural programs, and rely on the local knowledge of objects to accomplish their tasks. Novice designs are littered with regressions to global thinking: gratuitous global variables, unnecessary pointers, and inappropriate reliance on the implementation of other objects." http://c2.com/doc/oopsla89/paper.html

The global variables and unnecessary pointers in Ward and Cunningham's description are examples of failure to correctly assign responsibility. Applications having domain models that reflect those problems may bring a company as much revenue as any other design so, what is the difference between a model with entities and one that simply gets the work done in whatever manner the developer cared to code it? Correctly assigning responsibilities to unique, discrete, cohesive classes results in a design that is DRY (from the adage, "don't repeat yourself"). DRY code eliminates the repetition found in procedural code; DRY code is cheaper and faster to modify. Those who want to start developing a DRY domain model should see Beck and Cunningham's CRC technique described in the link above.

A useful alternative first step may be to create a normalized database model and to use this model as a guide for the classes and relationships in the OO domain model. This alternative is useful in modeling data and relationships but not behavior so, additional modeling will be required to create a full-fledged domain model and avoid the anemic domain model anti-pattern.

A similar problem to the one discussed above (uncohesive domain model) is mixing responsibilities of other application layers in the domain layer. Pay careful attention - don't avoid one problem and think you've avoided both. The domain model presupposes a three layer architecture with database and presentation responsibilities completely separate from the domain layer. The effect this has on the domain layer is that it is much simpler as it does not import or interact with classes in packages like java.sql or javax.faces, etc, etc. In this regard, it comes down to two rules; first, have cohesive layers and second, have cohesive classes.