Saturday, February 27, 2016

Why the Anemic Domain Model pattern?

Martin Fowler described a number of business logic shaping approaches in his classic work Patterns of Enterprise Application Architecture. The top three of them are:
  • Transaction Script, a business application is thought as a set of procedures, each one is invoked for a certain request comes on from the View layer.

  • Table Module, a business application also is thought as a set of procedures but every manipulations with each data table are encapsulated in a certain class. The application code looks like more structural and OOP fancy.

  • Domain Model, an approach is used to describe complex business logic. It is the most complicated way. The business logic is thought as a web of interconnected domain objects and every relation between the objects is described as a similar one in the Real World. Technical aspects like persistence, security, transactions management are implemented outside of the application business logic layer.

    There are two variants of the Domain Model pattern:
    • Rich Domain Model, the data and behavior are encapsulated in domain objects;
    • Anemic Domain Model, the data only are encapsulated in domain objects, there is the layer of services upon the business logic layer encapsulates the application behavior.l

Which pattern to chose, I mean the choice between the transaction script, table module or domain model patterns, is not a so difficult decision because the patterns are well described in the Fowler's work, but the question about whether leverage the Anemic Domain Model is more complicated. Some OOP theorists consider the pattern like an 'antipattern', but from another point of view the pattern is very popular in everyday application development practice and it could be an indicator the pattern provides some benefits. Let's learn the pattern more deeply!


Domain Model Pattern


Like it was described above, the crux of the pattern is the following: developers implement a web of interconnected objects each represents some meaningful individual. The approach provides some benefits, which decrease complex of the developed business logic. The developers could leverage all OOP principles like encapsulation, inheritance and polymorphism. The created class structure is a mirror for the Real World and this fact itself significant improve communication between developers and business analysts. The team members use a common language. The well described design patterns could be used. Another benefit is the transparent persistence, so the domain objects know nothing about underlying persistence mechanisms like a relational database.

Application business logic described like a domain model can be re-used. In contrast to the Transaction Script and Table Module patterns, the business logic is independent of the application View level and users requests, therefore any kind of the View level can be organized upon the logic, e.g. RESTful or SOAP web-services.

But there is a price for everything. The Domain Model pattern adopters designing, developing and maintaining solutions should gain more experience, they should build more complicated abstractions and the more complex technologies should be leveraged. For example, the full-function ORM frameworks like Hibernate, EclipseLink or OpenJPA usually are on the case. It takes more experienced developers and sometimes can be a reason for performance degradation.

Rich and Anemic Domain Models anatomy


What about the difference in the anatomies of Rich and Anemic? During the Rich Domain Model pattern using application business logic, i.e. the system behaviour, is implemented in domain objects. This approach does not absolutely deny the possibility of exploiting service classes like '*Service', '*Manager', '*Helper', but it is a good idea only while a number of domain objects are involved in a piece of the business logic and there isn't obvious object to put the logic in. As an example, we can have a look at the following piece of the 'Telecom' domain. A customer wishes to subscribe to a service and should add the service in an order. A developed application has to do provider checking, so to find a provider is able to provide a service with certain conventional parameter values. In the case of a Rich model, the service adding logic is encapsulated in the addNewService(Service service) method of the ServiceOrder class:


The anemic model looks different. Domain objects do not encapsulate any behaviour. They have appropriate constructors, access methods (getters and setters) only and in fact, they just implement some relationship with other objects. The behaviour is being moved in the service layer is upon domain model. Let's have a look at the same as above example, but the ServiceOrder class has only access methods and the provider checking is staffed into the ServiceOrderManager class:


Anemic Domain Model criticism


There are two important considerations cons the Anemic Domain Model pattern:
  • the pattern lies opposite the OOP principles. Because domain objects don't encapsulate any behaviour the model contradicts the main idea of OOP, the data and data processing methods have to be located in the same place.

  • the Domain Model pattern degenerates and the benefits provided by the pattern are lost but pattern's weakness still remain. For example the full-function ORM frameworks are necessary for data access layer implementation.
Let's look deeply on the each above consideration. Anemic model contradicts the main idea of OOP. Ok, yes, particularly it could be true since domain objects do not encapsulate any behavior. However, it is possible to hide the internal state of domain objects and let access to the state only using some addition methods. The idea could be demonstrated on the above order processing example, we just need to add the addService() method into the ServiceOrder class and mark the setService() method as private. The ServiceOrderManagerImpl class does provider checking and invokes the addService() method.


There still is a problem. Methods like the addService() must be public because the behaviour encapsulated in service classes and the classes must be allowed to invoke the methods. Encapsulation becomes worse and a new developer in the team can get a domain object property directly omitting the methods of an appropriate service, e.g. put a service into an order without providing checking.

