Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

Time:2021-1-27

This is the fourth article in the “domain driven design practice road” series. It introduces microservices from the disadvantages of single architecture. Combined with the concept of domain driven, it introduces how to divide microservices, design domain model, and shows the overall microservice system architecture design. Combined with the idea of hierarchical architecture, hexagon architecture and clean architecture, this paper shows the program structure design of a micro service under the background of actual use scenarios.

1、 Disadvantages of single architecture

Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

Example of monomer structure (quoted from Internet)

Generally, in the early stage of business development, the whole application involves less functional requirements, which is relatively simple. The application of single architecture is relatively easy to deploy, test, and achieve horizontal expansion.

However, with the increasing demand, more and more people join the development team, and the code base is also expanding rapidly. Gradually, the single application becomes more and more bloated, the maintainability and flexibility are gradually reduced, and the maintenance cost is higher and higher.

The following is an analysis of the disadvantages of single architecture application:

1. High complexity

At the beginning of the project, someone should be able to know all the functions and implementation of the application like the palm of his hand. With the increase of business requirements, all kinds of business processes are intricately kneaded together, and the whole system becomes huge and complex, so that few developers know the details of each function and business process.

This will make the new business needs assessment or abnormal problem location will take more time, but also contains unknown risks. What’s worse, this extreme complexity creates a vicious circle, and every change makes the system more complex and difficult to understand.

2. More technical debt

As time goes on, requirements change, and personnel change, the technical debt of the application will gradually form and accumulate. For example, the team must use the same technology stack for a long time, and it is difficult to adopt new frameworks and programming languages. Sometimes when you want to introduce some new tools, you need to maintain multiple sets of technical frameworks at the same time, such as hibernate and mybatis, which makes the cost higher.

3. It is difficult to isolate errors

Because all functional modules of a business project are undertaken on an application, including core and non core modules, any module or small detail, due to unreasonable design, poor code quality and other reasons, may cause the collapse of the application instance, thus affecting the business. The fundamental reason is that the code of core and non core functions run in the same environment.

4. The cost of collaboration among project teams is high, and the business response is getting slower and slower

There are bound to be similar functional modules among multiple similar business projects. If the single mode is adopted, it will bring repeated function construction and maintenance. Moreover, sometimes they need to interact with each other, and the cost of getting through the interaction integration and cooperation between individual systems also needs to pay extra.

Moreover, when the project is large enough, different modules may be maintained by different teams. The conflict of iterative joint debugging and code merging branches will affect the whole development progress, which makes the business response speed slower and slower.

5. High expansion cost

With the development of business, when the bottleneck of business processing appears in the system, it is often caused by the high load of one or several functional modules. However, because all functions are packaged together, when such problems occur, we can only load them separately by adding application instances, and there is no way to expand the service capacity of individual functional modules, thus bringing resources The cost of additional configuration is high.

In view of the above pain points, in recent years, more and more Internet companies use “micro service” architecture to build their own business platform, and “micro service” has also been affirmed by more and more technical personnel.

Microservice is actually an evolved form of SOA, which is not essentially different from the methods and principles of SOA. The core value of SOA concept is that loosely coupled services bring business reuse. According to the dimension of business rather than technology, micro services are divided according to the principle of high cohesion and low coupling, which is in line with the concept advocated by domain driven design.

2、 Microservice design

1. Micro Service Division

In a broad sense, domain is what an organization does and what it contains. Each organization has its own business scope and way of doing things, and this business scope and the activities carried out in it are areas.

The concepts of sub domain and bounded context of DDD can well match the services in microservice architecture. Moreover, the concept of autonomous team responsible for service development in microservice architecture is consistent with the concept that each domain model in DDD is developed by an independent team. DDD advocates dividing systems according to business areas. Microservice architecture emphasizes to deal with system complexity by dividing and ruling from business dimensions. The architecture designed by skipping business architecture does not focus on business response, which may be a big mud ball. It is very painful when facing demand iteration or responding to market changes.

