DDD Domain Driven Design: an in-depth interpretation of anemia model and congestion model

Time:2021-12-31

Foreword-

In order to deeply grasp and understand the core of DDD domain driven design, we can’t get around two abstract concepts – “anemia model” and “congestion model”:

  • The transaction model is the transaction script mode* Congestion model is the domain model pattern.

-Anemia model-

The anemia model was first widely used in EJB2 and was created by spring in its heyday. It will:

  • “Behavior” (logic, process); * “state” (data, corresponding to language is object member variable).

Separate into different objects:

  • State only objects are the so-called “anemia objects” (often referred to as VO value objects); * behavior only objects are the logic / service / manager layer in our common n-layer structure (corresponding to the stateless session bean in EJB2).

——Rod Johnson, once the author of spring, also admitted that spring is just following the “transaction script” in the era of EJB 2, that is, process oriented programming.

Anemia domain model is a long-standing anti model, and there are still many supporters.

Martin Fowler once chatted with Eric Evans. When talking about it, they all felt that this model seemed to be becoming more and more popular. As promoters of domain models, they think this is not a good thing.

DDD Domain Driven Design: an in-depth interpretation of anemia model and congestion model

The basic feature of the anemia domain model is that it really looks like this at first sight. There are many objects in the project, and their names are based on the domain. There are rich connections between objects, which is very similar to the real domain model. But when you look at the behavior of these objects, you will find that they basically have no behavior, just a bunch of getters / setters.

In fact, at the beginning of design, these objects are defined to contain only data and cannot be added to domain logic; Logic should be written into a group of objects called service; Service is built on domain models, which need to be used to transfer data.

The horror of this anti pattern is that it is completely contrary to object-oriented design.Object oriented design advocates binding data and behavior together, while anemia domain model is more like process oriented design. Martin Fowler and Eric strongly opposed this practice when they were in Smalltalk. What’s worse, many people think that these domain objects are real objects, so they completely misunderstand the meaning of object-oriented design.

Nowadays, the concept of object-oriented has been widely spread, and more arguments are needed to oppose this anemic domain model. The fundamental problem of anemic domain model is that it introduces all the costs of domain model design, but does not bring any benefits. The main cost is to map objects to the database, resulting in an O / R (object relationship) mapping layer.

Only when you make full use of object-oriented design to organize complex business logic can this cost be offset. If all behaviors are written to the service object, you will eventually get a set of transaction scripts, thus missing the benefits of the domain model. As Martin said in the book enterprise application architecture pattern, domain model is not necessarily the best tool.

Putting behavior into the domain model does not conflict with layered design (domain layer, persistence layer, presentation layer, etc.), because the domain model puts domain related logic – verification, calculation, business rules, etc. if you want to discuss whether you can put data sources or presentation logic into the domain model, it is beyond the scope of this article.

The views of some object-oriented experts sometimes make people confused. They believe that there should be a process oriented service layer. However, this does not mean that the domain model should not contain behavior. In fact, the service layer needs to be used in conjunction with a set of behavior rich domain models.

Eric Evans mentioned in his book Domain Driven Design:

Application layer (i.e. service layer)

Describe what the application needs to do and schedule a rich domain model to complete it. The task of this level is to describe business logic or interact with the application layer of other projects. This layer is very thin and does not contain any business rules or knowledge. It is only used for scheduling and dispatching tasks to the domain model of the next layer. This layer has no business status, but can provide task status for users or programs.

Domain layer (or model layer)

Represents business logic, business scenarios, and rules. This hierarchy controls and uses business States, even though they are ultimately stored by the persistence layer. In short, this layer is the core of the software.

The service layer is thin — all important business logic is written in the domain layer. He repeated this view in the service pattern: the common mistake people make today is not willing to spend time putting business logic into the appropriate domain model, so as to gradually form process oriented programming.

I don’t know why this anti pattern is so common. I doubt it because most people have not used a well-designed domain model, especially those data centric developers. In addition, some technologies will also promote this anti pattern, such as J2EE entity bean, which makes me prefer to use POJO domain model.

In short, if you put most of the behavior in the service layer, you will lose the benefits of the domain model. If you put all your actions at the service level, you are hopeless.

advantage

Simple:

  • For applications with only a small amount of business logic, it is very natural to use* Rapid development and easy to understand* Note: this approach cannot be completely excluded.

shortcoming

Unable to deal with complex logic well:

  • For example, the revenue recognition rules are changed. For example, a certain rule should be used for contracts signed before April 1… * another rule should be used for contracts signed with Europe

-Hyperemia model-

The essence of object-oriented design is: “an object has state and behavior”.

For example, a person:

  • What kind of eyes and nose he has is his state* People can play games or write programs, which is behavior.

Why should a “human manager” exist to help people “play games”? Take a simple J2EE case to design a user related function.

The traditional design is generally:

  • Class: user + usermanager* Save user call: usermanager save(User user)。

The design may be:

  • Class: user* Save user call: user save();* User has one behavior: save itself.

In fact, they have no particular applicable direction. Individuals prefer to always use congestion model, because OOP always has richer semantics, more reasonable organization and stronger maintainability than process oriented programming – of course, it is more difficult to master.

Therefore, in the actual engineering scenario, whether and how to use it still depends on the understanding and grasp of the designer and team model design, because most J2EE developers are deeply affected by the anemia model. In addition, many detailed problems will be encountered when using congestion model in actual engineering scenarios. The biggest difficulty is “how to design congestion model” or “how to separate appropriate and semantic logic from complex business and put it into VO behavior”.

If an object contains other objects, the responsibility will continue to be delegated, and the specific POJO will execute the business logic, making the policy pattern more fine-grained rather than writing ifelse.

Author: javaedge in Nuggets
Link:https://juejin.cn/post/6917125801460629518

Recommended Today

Could not get a resource from the pool when the springboot project starts redis; nested exception is io. lettuce. core.

resolvent: Find your redis installation path: Start redis server Exe After successful startup: Restart project resolution. ———————————————————————->Here’s the point:<——————————————————————- Here, if you close the redis command window, the project console will report an error. If you restart the project, the same error will be reported at the beginning, The reason is: It is inconvenient to […]