Tuesday, May 1, 2007

Anemic vs. Rich Domain Models

There's debate at almost religious intensity on some forums as to the type of domain model to be used in developing applications.

The rich Domain Model (proposed by Martin Fowler) suggests having e.g. Employee objects, with all operations on an Employee provided by the class itself - such as Employee.Save(). Fowler argues that this makes for better object orientation, as there is greater encapsulation and the opportunity for polymorphic use of objects.

The alternative is the Anemic Domain Model (the term coined by Fowler himself makes clear how much he dislikes the model by using a term with negative implications) and probably inspired by the design of stateless session beans from EJB. This design has (to follow the above example) Employee objects containing their own data, but EmployeeManager or EmployeeService classes containing the operations - such as EmployeeManager.Save(Employee).

Wikipedia labels the latter as an anti-pattern; however, given that there are so many proponents of the Anemic Domain Model (ADM), labeling it an anti-pattern seems to be an extremist, dogmatic point of view. The pro-ADM argument is that breaking the functionality out into separate classes further enhances separation of concerns, which is a good design practice.

Personally, I've found the ADM to be a simple one to develop, lending itself well to generation of code via templates etc. Furthermore, with the whole SOA/Web Service buzz, services as per ADM make a lot of sense; even use of the GOF Facade design pattern would probably lead to the same solution. Say in a Web Service application, the designer would be forced to make the Domain Model dependent on the relevant Web Service - in my book, placing Web Service calls behind Employee.Save() would be mixing up far too many concerns (i.e. business logic + web service invocation code).

Fowler's rich Domain Model is an ideal solution - and I've used it successfully on several in-process solutions - and if it can be achieved outside of the pro-ADM arguments just outlined - I'm all for it. Maybe having the UI talk to a rich Domain Model (your formal API), which in turn talks to the back end comprising an ADM would be the answer... however, this would mean code that would be repetitive and leave that much more room for defects to creep in.

It all comes down to a question of how pragmatic a software designer is willing to be. The only certainty is that this argument will not be going away anytime soon.

A few blogs which have opinions on this topic:
Finding references on this matter is not hard at all...
Google for rich Domain Model
Google for Anemic Domain Model

4 comments:

Mahasen Bandara said...

Hi,

I was more or less in the same belief and honestly didn't understand how to make rich domain model work with services.

But then, guided by you, I read Fowler's PoEAA and came across his Service Layer pattern. And it actually made sense.

What he suggests is to keep the domain model behind the service layer, giving the domain logic to the model objects and application logic to the service layer.

Applications communicating with the service layer should use DTOs, essentially, anemic counterparts of the rich domain object behind the service layer.

And on the topic of template based code generation; most code generators that I've used lately generate a separate set of partial classes for domain logic which they don't overwrite on consecutive re-generations. And even without such support, it is possible to have the domain model wrapped around the generated objects.

I think it saves the trouble of operating on collections and managing the chorus of relationship updates in a separate Manager or a Service class. (i.e Does EmployeeManager.Save(Employee) save the Employee.SalaryHistoryList as well? or delegate that to a SalaryHistoryManager.. Then how do you control what's saved first, is it the SalaryHistoryList collection or the Employee - this trouble is because the logic isn't where it belongs)

I think Fowler has a very valid point...

dilan said...

@Mahasen:

Fowler usually tends to have very valid points! :-)

One of the concerns I was raising was that with the proposed 'Service Layer', UI code would no longer be as expressive as earlier (e.g. employee.Save()). This code would reside behind the Service Layer now. This would mean that if you're using services, there's no way (short of mass-scale code duplication) that your outside/consumer facing API could be a richly expressive Domain Model.

While in a true sense of the word, DTOs were meant to be lightweight objects targeted at specific business functionality, I see some level of duplication with the domain model. By keeping the domain model anemic, this duplication is reduced - but some smart work may have to be done to prevent *excessive* (a very subjective word, highly dependent on requirements) data being transferred. There will also be a fair bit of DTO to Domain Model (and vice versa) conversion code...

On your point about code generation; yes, even at the time of writing this article I believe partial classes were in existence and the code generation templates could make use of this facility. I'm just a tad worried about the proposed wrapping solution, that we're tending towards more over-abstraction than needed.

As for what gets saved first -
I'd usually have business services and entity services - with the former dependent on the latter; transactions defined in the former. This would allow consumption at the required granularity. While I
guess this would be a personal preference, I'd always save the parent concept first (makes sense from a referential integrity perspective). I always liked the sequential code in a business service class approach, inside a TransactionScope - very clear, leaves no room for doubt!

All this shows that you can't get something without giving up something else, eh? But that's always been the Software Architect's job - balancing the trade-off!

Mahasen Bandara said...

I agree with the latter part of your comment, but not sure if I agree with the expressive UI code.

Should it know that an employee is saved? or should it just tell the service here I changed something about an employee and you worry about it if you want...

And then I start to think of a local caching scenario, then, may be CRUD operations aren't a good example. How about Employee.CalculateTax() (lets pretend for the moment CalculateTax is business logic that's run on the state of employee and doesn't belong with any other domain object). If the client could execute that logic too, then I feel that defeats the purpose of having the service in the first place.

I've spent some long nights reviewing and refactoring business logic separated from the domain objects sometime back - probably due to my bad designing and communication - but that lead me to think there should be a better and less error prone way of making business services and domain objects work. So Fowler's Service Layer gave me good food for thought. But the applications I work on now are different in nature so I don't get to experiment them much.

BTW; The wrapper I mentioned was motivated by Fowler's 'recordset' and intended to counter "languages that don't support partial classes" :)

dilan said...

@Mahasen: what I meant by expressive code was the apparently more readable 'employee.Save()' rather than 'employeeService.Save(employee)' notation, which is available in Rich Domain Models.

Even if we took the example of CalculateTax(), what I'm getting at is to be able to make the code look meaningful as in employee.CalculateTax(); whether this is to be executed remotely or locally is not really the client's concern. It just wants the tax calculated... period!

However, if we go with a Service Layer approach, we can't use the above notation, because that will mean mixing service invocation code with the 'Employee' class.

In my case, it was Rich Domain Models that gave me food for thought, for the raw OO-ness of it; I was happily going along developing apps with ADMs (which doubled as DTOs) and Services to contain the logic, until I came across RDMs!

I like the RDM style notation of SharePoint, MS Office PIA APIs etc. and I think this may hint that horses for courses may be the best way to go...