The core demand of DDD is to map the business architecture to the system architecture. When adjusting the business architecture in response to business changes, the system architecture will also change. Microservices pursue the reuse of business level, and the designed system architecture is consistent with the business; on the technical architecture, the system modules are fully decoupled, and the appropriate technical architecture can be freely selected, and the technology and data can be decentralized managed.

Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

Taking the resource ordering system of e-commerce as an example, typical business use case scenarios include viewing resources, purchasing resources, and querying purchased resources of users.

Domain Driven defines a separate domain model for each sub domain, and sub domain is a part of the domain. From the perspective of business, we analyze the business use case scenarios that we need to cover. With the idea of high cohesion and low coupling, combined with single responsibility principle (SRP) and closure principle (CCP), we divide the user management sub domain, resource management sub domain, order sub domain and payment sub domain from the perspective of business domain Four subdomains.

Each subdomain corresponds to a bounding context. Bounded context is a kind of conceptual boundary in which domain model works. Each bounded context has its own common language. Bounded context allows you to put an explicit, clear boundary around the domain model. Of course, the bounding context contains more than just the domain model. When using the microservice architecture, each bounding context corresponds to a microservice.

2.domain model

Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

Aggregation is a cluster of domain objects within a boundary, which can be regarded as a unit. It consists of root entity and one or more other entities and value objects. Aggregation decomposes the domain model intoblockEach aggregation can be processed as a unit.

The aggregation root is the only part of the aggregation that can be referenced by external classes. The client can only update the aggregation by calling methods on the aggregation root.

Aggregation represents a consistent boundary. For a well-designed aggregation, no matter what business requirements change, all invariant conditions in aggregation are consistent in a single transaction. An important empirical design principle of aggregation is to modify only one aggregation instance in a transaction. When you update an aggregation, you need to update the whole aggregation instead of a part of the aggregation, otherwise it is easy to cause consistency problems.

For example, a and b purchase online at the same time, use the same order, and realize that they are buying more than the budget. At this time, a reduces the number of snacks, B reduces the number of bread, and two consumers execute the transaction simultaneously. Then the total order amount may be lower than the minimum order limit, but for a consumer, it meets the minimum order limit. Therefore, update operations should be performed from the perspective of aggregation root, which will enforce consistent business rules.

In addition, we should not design too large aggregation. When dealing with the “Big Mac” object composed of large aggregation, it is easy to have different use cases and need to modify a part of it. Because the consistency constraint considered in aggregation design affects the whole aggregation, the modification of aggregation will cause changes to the aggregation as a whole. If optimistic concurrency is adopted, it will be easy to produce In addition, it will affect the performance and scalability of the system.

When using large aggregation, in order to complete a basic operation, hundreds of objects need to be loaded into memory together, resulting in a waste of resources. Therefore, small aggregation should be used as far as possible. On the one hand, the root entity is used to represent the aggregation, which only contains the minimum number of attributes or value type attributes. Here, the minimum number represents the minimum set of attributes required. Properties that must be consistent with other properties are required.

In aggregation, if you think that some included parts should be modeled as an entity, think about whether this part will change over time, or whether it can be completely replaced. If you can replace them all, you can model them as value objects instead of entities. Because the value object itself is immutable and can only be replaced completely, it is safer to use. Therefore, in general, the value object is preferred. In many cases, many concepts modeled as entities can be reconstructed into value objects. Small aggregation can also help the successful execution of transactions, that is, it can reduce transaction commit conflicts, which can not only improve the performance and scalability of the system, but also enhance the availability of the system.

In addition, the direct reference of aggregation is realized by the unique identifier rather than by the object reference, which not only reduces the usage space of aggregation, but also realizes the direct loose coupling of aggregation. If aggregation is a part of another service, there will be no cross service object reference problem. Of course, objects within aggregation can refer to each other.

The main principles of aggregation can be summarized as follows:

  1. Only aggregate roots are referenced.
  2. Reference other aggregations with a unique identity.
  3. Only one aggregation can be created or modified in a transaction.
  4. Use final consistency outside the aggregation boundary.

