Thursday, July 12, 2012

Anemia or not anemia, that's the question

Bottom line:
A refactoring transition from an anemic to a rich object model is possible, painful, and—at least for me—necessary.

I'm currently working on an anemic, Struts based J2EE POJO solution that is a few years old. As I understand it, it goes by the book, with class name patterns like OrderLogicOrderDTO (Data Transfer Object)OrderDAO (Data Access Object) and Hibernate annotated OrderVO (Value Object). They implement an anemic model with logic classes and DAOs containing purely code, and DTOs and VOs containing purely data, close to a Table Module architecture, with VOs acting as data records, which is basically a well structured Transaction Script model: Plain old data based, structured programming.

Oo freak as I am, this frustrates me, especially as there is leakage of responsibility between the classes. On the positive side, there are some good architectural efforts, with OrderLogic managing the high level request for orders, delegating the pure db-access to the DAO. Operations on the resulting OrderVO is mostly also found in OrderLogic, but also elsewhere, for instance in Struts Action classes, as well as in other XxxLogic classes. And there is duplication. And, surprise, surprise, all this is also to be expected, "by the book".

For my brain to function properly, I need to apply the SRP and the IE principles, so as to find my operations close to my data. I also need to support the changes I make with TDD. All this requires a rich, non-anemic domain model. Successively, instead of one big folder (and namespace) common for everything relating to say customer and order management, I create folders for three architectural layer, like Presentation Layer (common.PL), Domain Logic (common.DL) and Data Access (common.DA). To start with, PL contains the DTOs and related stuff, DL contains the new domain objects and other domain layer logic, like class repository objects, mostly refactored out of the Logic classes. Finally, DA contains DAOs and DVs. 

At least, that's what I thought.

Actually, after some refactorings, I am heading in a slightly different direction. In my search for how to design my domain objects, I have investigated three different models:
  1. inherit from the VOs
  2. delegate to the VOs
  3. promote the VOs to rich domain objects
I chose the third one, So I am successively moving the VOs to the DL (Domain Logic) package, removing the VO postfix in the process, and successively moving logic from Logic classes and elsewhere into them. That raised the dilemma of the DAOs, managing the low level Hibernate access and actually creating and saving the former VOs. They cannot be located in an architectural layer below the objects they are to manage. So now, I have promoted the DA package to the domain logic layer, and I am moving the Repository classes into DA, the difference between them and DAOs being that DAO contains the Hibernate mapping, whereas the repositories handle requests for domain objects from the rest of the system.

When time allows, I will add a figure here to explain this more clairly. For the time being, I am curious to see where this strategy takes me.

No comments: