[Translation] What is the difference between aggregate root, entity, and value object?

1. What is the difference between aggregate root, entity and value object?

From an identity perspective:

The aggregate root has a global unique identifier, while the entity only has a unique local identifier within the aggregate, and the value object has no unique identifier. There is no such thing as this value object or that value object;

From a read-only perspective:

In addition to the unique identification of the aggregate root, all other state information is theoretically mutable; entities are mutable; value objects are read-only;

From a life cycle perspective:

The aggregate root has an independent life cycle. The life cycle of an entity belongs to the aggregate to which it belongs, and the entity is completely managed and maintained by the aggregate root to which it belongs; the value object has no life cycle, because it is only a value;

2. How to establish associations between aggregate roots, entities, and value objects?

Aggregate root to aggregate root: associated by ID;

Aggregate root to its internal entity, direct object reference;

Aggregate roots to value objects, direct object references;

The reference rules of entities to other objects: 1) can refer to the aggregate root, entity, and value object in the aggregate to which it belongs; 2) can refer to the external aggregate root, but it is recommended to associate by ID, and it can also be associated with an external aggregate. , but it must be an ID association, otherwise the reference of the same entity will be held by two aggregate roots, which is not allowed, and the reference of an entity can only be held by the aggregate root to which it belongs;

Reference rules for value objects to other objects: just ensure that the value object is read-only, and it is recommended that all attributes of the value object be value objects as much as possible;

3. How to identify aggregates and aggregate roots?

Clear meaning: A Bounded Context may contain multiple aggregates, each of which has a root entity called an aggregate root;

Identification sequence: first find out which entities may be aggregate roots, and then analyze the boundaries of each aggregate root one by one, that is, which entities or value objects should be aggregated by the aggregate root; finally, divide the Bounded Context;

Aggregate boundary determination rule: according to the invariant constraint rule (Invariant). There are two types of immutability rules: 1) what information must be in the aggregate boundary, without which it cannot be called a valid aggregate; 2) the state of some objects in the aggregate must satisfy a certain business rule;

 

Example Analysis 1: Order Model

An Order (an order) must have corresponding customer information, otherwise it cannot be called a valid Order; similarly, an Order has an invariance constraint on an OrderLineItem, and an Order must also have at least one OrderLineItem (an order detail), otherwise it cannot be called a valid Order. is a valid Order; in addition, the number of any OrderLineItem in the Order cannot be 0, otherwise the OrderLineItem is considered invalid, and it can be inferred that the Order may also be invalid. Because if the quantity of an OrderLineItem is allowed to be 0, it means that the quantity of all OrderLineItems may be 0, which leads to the total price of the entire Order being 0, which is meaningless and is not allowed, resulting in Order is invalid; therefore, it must be required that the number of all OrderLineItems in Order cannot be 0; then it can be determined that Order must contain some OrderLineItems, so should the inclusion relationship be expressed by reference or ID association? ? This needs to lead to another question, which is to first analyze whether the OrderLineItem is an independent aggregate root. Answering this question, then according to the above rules, we know whether to use object reference or ID association. So is OrderLineItem a separate aggregate root? Because the aggregate root means the root of an aggregate, and the aggregate represents a context boundary, and a context boundary represents an independent business scenario, the only object operated by this business scenario is always within the context boundary. Aggregate root. Thinking of this, we can think about whether there is any scenario that bypasses the order and directly operates on an order detail. That is to say, in this case, we take OrderLineItem as the main body, and we are doing business operations for OrderLineItem. Is there such a business scenario? No, all our operations on OrderLineItem are based on the Order. We always do business operations for the entire Order, such as adding details to the Order, modifying The purchase quantity of a certain item of the Order corresponds to the purchase quantity of the item, removing a certain item from the Order, and so on. We will never perform some business operations from the OrderlineItem as a starting point; in addition, from the perspective of life cycle, Then the OrderLineItem leaves the Order without any meaning, that is to say, the life cycle of the OrderLineItem is subordinate to the Order. So, we can confidently answer that OrderLineItem is an entity.

 

Example analysis 2: The model of post and reply, make a comparison for better understanding.

Immutability Analysis: Are there immutability rules between posts and replies? It seems that we only know one thing for sure, and that is the relationship between posts and replies, a 1:N relationship; we don't see any other immutability rules beyond this. So is this 1:N object relationship an immutability rule? no! First of all, a post can have no replies, and the post does not have any rules for its replies, it doesn't even know how many replies it has; again, posting a reply has nothing to do with the post; second, posting a reply has nothing to do with the post Nothing has changed; from the point of view of business scenarios, we have scenarios where we post posts, and there are scenarios where we post responses. When posting a reply, the main body is the reply, and the post is only the necessary information contained in the reply, which is used to indicate which post the reply is a reply to. These all indicate that there is no invariant constraint between posts and replies; because posts and replies have their own needs for independent business scenarios, it is easy to understand that they are independent aggregate roots; it is also easy to know How to establish the association between them, but we want to minimize the association, so only keep the association of the reply to the post; there is no need for the post to save a list of reply IDs; then you might say, when I delete After a post, the reply should be meaningless? No, it is not that there is no meaning of existence, but that the deletion of the post results in the lack of the relevant information of the reply to the post, resulting in inconsistent data. This is because there is an inevitable connection (1:N) between a post and a reply, and a reply must have a corresponding post; but a reply has its own life cycle and should not be deleted in a cascade with the deletion of a post. In this case, if you delete the post, the reply becomes invalid data; therefore, we absolutely do not allow to delete any aggregate root, because once you delete the aggregate root, it means that it is related to the aggregate root Any other aggregate root of , will have the problem of missing foreign key references, which will lead to inconsistency of the entire domain model data; therefore, never delete the aggregate root;

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326251026&siteId=291194637