For my first post I want to question one of the most prominent Goolden Hammers and put an anti pattern back into my toolbox.
Object Orientated Design has been for a long time accepted as the 'correct' approach to software development.
There are very different approaches available and especially functional programming has been getting some prominence recently.
For this post however I won't go so far as to question the whole approach but will attempt to put one of the 'anti-patterns', the Anemic Domain Model, back into the toolbox as one of the right tools for the right job.
The term Anemic Domain Model was coined and made an anti pattern by Martin Fowler in 2003 ( AnemicDomainModel).
As I don't really want to talk about an anti pattern and as any modern approach should be represented by a three letter acronym I will use a far more positive title for it here and call it POO (Process Orientated Objects).
The idea here is that the domain objects are demoted to pure state-holders which have no behaviour themselves. Behaviour and business rules are extracted into processes. I call these processes rather than services as the term service implies a coarse grained and exposed structure. A service might therefore utilise a series of processes, which themselves might utilise child processes.
The processes hence become the puppet players and the domain objects are the puppets.
Let's see why I would want to do so.
My role in my company is to create and maintain software products for our customers.
As customers do, our customers would like to have their cake and eat it. They expect to receive established products. At the same time they want these products to follow their specific processes and tie in with their existing infrastructure and legacy applications.
My employer is not very different. The company wants to have a single maintenance and hence source branch for a product whilst not having to say no to any specific wishes of a client.
This would all still be fine if we would talk about simple extensions to existing functionality or the odd custom field.
We are writing however financial software for large international finance houses. Although from a high level these all want the same functionality (let's say a loan administration system), once you zoom into their precise requirements , no two companies want the same business rules.
Worse, even the same company is likely to have disparate rules for the individual sectors they are working in.
Let's look at a simple loan contract. Depending on client and sector the differences can be described in two main directions:
- The details captured
If it's a mortgage I want to record the property details, for a car loan the details of the vehicle and for a personal loan I have no collateral at all. Depending on the sector I might or might not have to care about VAT (Sales tax).
- The functionality
Interest might be calculated daily, monthly or yearly. I might need compound interest and I might or might not charge interest on outstanding fees.
However inheritance is one directional (at least in the world I live in, e.g. Java). If I have behaviour and state encapsulated in the same object than I can only extend both at the same time.
As a result I quickly start to branch and reimplement similar functionality twice:
If I split behaviour out of the domain objects on the other hand I can have these two concerns evolve separately:
The usefulness of this approach increases as we add more functionality. Each of these functions will live in their own process hierarchy which allows any combination of methods to be applied without the need to branch.
I would like to finish of by dealing with the reasons why the POO approach is poo poo'ed. Looking at Martin Fowler's original blog I can however see only one concrete critique that does not just state that it isn't OO as it was intended:
"In essence the problem with anemic domain models is that they incur all of the costs of a domain model, without yielding any of the benefits. The primary cost is the awkwardness of mapping to a database, which typically results in a whole layer of O/R mapping."
This might have been a real issue in 2003. Transparent persistence and decent ORM tools are the norm now with technologies such as Hibernate and JPA.
I actually use AndroMDA to create my domain objects and mappings for me from my UML diagrams which makes the whole process very easy and quick.
So I shall reformulate this to:
In essence the benefit of POO is that I get a lot of the benefits of the OO aproach, the benefits of ORM tools and transparent persistence, whilst keeping the concerns of state and behaviour logically separated.
If anyone reads this blog as an argument that POO is the correct approach and that real OO is not, they have misunderstood me. Both are valid approaches and the skill is to decide which approach fits a particular requirement.
I use POO to create myself a construction kit from which to build specific implementations. If you do not have such a desire/requirement, proper OO will be the neater and better approach.