Domain Driven Design Theory and Practice

strategic design

Strategic design is the process of deconstructing "chaos" into "clarity". From the beginning to the end of the process, we will divide the domain, define the scope of the common language, determine the system boundary context and the mapping method between contexts .

insert image description here

Field division

Strategic design plays a key role in domain-driven design, because it determines whether the direction of progress is correct; domain division is the most critical point in strategic design, which determines the rationality of the final system architecture.

What domain division needs to do is to identify core domains and subdomains. The core domain is the core of the system, the key direction of system construction, and the focus of resource tilt; sub-domains are divided into supporting sub-domains and general sub-domains, which can be considered as base capabilities.

upper and lower limits

The process of determining the bounded context is the process of system division. After the domain division is completed, there are multiple domains, which domains can be independently formed into a system? Which domains can be built together in the same system? It is this step that needs to be determined.

As far as how to determine the bounded context, we should consider several aspects:

  • Rationality of domain division
  • Boundary system construction cost
  • Boundary System Maintenance Costs

common language

Usually, a system has its own independent lingua franca, but it is more hoped to form it into a universal lingua franca and form a consensus, so that communication can form a conceptual unity. In the actual implementation process, we should elaborate and maintain the relevant terms in detail, and accumulate them as domain assets.

context map

Context mapping is the way of interaction between boundary systems. In the strategic design phase, it should be considered from the perspective of architectural rationality.

Strategic Design Case

Here is a simple trading system for strategic analysis, involving the following scenarios:

  • User purchases an item
  • platform for distribution
  • User signs for goods

At this time, the following strategic design can be made:
insert image description here

From the scenario analysis as the starting point, divide the commodity domain, transaction domain, user domain and delivery general domain, and form the corresponding bounded context system; at the same time, considering the connection between domains, the commodity domain and transaction can be combined into one A larger transaction domain.

tactical design

entity

What is an entity? An object defined not by attributes, but by a series of continuous events and identities.

The entity object has a unique identifier, and the identifier can remain consistent after various state changes, while other attributes of the object are not so important relative to the identifier. A content modifier in this state, used to enrich the entity itself.

For an entity, an identifier is a very important concept, just like an ID card is for a person, it is the identity authentication of the entity itself, no matter which system the entity data flows to, the identifier will never change. For example, in the actual scenario, for the order entity, the identifier is the order ID. No matter how the life cycle of the order changes, this ID is always unique throughout the entire track career of the order and in different contexts.

Therefore, as far as the modeling of domain entities is concerned, the identifier must exist and should not be confused with the identification ID of the database, because the database is only the persistence method of the entity. For the persistence of the entity, both relational and document types can be selected. Type, index type database, memory storage can also be selected, and the ID of the data storage medium is called a derived identifier for domain entities.

Taking the order entity as an example, the modeling sample is briefly as follows:

public class OrderInfo {
    
    

    private String orderId;
    private String userId;
    private String addressId;
    private BigDecimal amount;
    private OrderStatus orderStatus;
    
    /* 其他字段信息省略*/

    public String getId() {
    
    
        return this.orderId;
    }
}

For continuous events, the state of the order is the embodiment of the continuous event of the order entity. After multiple state transitions, the identity of the entity will not change, and the content of the changed knowledge entity and the state at a certain stage.

value object

What is a Value Object? An object that describes some characteristic or property but has no conceptual identity.

A value object is a combination of entity attributes for conceptual unification. It combines multiple related attributes into a conceptual whole, which can ensure the clarity of attribute classification and the integrity of the concept, and avoid scattered attributes in entities.

Value objects exist in two forms in code:

  • If the value object is a single attribute, it is directly defined as an attribute of the entity class. For example, an 'Integer' property and an enumeration property can be called value objects. From the perspective of value objects, the index should be defined as a wrapper type object for the basic type properties of entities.
  • If it is a combined concept of multiple scattered attributes, it will be designed as a class. For example, the amount can have two attributes, the amount and the unit, which are essentially the same as 'Integer', except that 'Integer' has been encapsulated into an object, and we need to encapsulate the 'amount' here.

For an order, the amount value object 'Amount' and the user id value object 'addressId' are as follows:

public class OrderInfo {
    
    

    private String orderId;
    private String userId;
    private String addressId;
    private Amount amount;
    private OrderStatus orderStatus;
    
    /* 其他字段信息省略*/

    public String getId() {
    
    
        return this.orderId;
    }

    public static class Amount {
    
    
    	private BigDecimal amount;
    	private String unit;
    }
}

As far as the definition of value objects is concerned, we should classify the business semantics according to the attributes and characteristics of value objects, semantic cohesion, and avoid the existence of value objects whose attributes are irregularly tiled and semantically generalized; of course, from the perspective of domain modeling, We should try our best to use value objects to carry the business and reduce the number of entities, which can reduce the complexity of the business model.