Of course, in the actual use process, for example, a business use case needs to obtain a domain object in the aggregation, but the acquisition path of the domain object is cumbersome. In order to be compatible with this special scenario, the attribute (entity or value object) in the aggregation can be directly returned to the application layer, so that the application layer can directly operate the domain object.

We often encounter that when we execute command methods on one aggregation, we need to execute additional business rules on other aggregations, and try to use final consistency, because final consistency can process each link step by step according to aggregation dimension, so as to improve the throughput of the system. For a business use case, if the data consistency should be guaranteed by the user executing the use case, transaction consistency can be considered. Of course, other aggregation principles still need to be followed at this time. If other users or systems are needed to ensure data consistency, the final consistency is used. In fact, the ultimate consistency can support most business scenarios.

Based on the above division of business sub domain of e-commerce resource ordering system, we design resource aggregation, order aggregation, payment aggregation and user aggregation. Resource aggregation and order aggregation are associated by resource ID, order aggregation and payment aggregation are associated by order ID and user ID, and payment aggregation and user aggregation are associated by user ID. The resource aggregation root contains multiple resource package value objects, and one resource package value object contains multiple preview value objects. Of course, in the actual development process, according to the actual situation, the aggregation root can also contain entity objects. Each aggregation corresponds to a micro service. For a particularly complex system, a sub domain may contain multiple aggregations, that is, multiple micro services.

3.Architecture design of microservice system

Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

Based on the above analysis of the sub domain of e-commerce resource ordering system, the server background uses four micro services: user service, resource service, order service and payment service. The API gateway in the figure above is also a service, and can be regarded as the application layer in DDD, similar to the facade pattern in object-oriented design.

As the unified facade of the whole back-end architecture, it encapsulates the internal architecture of the application and is responsible for the task coordination of business use cases. Each use case corresponds to a service method, calls multiple micro services and returns the aggregation results to the client. It may also have other responsibilities, such as authentication, access authorization, caching, rate limiting, etc. Taking the query of purchased resources as an example, API gateway needs to query the order service to obtain the list of purchased resource IDs of the current user, then query the resource service according to the list of resource IDs to obtain the detailed information of purchased resources, and finally return the aggregation result to the client.

Of course, in the process of practical application, we can also divide the API gateway into several different services according to the complexity of the API request from the business point of view, so as to prevent it from returning to the single bottleneck of the API gateway.

In addition, sometimes some sub domains separated from the perspective of business domain are relatively small. From the perspective of resource utilization, it is a bit thin to put them into a micro service alone. At this time, we can break the concept that a bounded context corresponds to a microservice, merge multiple subdomains into the same microservice, and realize the task coordination of multiple subdomains by the microservice’s own application layer.

Therefore, in our system architecture, there may be micro service level small application layer and API gateway level large application layer scenarios. Theory is theory, but it needs to be flexibly applied in combination with the actual situation.

3、 Application of Domain Driven concept in single microservice design

1.Architecture selection analysis

Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

Hierarchical architecture diagram (quoted from Internet)

Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

Hexagon architecture (quoted from Internet)

Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

Clean architecture (quoted from Internet)

The concentric circles in the above clean architecture diagram represent different levels of the software system. Generally, the closer to the center, the higher the software level.

The dependency rules of clean architecture tell us that the dependencies in source code must only point to the inner layer of concentric circles, that is, from low-level mechanism to high-level strategy. In other words, any code belonging to the inner circle should not involve the code in the outer circle, especially the code in the inner circle should not refer to the name declared by the code in the outer circle, including functions, classes, variables and all other named software entities. Similarly, the data format used by the outer circle should not be used by the code in the inner circle, especially when the data format is generated by the frame of the outer circle.

In short, you should not let any changes in the outer circle affect the code of the inner circle. The business entity layer encapsulates the most common and high-level business logic in the whole business field. They should belong to the part of the system that is not easily affected by external influences. In other words, our core domain model is relatively stable in general. It should not be because of the changes in the outer infrastructure, such as the selection of data storage technology, or the UI display mode And so on, so we need to make corresponding changes.