Encapsulating the business logic with a POJO façade or a session EJB looks like a solution. Returned domain objects should be immutable or should be in the detached from the data access layer state, so the objects couldn't be persistently changed omitting the business logic layer.

Other OOP principles like inheritance and polymorphism still available during Anemic Domain Model using. Almost all modern ORM frameworks allow mapping an object's hierarchy to a database. For example, designing a financial application model a developer has to implement different overdraft calculating strategies. Let's suppose there are two strategies: the no limit overdraft strategy and the set by a constant limit overdraft one and write the following piece of code:


Every instance of the Account class, entity, has a reference on a certain overdraft calculating strategy is applicable for:


And the polymorphic strategy is allowed for using in the AccountService class:


So, no advantages of the Domain Model pattern and OOP design principles utilization is stolen during Anemic Domain Model using, as shown above. Exactly, a designer should spend a little bit more time for system architecture building, e.g. put some interfaces between layers, but it is the righteous fee because the simpler design pattern is used. Also, transparent persistence is in the case because the synchronization of object internal state changes and a persistent store doesn't depend on a place where the changes are bringing to, it doesn't matter an object changes it's own state or a service does it.


Why the Anemic Domain Model pattern is so popular today? My opinion is the pattern is implemented a bit easy than the Rich Domain Model one using this day technologies. The most popular and usable way for design program structure is the Dependency Injection design pattern, so there are two sources of objects in each modern application:
  1. an Inversion of Control container, which implements the Dependency Injection design pattern and creates all service objects: repositories, services, facades, etc.;

  2. an ORM framework, which creates all domain objects.
The Rich Domain Model design pattern creates the problem of weaving objects emitted by the sources in the common web of objects. In the above example an instance of the ServiceProviderRepository must be injected into an instance of the ServiceOrder class somehow. Not all ORM frameworks allow the injection of created by an IoC container objects into ones created by the framework itself. There are a number of approaches but everyone has some or others weaknesses.
  1. The static variables and methods injection. Repositories and other objects created by an IoC container are provided as singleton objects. The weaknesses are the following: it is very complicated to mock an injected object during testing, for example, also the approach brings hidden dependencies.

  2. The method injection (it is not the same as the setter injection). Dependencies are assigned as parameters of a domain method implementing business logic, so all objects are needed for the method like repositories, factories, connections and so on must be assigned as method's parameters. The weaknesses are the following: domain methods must be defined with complex, verbose signatures. All dependencies are shown by outside of each domain object class. During modification a method, when a new dependency is being injected, all points of the code where the method is invoked must be changed.

  3. The Service Locator design pattern could be utilized and each domain method implementing business logic should acquire a reference on the Locator. The weaknesses are the same as the design pattern has.

  4. To omit any dependency injection and pass to domain methods the results of the service objects execution. But this way just remove business logic from domain objects and it is the first step on the Anemic way.

The benefits


One reason for the Anemic popularity is the modern application design infrastructure, but the pattern provides its own advantages. Let's have a look at the following advantages list.
  • Simple design and development. As a rule, an anemic model takes less effort for design and could be implemented by less-experiences professionals. Also, it is no question about the right domain object for a piece of business logic, only services should implement the logic. There are some questions about which service has to be created and in which one put the logic but these questions are easy.

  • Domain objects might just be generated from a persistent store, i.e. a database, a WSDL document, an object-relation mapping file and so on. If a developed application is an interface for a legacy system designed using no-OOP language or provided a set of RCP style APIs. Because today there is a trend to exploit an SOA approach this benefit becomes more and more important. This point distinguishes today situation from the Fowler article time, after all, the article was published 12 years ago. To generate a domain model for a client to an external service and implement a service layer upon the model is a much easier way than to create a rich domain model and implement the integration between the model and the external service.

  • Reusability. If there is a requirement to design an application, which uses the same data as an existing one built upon the Anemic Domain Model pattern but by another way, so implementing another business logic, the existing domain object classes will be reused. As opposite, a rich domain model is less ready for reusing since the application business logic hard coded in the domain object classes. From this point of view, excessive encapsulation looks like a harmful thing.

Conclusion


In conclusion, I would like to say it is a bad idea to allege an authority during a discussion or decision making. Solution Architecture is a kind of science and it is a usual situation while there is a number of scientific each of has its own opinion. Pluralism is a great achievement of the civilization. Do not idolize somebody for you, a better approach is take into account your own experience and priorities are actual for your project only!

Publications



Would you like to give a 'Like'? Please follow me on Twitter!

No comments:

Post a Comment