As far as database storage is concerned, the persistence of the value object of the attribute combination can be a certain attribute of the entity, which exists in a serialized form (such as JSON). Of course, it can also be defined as a simulated entity (not Real entities), stored in a dedicated table.

Entities and value objects are the most basic and core objects in the domain. Based on these basic domain objects, diversified business domain logic can be derived.

polymerization

What is aggregation? Aggregation is a collection of related objects. We use aggregation as the unit of data modification. External objects can only refer to one member of the aggregation, which we call the root.

From the perspective of persistence, the consistency rule is applied within the boundary of the aggregation, that is, to ensure the consistency of transactions within the boundary of the aggregation; from the perspective of query, the entire aggregation can be queried, and some entities can also be queried. It needs to be considered from the perspective of actual business conditions and performance conditions.

The aggregation of orders is briefly as follows:

public class OrderInfo extends Aggregate<String> {
    
    
    private String orderId;
    private String userId;
    private String addressId;
    private BigDecimal amount;
    private OrderStatus orderStatus;
    private List<OrderDetail> orderDetailList;
    private OrderExtentInfo orderExtentInfo;
}

At this time, the aggregate root is the order, and the related objects of the aggregation include: order entity, sub-order entity, and order extension entity.

factory

A factory is an encapsulation abstraction for the complex creation logic of objects and aggregates, but it does not assume the responsibilities in the domain model; it is a way to produce target objects just like the factory in the design model.

In actual landing applications, there are usually two applications of factory concepts:

  • Internal attributes such as entities, aggregates, and value objects are used as parameters to construct objects, and clearly identify the parameters required for object creation;
  • Production of complex objects, such as static compilation, dynamic composition (running dependencies), etc.;

The first method takes a simple query condition as an example, as follows:

public class OrderQueryCondition {
    
    

    private String userId;
    private String orderId;
    private OrderStatus orderStatus;

    @DomainFactory
    public static OrderQueryCondition build(String userId, String orderId, OrderStatus orderStatus) {
    
    
        OrderQueryCondition condition = new OrderQueryCondition();
        condition.setUserId(userId);
        condition.setOrderId(orderId);
        condition.setOrderStatus(orderStatus);
        return condition;
    }
}

The second method takes domain events as an example, as follows:

@DomainFactory
public class OrderEventModelFactory {
    
    

    public static OrderEventModel build(OrderEventAction action, OrderInfo orderInfo) {
    
    

        OrderEventModel event = new OrderEventModel();
        event.setAction(action);
        event.setUserId(orderInfo.getUserId());
        event.setOrderId(orderInfo.getOrderId());
        event.setAddressId(orderInfo.getAddressId());
        event.setAmount(orderInfo.getAmount());
        event.setOrderStatus(orderInfo.getOrderStatus());
        return event;
    }
}

resource library

The resource library is usually designed for aggregation to effectively manage the storage and query behavior of the aggregation. It can be a relational database, an index, a document database, an in-memory database, and a collection storage.

In practical applications, that is, the repository we usually see, there are different forms following different practices:

  • From the perspective of aggregation, resource pools and aggregates are mapped one-to-one, that is, one aggregate is one resource pool;
  • From the perspective of entities, the resource library is mapped one-to-one with the entity, that is, one entity has one resource library;

An example of an aggregated angular repository definition is as follows:

public interface OrderInfoRepository {
    
    
    String save(OrderInfo orderInfo);
    OrderInfo queryByOrderId(String userId, String orderId);
}

An example Angular repository definition for an entity is as follows:

public interface OrderInfoRepository {
    
    
    String save(OrderInfo orderInfo);
    OrderInfo queryByOrderId(String userId, String orderId);
}
public interface OrderDetailRepository {
    
    
    void batchInsert(List<OrderDetail> orderDetailList);
    List<OrderDetail> queryByOrderId(String orderId);
}

domain service

What is domain service? When an operation process or conversion process in the domain is not the responsibility of the entity or value object, the operation can be placed in a separate interface, that is, a domain service is encapsulated.

Domain services can exist in the following three ways:

  • Significant business use case execution process
  • Business orchestration of multiple domain objects
  • Reusable application layer logic lower layer

What is a significant business use case? From the use case analysis of the transaction system, such as creating orders, canceling orders, paying orders, etc. are notable business use cases, and their execution process includes business rule verification and core logic processing.

So how to use application services and domain services reasonably in practice, and make domain services thicker and application services thinner? Here is a suggestion to follow a principle: application services only do cross-aggregation and cross-application orchestration, and the underlying domain of the core rules .

domain event

What are Domain Events? It is to model the activity behavior of the aggregate in the domain as a series of discrete event behaviors, usually reflected in the state change of the aggregate.

In practice, it can be divided into in-application events and out-of-application events. In-application events are processed in listener mode, and out-of-application events are processed in message mode.

Guess you like

Origin blog.csdn.net/qq_28851503/article/details/130233050