In the past project experience, most students are also familiar with the hierarchical architecture, including the display layer, application layer, domain layer and infrastructure layer. An important advantage of hexagon architecture is that it separates business logic from the logic of presentation layer and data access layer contained in adapter. Business logic does not depend on presentation layer logic or data access layer logic. Because of this separation, it is much easier to test business logic separately.

Another advantage is that business logic can be invoked through multiple adapters, each of which implements a specific API or user interface. Business logic can also call multiple adapters, each of which calls a different external system. So hexagon architecture is a good way to describe the architecture of each service in microservice architecture.

According to our specific practical experience, for example, in our usual projects, MySQL and redis are the most common storage structures, and they are rarely changed to other storage structures. In this paper, the idea of hierarchical architecture and hexagon architecture is integrated. On the one hand, we hope that our microservice design structure will be more beautiful. On the other hand, we hope that on the basis of the existing programming habits, we can easily accept the new idea of clean architecture.

The implementation of microservice in our project combines the idea of hierarchical architecture, hexagon architecture and clean architecture, and takes the actual use scenario as the background. The application structure chart is as follows.

Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

As can be seen from the figure above, our application consists of application layer, domain layer and infrastructure layer. The facade interface of domain service needs to be exposed to other three-party systems, so it is encapsulated as a module. Because we are generally used to the hierarchical architecture mode to build the system, we name each layer according to the hierarchical architecture.

From the perspective of hexagon architecture, the application layer is equivalent to the inbound adapter, and the infrastructure layer is equivalent to the outbound adapter. So in fact, the application layer and the infrastructure layer belong to the same outer layer and can be considered to be in the same layer.

The facade module is actually separated from the domain layer. From the perspective of clean architecture, the domain layer is the kernel business entity, which encapsulates the most common and high-level business logic in the whole business field. Generally, the core domain model is relatively stable and does not change due to external influence. Facade is the domain service capability exposed to the outside world by microservices. Generally, the setting of interface should conform to the boundary of current domain service, so facade module belongs to kernel domain layer.

The implementation of facade interface is in impl part of application layer, which is in line with the idea that the outer layer of clean architecture depends on the inner layer. For impl input port and inbound adapter, different protocols and technical frameworks can be adopted, such as Dubbo or HSF. The composition of each module is explained one by one.

2. Domain layer

Factory

Object creation itself is a major operation, but the created object is not suitable for complex assembly operations. Mixing these responsibilities together can lead to poorly designed designs that are difficult to understand. Let the customer be directly responsible for creating objects will make the customer’s design into confusion, and destroy the encapsulation of assembly objects, and lead to too close coupling between the customer and the implementation of the created objects.

The creation of complex objects is the responsibility of the domain layer, but this task does not belong to the objects used to represent the model. Therefore, we usually use a separate factory class or provide an interface to construct domain objects in domain services to create domain objects.

Here, we choose to add a domain object creation interface to the domain service to assume the role of factory.

/**
 *Description: resource domain service
 *
 * @author Gao Ju
 * @date 2020/7/27
 */
public class ResourceServiceImpl implements ResourceService {
 
    /**
     *Create resource aggregation model
     *
     *@ param resourcecreatecommand create resource command
     * @return
     */
    @Override
    public ResourceModel createResourceModel(ResourceCreateCommand resourceCreateCommand) {
        ResourceModel resourceModel = new ResourceModel();
        Long resId = SequenceUtil.generateUuid();
        resourceModel.setResId(resId);
        resourceModel.setName(resourceCreateCommand .getName());
        resourceModel.setAuthor(resourceCreateCommand .getAuthor());
        List<PackageItem> packageItemList = new ArrayList<>();
        ...
        resourceModel.setPackageItemList(packageItemList);
        return resourceModel;
    }
}

Repository

Generally, the aggregate instance is stored in the resource library, and then the same instance is obtained through the resource library.

If an aggregation is modified, the change will be persisted by the repository. If an instance is removed from the repository, it cannot be retrieved from the repository.

