preface

  • Domain-driven design is a conceptual model. Abbreviated as DDD, it didn’t have much use when it was just born, but when Martin Fuller came up with the idea of microservices, it really showed up.

  • Before we talk about DDD, we need to talk about a few code entity design models

Anemia model

  • We’re all Java developers, and we all know that Java is an object-oriented language.

  • Unfortunately, in the course of our self-learning and online tutorials, Java object oriented functionality was only used when we learned the basics of JavaSE. Most of its functionality [Java objects] has been transferred to the so-called Service layer, while Java entities, or VO, DTO, BO, etc. It is only the carrier of data, which only carries out a few operations on data — data format conversion and data format verification.

  • But we can still remember when we were learning object orientation, such as a User. It has its own name, password, ID, address, mobile phone number and other information. When a User object needs to modify information, it simply calls its internal methods to modify the object’s data.

  • But as we learn, we find that a lot of the time, User objects [or other types of objects] are just carriers of data. Most operations on entities are performed in services. Entities simply map, transfer, and transform data to database tables. And that turns object oriented play into process oriented play. What is procedural orientation — a typical three-tier, four-tier architecture: the Controller calls the Service, the Service calls the DAO, the DAO queries the database, returns the data object, and passes it up. There is no implementation of an operation on an object. That is, the object itself does not have permission to operate on itself, and it gives authority to the Service, which is the so-called anemic model. The function of the entity object is infinitely reduced.

  • The Java object-oriented language, in the end, is like a process oriented language, where the user can’t manipulate himself, but the other person can manipulate him, which is very coupled. You have no right to know what people are doing to you. Isn’t that creepy?

Congestion model

  • The anemic model, for example, corresponds to the hyperemic model.

  • The hyperemia model, which is the counterpart of the anemia model. In the congestion model, each object can have its own field, but also has its own method, that is, in the object-oriented operation itself. In this model, the object has the right to know about itself and can operate on itself, which does not require others to operate the object itself.

  • The congestion model encapsulates the object and its business attributes together. At this time, it is no longer the data carrier of the object, but also the business carrier of the object. The congestion model meets the object – oriented encapsulation characteristics, unlike the anemia model which is process – oriented.

Comparison of anemia model and hyperemia model

  • Anaemia model is class-oriented process. In three-tier and four-tier architectures, its anaemia objects [Entity, BO, PO] are only carriers of data, including some simple formatting and data conversion operations. Its core functions are performed by the external object Service, that is, its own business functions are delegated to others. Fixed thinking, using Controller to call Service, Service to call DAO. Broke the encapsulation, not quite consistent with the single responsibility principle.

  • Congestion model, object oriented. In anemia objects in the model, not only is the carrier of data, and their data of the operator, a congestion object can add and delete operations on yourself, rather than Service to call its function implementation, in this case, the Service of “centralized” weakened and part of the business functions to congestion. Service functions are split to complete the transfer.

  • Advantages and disadvantages: The anemia model is relatively simple, its entities do not need to care about any operations, they only need to carry the data, the Service layer is in charge, all functions are done by the Service. Congestion model is more difficult and complex to design than anaemic model, because it is necessary to consider which behavior methods are needed to operate a model object. As part of Service business is transferred, if the design of congestion model object is not reasonable, Either change the congestion model object (which may result in changes to the upper code), or add methods at the Service layer, where the non-anaemic model is mixed with the anaemic model, and the code logic of the whole system is stretched, which means that the code is different and complex to maintain.

What is a DDD

  • DDD is Domain-Driven Design. Domain-driven design

  • So why do we need to choose DDD? Let’s review some college knowledge first.

  • Computer professional children’s shoes should be learned such an introduction to the software engineering, a subject which contains a variety of software design method, such as waterfall, iterative, spiral, agile, and among them, I the deepest impression is, whether it’s that kind of development model, a stable, powerful system, its design is of high cohesion and low coupling. In other words, I can do a lot of my own functions with a single cohesion, and I don’t need to rely on others to do it. In this way, the coupling degree between the whole system is not high, and it can be properly split and reused.

  • And the aggregate root in DDD, even though we talked about a cohesion above. Here’s an analogy.

  • Within the aggregate root are many entities with their own methods and value objects. So authority moves down, entities operate on themselves, persist data, etc.

  • Compared with the traditional development mode, the traditional development mode is database-driven design [SQL-driven], that is, a system, is designed by the database first, and then according to the database design to complete the corresponding data operation, code writing. In this case, a lot of the business logic is contained in SQL, and a SINGLE SQL can do very little. In this case, when a Service object requires some operations, it will be awkward to write in DAO. This will cause redundancy of SQL, and many SQL statements will differ only by one field.

  • In DDD, all required business scenarios are presented through event storms, domain modeling, product vision, and so on, and attributes and methods included in the domain lock are defined. Domain models are equivalent to reusable business intermediates. New functional requirements are developed based on these domain models defined previously.

  • In THE DDD design, the Service is not removed, but its functionality is weakened. Why?

    • Service is impossible to get rid of, as I understand it now, because each domain model is its own operation, and the Service class is responsible for communicating with Repository, and the xxxService is responsible for communicating with xxxRepository, calling the xxxRepository method, The data in the database is captured, converted to a domain model, the business logic is done by domain model objects, and the data is persisted by calling xxxRepository.

    • The Service class is responsible for cross-service invocation and aggregation of domain models. DDDS work with microservices, that is, methods that need to invoke domain model objects of other services. Cross-service communication is done in the Service

    • Services are responsible for some of the non-functional and third-party system interactions. Idempotent, transactional, emailing, messaging, logging, calling other systems’ RPC interfaces, etc., can all be placed in the Service class.

  • Based on the congestion model of DDD development mode, Service is modified to congestion model, but the Controller layer and Repository are still anaemic model, do you need congestion domain modeling?

    • No, because the domain modeling of the Service already does most of the work. In addition, Entity has a very short life cycle and generally ends when it is passed to Service, while VO and DTO are only carriers of data and do not need to carry out many complex operations on data. Functionally, it contains no business logic, only data.

