If the domain-driven design based on the object-oriented design paradigm is followed and used to cope with the complex business logic, then the congestive design model that emphasizes the domain model has become an indisputable fact in the community. I regard Eric's tactical design elements such as EnTIty, Value Object, Domain Service, Aggregate, Repository, and Factory as design models. Of these, only EnTIty, Value Object, and Domain Service can express domain logic.
To avoid the anemia model, consider the order of the design elements when encapsulating the logic of the field:
Value Object -》 EnTIty -》 Domain Service
Remember that we must use the Domain Service as the last straw to assume business logic. The reason why Domain Service was put in the end was because I was too aware of the powerful "magic" of domain services. Developers always have an inertia. Many times they don't want to think carefully about the correct performers of the so-called "responsibilities (encapsulation of the logic of the field's logic)", and domain services are precisely the most convenient option.
For my personal understanding, only the domain behavior that satisfies the following three characteristics should be put into the domain service:
Domain behavior requires multiple domain entities to participate in collaboration
Domain behavior and status have nothing to do
Domain behavior needs to work with external resources (especially DB)
Assume that the contract management function of a system allows the customer to input the self-encoding, and the self-encoding needs to follow a certain encoding format. When creating a new contract, the customer enters the code and the system needs to check if the self code already exists in the existing contract. For this requirement, two fields of behavior can be extracted:
Verify that the input self-encoding complies with business rules
Check for self-encoding duplicates
When looking for performers of responsibilities, we should first follow the “Information Expert Modelâ€, which means “the object that owns the information is the expert who operates the informationâ€, so it is possible to ask a question: Who owns the data for the domain behavior? For the first domain behavior, is to confirm who owns the self-encoding format validation rules? There are two candidates:
"Contract" object with self-encoded information
A "CustomizedNumber" object that embodies the concept of coded knowledge itself
I tend to define the CustomizedNumber value object, wrap this detection rule inside it, and validate it in the constructor. In domain-driven design, value objects are often used to encapsulate these basic concepts. Since the type of customization can encapsulate domain behavior, it is possible to effectively implement the “division of governance†of responsibilities and achieve the cooperation of the objects.
To check if the self-encoding is duplicated, you need to look it up in the database. This requires collaboration with the DB through the Repository. Based on the three characteristics summarized above, this responsibility should be assigned to a domain service, such as DuplicatedNumberChecker.
From the point of view of the assignment of responsibilities, the entity Contract or the value object CustomizedNumber should be a reasonable choice to assume the responsibility. Why do I define such an exception principle? The reason is that in the domain-driven design, we should try to ensure the purity of the entity and value objects, and in particular should not rely on the Repository. The fundamental reason for continuing to dig deeper is that the life cycle of entity and value objects is managed by Repository. If the managed entity object also depends on the Repository, it requires that the Repository corresponding to the entity manages the life cycle of the entity object and also needs to manage its dependency with the Repository. This is unreasonable. Value objects are within an Aggregate boundary, and the reason is the same.
For example, suppose that Contract is an aggregate root. If you assign the responsibility for checking duplicate encodings to this entity object (or value object, CustomizedNumber), you need to rely on the ContractRepository internally. However, Contract's access is also obtained through the Repository. When the infrastructure layer implements the ContractRepository, it does not actually know how to manage the dependencies between the two. If the Contract entity also depends on other Repositories, it is even less likely.
If you really want to solve this dependency management problem, a simpler approach is to provide the Contract with a setContractRepository() dependency injection method. However, when the Contract is obtained through the Repository, DI frameworks such as Spring and Guice cannot inject this dependency and therefore need to be explicitly invoked, which will introduce coupling to the concrete implementation of the Repository. This coupling is placed in the domain layer, resulting in a purely domain-level kernel that relies on external resources. If this specific coupling is extrapolated, for example pushed to the application layer, it will increase the burden on the caller.
Domain services do not have this problem because its life cycle is not managed by the Repository. The following domain service definition is reasonable:
When we allocate domain logic, domain services are the easiest and cheapest choice. This will lead to the proliferation of domain services, and in the long run, the development of the domain level will turn to the old road of the "anemia model." The so-called "service" itself is an abstract concept. The more abstract it becomes, the more inclusive it is. For example, if you define an OrderService, then all the logic related to the order can be plugged into this service, and there are many restrictions on the entity objects such as Order, and you need to think twice about assigning responsibilities. Therefore, if there is no restriction on the distribution of responsibilities during design and development, the so-called "duty-division and separation of duties" is nothing more than empty talk.
After all, mainstream domain-driven design is actually an object-oriented design capability that is examined at the tactical level. I think that the core of object-oriented design is roles, responsibilities, and collaboration. When assigning responsibilities, you should consider encapsulating data and behavior. This is the first principle of object-oriented design.
In order to prevent programmers from treating domain services as a "basket", what logic is loaded into them, in addition to the need to improve the team members' object-oriented design capabilities and to strengthen code reviews, there is also a way to constrain domain services.
No language can impose constraints on DDD design elements. The practice of Mat Wall and Nik Silver in promoting DDD to Guardian.co.uk website is worth learning from. They suggested in the article "Field Driven Design in Evolutionary Architecture":
In order to deal with this behavior, we conduct code reviews of all services in the application and refactor them to move the logic to the appropriate domain objects. We also have a new rule: Any service object must include a verb in its name. This simple rule prevents developers from creating classes like ArTIcleService. Instead, we create classes such as ArticlePublishingService and ArticleDeletionService. Pushing this simple naming convention does help us move the domain logic to the right place, but we still require regular code review of the service to ensure that we are on track and that the modeling of the domain is close to the actual business perspective .
In fact, this unique form of restraint is in fact consistent with the essence of service. That is, services should represent stateless domain behavior, and even domain services can be said to be examples of domain-level use cases.
This practice may result in the creation of more fine-grained domain services, but the more likely outcome is that when we are creating a new domain service, we may consider temporarily stopping and thinking about assigning to this new Is there a better place for service domain logic? Even if this logic may involve multiple domain entities, or it needs to be put into the domain service in cooperation with the Repository, it seems that you can consider the content of the domain logic and the entity (or value object) data strongly related "Abstract "Come out, allocate to suitable places, and ensure a reasonable balance of responsibilities. The harmonious collaboration mechanism is a good object-oriented design.
Solar Energy Mounting Ground Screw Pile
Solar Energy Mounting Ground Screw Pile with N series and F series mainly .N Series Ground Screw with 3pcs,4pcs or 6pcs nut and reinforced plate to assemble ,F Series Ground Screw with flange to assemble solar brackets .
There are two kinds of N series Ground Screw mainly ,with 1 or 2 or 3pcs big blade ,and with Nuts and reinforced plates,another kind of ground screw with continuous small blades .F series ground screw with round,hexagon ,triangle or square flanges .with big blade or continuous blade .
Ground Screw Pile for solar energy mounting system with many advantage : no-digging,no waste time ,lower cost,protect environment,easy install .
Solar Energy Mounting Ground Screw System,Ground Screw Pile Foundation for Solar,10Kw PV Panel Mounting System,Ground Screw Solar Rack System
BAODING JIMAOTONG IMPORT AND EXPORT CO., LTD , https://www.chinagroundscrew.com