The resource pool is created for the aggregation dimension, and the aggregation type and resource inventory are in a one-to-one relationship.

In short, a repository is an encapsulation of aggregated CRUD operations. What kind of storage facilities mysql, mongodb or redis are used in the repository is actually not aware of the domain layer.

Domain Driven Design (DDD) practice (4): application of domain driven in microservice design

Resource repository composition diagram

In our project, MySQL is used as the persistent storage of the resource repository. In the figure above, each do corresponds to a database table. Of course, you can also use other storage structures or design other table structures. The specific processing flow is encapsulated by the repository. For domain services, it only perceives the crud operation of the resource aggregation dimension. The example code is as follows.

/**
 *Description: resource warehouse
 *
 * @author Gao Ju
 * @date 2020/08/23
 */
@Repository("resourceRepository")
public class ResourceRepositoryImpl implements ResourceRepository {
 
    /**
     *Resource mapper
     */
    @Resource
    private ResourceMapper resourceMapper;
 
    /**
     *Mapper
     */
    @Resource
    private PackageMapper packageMapper;
 
    /**
     *Resource package preview mapper
     */
    @Resource
    private PackagePreviewMapper packagePreviewMapper;
 
    /**
     *Create order information
     *
     *@ param resourcemodel resource aggregation model
     * @return
     */
    @Override
    public void add(ResourceModel resourceModel) {
        ResourceDO resourceDO = new ResourceDO();
        resourceDO.setName(resourceModel.getName());
        resourceDO.setAuthor(resourceModel.getAuthor());
        List<PackageDO> packageDOList = new ArrayList<>();
        List<PackagePreviewDO> packagePreviewDOList = new ArrayList<>();
        for (PackageItem packageItem : resourceModel.getPackageItemList()) {
            PackageDO packageDO = new PackageDO();
            packageDO.setResId(resourceModel.getResId());
            Long packageId = SequenceUtil.generateUuid();
            packageDO.setPackageId(packageId);
            for (PreviewItem previewItem: packageItem.getPreviewItemList()) {
                PackagePreviewDO packagePreviewDO = new PackagePreviewDO();
                ...
                packagePreviewDOList.add(packagePreviewDO);
            }
            packageDOList.add(packageDO);
        }
 
        resourceMapper.insert(resourceDO);
        packageMapper.insertBatch(packageDOList);
        packagePreviewMapper.insertBatch(packagePreviewDOList);
    }
}

You may have doubts. According to the idea of clean architecture, the interface of repository should be defined in the domain layer, and the implementation of repository should be defined in the infrastructure layer. In this way, it is in line with the inner layer with higher stability of outer layer dependence.

Combined with our actual development process, it is not easy to make a big adjustment after selecting the storage structure or setting the table structure, so we use it according to the usual hierarchical structure. The domain layer directly depends on the infrastructure layer to reduce the extra cost of coding.

Domain service

Domain Driven emphasizes that we should create a domain model, encapsulate the data and behavior together, and map the domain model to the business objects in the real world. Each category has a clear division of responsibilities, and the domain logic is distributed to each domain object.

A service in a domain represents a stateless operation, which is used to implement a domain specific task. When an operation is not suitable to be placed on a domain object, the best way is to use domain services.

A brief summary of the responsibilities of domain service itself is to provide interactive interfaces for the upper application layer by concatenating domain objects and resource databases, generating and publishing domain events, executing transaction control and a series of domain object behaviors.

/**
 *Description: order domain service
 *
 * @author Gao Ju
 * @date 2020/8/24
 */
public class UserOrderServiceImpl implements UserOrderService {
 
    /**
     *Order warehousing
     */
    @Autowired
    private OrderRepository orderRepository;
 
    /**
     *Message publisher
     */
    @Autowired
    private MessagePublisher messagePublisher;
 