DDD build process

Building domain knowledge
  • In plain English, it means to understand the domain objects that can be refined in this domain (insurance domain, e-commerce domain, etc.), that is, what fields and operations this object can have
The common language
  • Because different industries focus on different points, for example, we programmers to connect with customers, we are thinking about code implementation, but customers are thinking about functions. This can lead to mismatches, and in this case, use common language — that is, both sides can understand, both can fully express and be expressed.
Model-driven design
  • Through event storm, common language analysis and product vision, the next step of model-driven design is to design the scope of the model and its functions
Model diagram
  • When we design multiple models, there may be coupling between models, and we need to connect the coupling lines between models so that we can know where we need to use what
Building a Layer architecture
  • The hierarchy, in this case, is the logical and physical layering of code. It’s already DDD logic

  • And, in general, a model can become a microservice, but on a case-by-case basis

Entity objects and value objects
  • Entities are similar to the concept in object orientation, and are brought up here again because they are fundamental elements of the domain model. In the domain model, entities should have unique identifiers, and entities should be considered from the beginning of the design. It is also important to decide whether to create one.

  • A value object is different from a numeric variable in programming. It is simply an entity without a unique identifier. For example, if two harvest addresses have exactly the same information, it is a value object, not an entity. Value objects can be shared in the domain model, they should be “immutable” (read only), and a copy of the value object can be passed as a parameter when it is needed elsewhere.

service
  • Not all of these points can be implemented through the model, and this is where services are needed to further deepen and refine the functionality.

  • Services exist to provide a simple approach to the domain model

  • The characteristics of

    • The behavior embodied in a service must not belong to any entity or value object, but it falls within the scope of the domain model

    • The behavior of a service must involve multiple other objects

    • The operation of the service is stateless

The module
  • To reduce complexity by organizing unified model concepts.

  • Modules should have consistent external interfaces to be called by other modules. For example, if there are three objects in module A, module B should not operate directly on these three objects, but on exposed interfaces. Modules are also carefully named to reflect the domain model in depth.

Aggregation and aggregation roots
  • Aggregation is seen as a combination of model elements that define the relationships and boundaries of the model. Each aggregation has a root, which is an entity and is uniquely accessible externally. As such, aggregation guarantees the immutability of multiple model elements, because other models refer to the root of the aggregation. The only way to change other objects is through the root of the aggregation. If the root is gone, then the other objects in the aggregation will also be gone.
The factory
  • In complex applications, entities and aggregations are often very complex, so constructing objects through constructors, that’s complicated. A factory encapsulates the details of creating an object and implements dependency inversion.

  • This is also true for aggregation (when an aggregation root is created, other objects can be created automatically). The factory was probably first known in design patterns, and indeed, the factory mentioned here is the same concept.

  • Note that it is not appropriate to use the factory when:

    • The constructor is simple

    • Constructing objects does not depend on the creation of other objects

    • Use the policy pattern

warehouse
  • warehouseEncapsulating the logic of getting objects, domain objects do not need to interact with the underlying database, it only needs to get objects from the repository. Repositories can store references to objects, and when an object is created, it may be stored in the repository so that it can be fetched from the repository the next time. If the data requested by the user is not in the repository, it is fetched from the database, reducing the number of low-level interactions

Unified non-null validation

  • NonEmptyValidationConfig

  • What is uniform non-null validation?

  • Why do YOU need uniform non-null validation?

doubt

  • The domain model operates on its own, and if some SQL is not implemented (as it should be), implement the Repository method. [inevitable]

  • Lack of practice, the implementation of its function is not very familiar.

The resources

  • Analyses the DDD (domain driven design) : www.jianshu.com/p/b6ec06d6b…

  • Command and query separation of responsibility (CQRS) mode: docs.microsoft.com/zh-cn/azure…

  • Implementing Domain-Driven Design by Vaughn Vernon