In recent years DDD (domain-driven Design) concept is very hot, it uses a unified language to express business processes and technical architecture, convenient domain experts, technology development exchanges to reach consensus, can be considered as a solution to a complex business.

We use DDD to understand the core issues of the business when facing business change, that is, to conduct targeted separation of concerns to find relatively cohesive business activities to form sub-problem areas. The subproblem domain is relatively stable inside, that is, the frequency of future changes will not be very high, and the boundary of the subproblem is easy to change. In other words, the core of DDD lies in the identification and demarcation of domain boundaries.

For example, in the logistics system, the calculation of two routes is relatively fixed, but the route selection based on parcel information often changes with business conditions.

Let’s focus on the concepts of DDD domain models

entity

Objects with business attributes and business behavior, carrying unique identifiers, and with a life cycle. For example, in the order domain, the order is abstracted as an entity, whose life cycle includes the entire cycle from placing the order to finally receiving the goods.

The value object

Has only attribute information and does not carry objects with unique identifiers.

Aggregate, aggregate root

Organizing entities and value objects together to work together is called aggregation.

The aggregation root is also called the root entity, and the communication between aggregates is managed by the aggregation root, which accepts external tasks and requests in a manner associated with the aggregation root ID. That is, if you need to access other aggregated entities within an aggregate, you need to access the aggregate root first and then navigate to the aggregate internal entity; external objects cannot directly access the aggregate internal entity.

The aggregate root typically corresponds to a Repositories.the hierarchical model prior to DDD typically corresponds to a Dao with a DO object.

Generally speaking, one business use case corresponds to one transaction, and one transaction corresponds to one aggregate root, meaning that only one aggregate root can be operated on at a time. If a business process involves multiple aggregate root operations, the different aggregate roots can be decoupled through domain events, but this is the ultimate consistency.

Field service

Domain services are those that interact with entities, but are not wholly owned by a single entity or aggregate, which are generally abstracted to serve the domain.

For example, in the field of account management, it is inappropriate to regard the business behavior of transfer as an account behavior since the transfer itself occurs on two accounts. It is also awkward to abstract the transfer noun as an entity, since the transfer is based on the account.

Application service

Application services provide interfaces directly to the outside world on top of domain services. Compared with the facade-Serviece-DAO model before DDD, the application services layer in DDD is thinner and more adaptable to business changes because domain services and entities are relatively stable.

Repositories

A similar concept for Repositories is Dao, except for the coarse-grained abstraction Repositories, which in DDD corresponds to aggregations whereas Dao corresponds to DO classes or entities.

Why is Repositories necessary? This is because obtaining aggregates is not a simple operation, Dao. Get, which is encapsulated by Repositories. Domain services and entity actions can be accessed by simple calls to the Repositories method, regardless of the data storage medium. In general, the most common methods for Repositories are GET and Save, the former for query scenarios and the latter for save update scenarios.

For example, in the Order Notification business scenario (Business Services), where the advice as a service should not hold specific order information, we would need an abstraction from Repositories to create an aggregate query for the order, i.e. a repO for the order, with specific query logic in the REPO.

Bounded context

A bounded context defines the boundary of a domain model, and each domain model has its own domain boundary, within which is a bounded context.

A bounded context encapsulates the domain model and services of a relatively independent subdomain. The bounded context map describes the integration call relationship between the various sub-domains, which is consistent with the division of microservices to provide business capability-oriented, autonomous, independent deployment units.

DDD is already decomposed for business capabilities by subdomain, and bounded context is further decomposed in solution domain. Of course, we cannot completely assume that there is a strict one-to-one relationship between a subproblem domain and a bounded context, but most of the time a subproblem domain is designed to be one or more bounded contexts. Subdomains and bounded contexts are mutually reinforcing in a sense, focusing on distinguishing the problem domain from the solution domain, which is the most difficult part of landing DDD, and also the watershed for judging an architect’s ability to progress.

With that said, let’s look at their respective positions in the DDD hierarchy:

Finally, looking at domain events, DDD advocates business collaboration between aggregations in the form of domain events, which abstracts the actions of upstream aggregation processes through events.

In DDD, two concepts related to domain events are event traceability and CQRS.

Event traceability is not concerned with the current state, but with events that are constantly changing. The advantage of event traceability is that it records all historical events, which facilitates data audit and playback. Better scalability, conflict reduction, easy to optimize performance.

CURS is command query separation, or read/write separation, in which writes and queries correspond to different data models. The general implementation scheme is to send events after data writing, so that consumers can construct their own read view data according to the time. Read and write are decoupled and can be optimized separately.

DDD domain concept is basically the above mentioned, but in the actual business implementation of DDD, we will encounter some problems, such as the simplest is to have an object, there is no business behavior, but the subsequent business behavior may be, this in the end is abstracted as a value object or entity? These require some experience or tradeoff. Note that landing DDDS are allowed as long as they do not violate the larger DDD concept and can be used tradeoff to abstract or isolate some of the change points so that subsequent changes to those change points can be controlled on the impact surface.

Recommended reading

  • How to solve the problem of large paging query
  • From intrusive Service governance to Service Mesh
  • Blah blah blah, service governance is what
  • Application of token bucket, funnel and cold start current limiting in Sentinel
  • Seata AT mode flow