    /**
     *Order logic processing
     *
     *@ param userorder user order
     */
    @Override
    public void createOrder(UserOrder userOrder) {
        orderRepository.add(userOrder);
        OrderCreatedEvent orderCreatedEvent = new OrderCreatedEvent();
        orderCreatedEvent.setUserId(userOrder.getUserId());
        orderCreatedEvent.setOrderId(userOrder.getOrderId());
        orderCreatedEvent.setPayPrice(userOrder.getPayPrice());
        messagePublisher.send(orderCreatedEvent);
    }
}

In the process of practice, for the sake of simplicity and convenience, we still use the anemia domain model, and put the domain object’s own behavior and the behavior that does not belong to the domain object into the domain service.

Most scenario domain services return aggregate roots or simple types. Some special scenarios can also return entity or value objects contained in aggregate roots to callers. Domain services can also operate multiple domain objects and aggregations at the same time to convert them into other outputs.

In our actual use scenario, the domain is relatively simple. Domain services only operate one domain object and only operate one aggregation. Application services coordinate multiple domain objects.

3. Domain event

In the context of domain driven design, domain events are published when aggregations are created or when other significant changes occur. Domain events are triggered when the aggregation state changes.

When naming a domain event, the past participle of the verb is generally selected, because when the state changes, it means that the current event has occurred. Each attribute of a domain event is an original type value or value object, such as event ID and creation time. Event ID can also be used as idempotent.

Conceptually, domain events are released by aggregations, which know when their state changes, so they know the events to be published.

Because aggregation can’t use dependency injection, we need to pass the message publisher to aggregation in the form of method parameters, but this interweaves the infrastructure and business logic, which is contrary to our decoupling design principle.

A better way is to publish the event in the domain service, because the service can use dependency injection to obtain the reference to the message publisher, so as to easily publish the event. As long as the state changes, the aggregation generates events. The return value of the aggregation method includes a list of events and returns them to the domain service.

Saga is a mechanism to maintain data consistency in microservice architecture. Sage consists of a series of local transactions. Each local transaction is responsible for updating the private database of its service, and coordinating a series of local transactions through asynchronous messages, so as to maintain the final data consistency among multiple services. Saga includes collaborative and choreographic,

We implement distributed transactions in a collaborative way, and the published domain events are sent to saga participants in the form of command messages. If domain events are self publishing and self consuming and do not rely on message middleware implementation, event bus mode can be used to manage them. The following is an example of the process of purchasing resources.

The process of purchasing resources

  • After submitting the order creation request, orderservice creates a userorder in the paying state and publishes the ordercreated event.
  • Userservice consumes the ordercreated event, verifies whether the user can place an order, and publishes the userverified event.
  • Paymentservice consumes the userverified event, performs the actual payment operation, and publishes the paysuccess event.
  • Orderservice receives the paysuccess event and changes the userorder state to pay_ SUCCESS。

Compensation process

  • Paymentservice consumes the userverified event, performs the actual payment operation, and publishes the payfailed event if the payment fails.
  • Orderservice receives the payfailed event and changes the userorder state to pay_ FAILED。

In saga’s concept,

The first step is called a compensatory transaction, because later steps may fail.

The third step is called critical transaction because it is followed by steps that cannot fail. Step 4 is called a repeatable transaction because it always succeeds.

/**
 *Description: domain event base class
 *
 * @author Gao Ju
 * @date 2020/7/27
 */
public class BaseEvent {
    /**
     *Message unique ID
     */
    private String messageId;
 
    /**
     *Event type
     */
    private Integer eventType;
 
    /**
     *Event creation time
     */
    private Date createTime;
 
    /**
     *Event modification time
     */
    private Date modifiedTime;
}
 
 
/**
 *Description: order creation event
 *
 * @author Gao Ju
 * @date 2020/8/24
 */
public class OrderCreatedEvent extends BaseEvent {
 
    /**
     *User ID
     */
    private String userId;
 
    /**
     *Order ID
     */
    private String orderId;
 
    /**
     *Pay the price
     */
    private Integer payPrice;
}

4. Facade module

Facade and domain belong to the same layer. Some classes provided for three parties are defined in the facade. For example, the resource type enumeration categoryenum limits the scope of three party resources, and then the domain relies on the definition of enum in the facade.

In addition, according to dimit’s law and the principle of telling rather than asking, the client should know as little as possible about the internal structure of the service object, and tell the service object what to do by calling the public interface of the service object.

Therefore, we should not disclose the domain model to other micro services. When providing facade services, we should wrap a data transfer object (dto) according to the domain object to realize the interaction with external three-party systems, such as resourcedto in the figure above.

5.Application layer

Application layer is the entrance of business logic, which is called by inbound adapter. The implementation of facade, the execution of timing tasks and the message listening processor all belong to the inbound adapter, so they are all located in the application layer.

Normally, a micro service corresponds to an aggregation. In practice, in some scenarios, a micro service can contain multiple aggregations, and the application layer is responsible for the task coordination of use case flow. The domain service dependency is injected into the application layer, and the domain business rules are executed through the domain service. The application layer also handles non domain operations such as authorization, authentication, caching, anti-corrosion conversion between dto and domain objects.

/**
 *Description: order facade
 *
 * @author Gao Ju
 * @date 2020/8/24
 */
public class UserOrderFacadeImpl implements UserOrderFacade {
 
    /**
     *Order service
     */
    @Resource
    private UserOrderService userOrderService;
 
    /**
     *Create order information
     *
     *@ param orderpurchaseparam order transaction parameters
     * @return
     */
    @Override
    public FacadeResponse<UserOrderPurchase> createOrder(OrderPurchaseParam orderPurchaseParam ) {
        UserOrder userOrder = new UserOrder();
        userOrder.setUserId(request.getUserId());
        userOrder.setResId(request.getResId());
        userOrder.setPayPrice(request.getPayAmount());
        userOrder.setOrderStatus(OrderStatusEnum.Create.getCode());
        userOrderService.handleOrder(userOrder);
        userOrderPurchase.setOrderId(userOrderDO.getId());
        userOrderPurchase.setCreateTime(new Date());
        return FacadeResponseFactory.getSuccessInstance(userOrderPurchase);
    }
}

6. Infrastructure layer

The responsibility of the infrastructure is to provide technical support for other parts of the application. The Dao module interacting with database, the cache module interacting with redis cache and local cache, the interaction with parameter center and three party RPC service, the message framework and the message publisher are all encapsulated in the infrastructure layer.

In addition, the utility module and exception class used in the program are encapsulated in the infrastructure layer.

From the perspective of hierarchical architecture, domain layer can rely on infrastructure layer to interact with other peripherals. In addition, no matter from the upper application layer of hierarchical architecture or from the perspective of hexagon architecture, the input port and adapter application can rely on the infrastructure layer as the output port and adapter at the bottom or in the same layer, such as calling util or exception module.

4、 Concluding remarks

In fact, whether it’s service-oriented architecture, SOA, micro service, domain driven, or middle platform, its purpose is to say that when we do architecture design, we should start from the business perspective and divide the business fields involved based on the idea of high cohesion and low coupling, so as to achieve the maximum and reasonable business reuse.

This is not only convenient to provide professional and stable business services, but also conducive to business precipitation and sustainable development. Under the business is the realization of system based on technology. Technology makes business and business leads technology. The two complement each other and contribute to social progress together.

5、 References

  • [1] Eric Evans, translated by Zhao Lisheng, Hai Yan and Liu Xia, people’s Posts and Telecommunications Press
  • [2] Realizing domain driven design, written by Vaughn Vernon, translated by Teng Yun, Zhang Yishen, electronic industry press
  • [3] Design pattern of microservice architecture, written by Chris Richardson, translated by Yu Yong, China Machine Press
  • [4] The way to clean architecture, written by Robert C. Martin, translated by sun Yucong, electronic industry press
  • [5] The transformation of enterprise IT architecture: Alibaba’s China Taiwan strategic thinking and architecture practice, edited by Zhong Hua, China Machine Press
  • [6]DDD practice (2): event driven and cqrs, vivo Internet technology
  • [7]Practice of Domain Driven Design in Internet business development, meituan technical team

By angel Gao