Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Domain Driven Design Reference (3)-- Building Model of Model-driven Design

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

This book is a dictionary reference book written by Eric Evans for his own "Domain-driven Design-the way to deal with Software Core complexity". It can be used to quickly find many concepts in "Domain-driven Design" and their concise explanations.

Addresses for other articles in this series:

Domain Driven Design Reference (1)-- Preface

Domain Driven Design Reference (2)-- make the model work

Domain Driven Design Reference (3)-- the Construction Module of Model-driven Design

Ⅱ. Construction module of model-driven design

These patterns are based on domain-driven design and widely implement the best practices of object-oriented design. They guide decisions to refine the model and align the model with the implementation, each of which enhances the effectiveness of the others. Careful elaboration of the details of the model elements provides a stable platform for developers to explore the model and keep it closely linked to the implementation.

Hierarchical architecture

In object-oriented programs, user interfaces, databases, and other supporting code are usually written directly to business objects. Additional business logic is embedded in the behavior of UI parts and database scripts. This happens because it is the easiest way to do so in the short term.

When domain-related code is spread through such a large amount of other code, it becomes very difficult to understand and reason. Superficial changes in UI can actually change business logic. To change business rules, you may need to carefully track UI code, database code, or other program elements. Implementing consistent, model-driven objects becomes impractical. Automated testing becomes difficult. Since each activity involves all the technology and logic, the program must be kept very simple, otherwise it cannot be understood.

Therefore:

Isolate the expression of domain models and business logic, and eliminate dependence on infrastructure, user interfaces, and even application logic that is not business logic. Divide a complex program into multiple layers. Develop a cohesive design within each level and rely only on the following layers. Follow the standard building pattern to provide loose coupling for the above layering. Centralize all the code related to the domain model in one layer and isolate it from the code of the user interface, applications, and infrastructure. Domain objects do not have the responsibility of displaying themselves, storing themselves, managing application tasks, and so on, and can focus on expressing domain models. This makes a model rich and clear enough to capture the necessary business knowledge and put it into practice.

The key goal here is isolation. Related patterns such as the "hexagonal architecture" can allow our domain model performance to avoid dependencies and references to other system problems, or even better.

Entity

Many objects represent a continuous identified thread throughout the life cycle, although their properties may change. Some objects are not defined primarily by their properties. They represent identities that run through time and often cross the main lines of different forms of presentation. Sometimes such an object must match another object, even if the properties are different. The wrong identity can lead to data corruption.

Therefore:

When an object is distinguished by its identity rather than its attributes, make it a point of its definition in the model. Keep the class definition simple and focus on lifecycle continuity and identity.

Define a method that distinguishes each object, regardless of its form or history. Be wary of the need to call matching objects through properties. Define an operation that guarantees a unique result for each object, perhaps by appending a symbol that guarantees uniqueness. This means of identification may come from an external or any identifier created by the system, but it must conform to the identity distinction in the model.

The model must define what is the same thing.

(also known as reference object)

Value object

Some objects describe or calculate the characteristics of things.

Many objects have no conceptual identity.

Tracking the identity of the entity is critical. But attaching identities to other objects can hurt system performance, increase analysis work, and make all objects look exactly the same. Software design is a complex ongoing battle. We must make a distinction so that special treatment can be carried out only when necessary.

However, if we think of this type of object as a lack of identity, then we don't add much to our toolbox or vocabulary. In fact, these objects have their own characteristics and are meaningful to the model itself. These are the objects that describe things.

Therefore:

When you are only concerned with the attributes and logic of the model elements, classify them as value objects. Make it express the meaning of the attribute it conveys and give it related functions. Value objects are treated as immutable. Make all operations non-side-effect functions that do not depend on any variable state. Do not give any identity to the value object and avoid the design complexity necessary to retain the entity.

Domain event

What the experts in the field care about happened. An entity is responsible for tracking its state and rules governing its life cycle. However, if you need to know the actual cause of the state change, this is usually unclear, and it may be difficult to explain how the system implements it. Audit trails can be traced, but they are usually not suitable for the logic of the program itself. The change history of an entity allows access to previous states, but ignores the meaning of these changes so that any operation on the information is procedural and is often thrown out of the domain layer.

There are a series of unique but related problems in distributed systems. The state of a distributed system cannot be completely consistent at any time. We always keep the aggregation consistent and make other changes asynchronously. When changes are propagated between nodes on the network, it can be difficult to resolve multiple updates that are out of order or from different sources.

Therefore:

Model information about activities in the domain is treated as a series of discrete events. Each event is represented as a domain object. These are different from system events, they reflect the activities of the software itself, although system events are usually associated with domain events or as part of the response to domain events, or as a way to bring information about domain events to the system.

Domain events are an integral part of the domain model and a representation of what happens in the domain. Ignore irrelevant domain activities and identify events that domain experts want to track or be notified, or events associated with state changes in other model objects.

In a distributed system, the state of an entity can be inferred from the currently known domain events of a specific node, and the relevant model can be obtained without complete information about the whole system.

Domain events are usually immutable because they are records of something in the past. In addition to the description of the event, the domain event usually contains the timestamp of the time when the event occurred and the identity of the entity involved in the event. In addition, domain events usually have a separate timestamp indicating when the event enters the system and the identity of the person who brought it into the system. If useful, the identity of domain events can be based on some collection of these attributes. So, for example, if two instances of the same event arrive at the same node, they can be identified as the same.

Service

Sometimes, it's not the same thing. It is unnatural for some concepts in the domain to be modeled as objects. Force the required domain functions to become the responsibility of entities or value objects, either tampering with the definition of model-based objects or adding meaningless virtual objects.

Therefore:

When important processes or transformations in the domain are not the natural responsibility of entities or value objects, add an operation to the model as a separate interface and declare it as a service. Define a service contract, a set of declarations about interacting with the service. These declarations are stated in a common language in a specific bounded context. Give the service a name, which becomes part of the lingua franca.

Module

Everyone uses modules, but rarely regards them as an integral part of the model. The code is broken down into various categories, from all aspects of the technical architecture to the developer's tasks. Even developers who have done a lot of refactoring tend to use modules conceived early in the project.

The interpretation of coupling and cohesion tends to make them sound like technical indicators, making mechanical judgments based on the distribution of correlations and interactions. However, this is not just about dividing the code into modules, but also concepts. How many things a person can think about at a time is limited (so the coupling is low), and incoherent fragments of ideas can hardly be understood as an undifferentiated idea (and therefore highly cohesive).

Therefore:

Select the module that can tell the story of the system and contain a series of concepts of cohesion. Make the module name part of the common language. Modules are part of the model, and their names should reflect insight into the domain.

This usually leads to low coupling between modules, but if it does not find a way to change the model to decompose the concept, or a neglected concept, it may be the basis of a module that can group elements together in a meaningful way. Seek low coupling on concepts that can be understood and reasoned independently. Refine the model according to the high-level domain concept until it is partitioned and decouple the corresponding code.

Polymerization

It is difficult to ensure the consistency of object changes in complex association models. They can be overshadowed by changes in other objects that are conceptual components. Similar problems occur when distributing objects among multiple servers or designing asynchronous transactions.

Therefore:

Centralize entities and value objects into aggregates and define boundaries around them. Select an entity as the root of each aggregation and allow external objects to retain only references to the root (references to internal members can only be used when returned in one operation). Define the attributes and invariants of the aggregation as a whole, and assign responsibility for this constraint to the root [in this case, the aggregation root] or some specified framework mechanism.

Use the same aggregation boundaries to manage transactions and allocations.

Consistency rules are applied synchronously within an aggregation boundary. Process updates asynchronously across boundaries.

Jointly maintain an aggregation on a single server. Allows different aggregations to be distributed between nodes.

If these design decisions are not well guided by aggregation boundaries, reconsider the model. Is it that the scene in the field is suggesting an important new insight? This change usually improves the expressiveness and flexibility of the model and solves transaction and allocation problems.

Warehousing

Query the aggregation of common language expressions.

The spread of traverable associations is only used to find things that mess up the model. In mature models, queries often express domain concepts. However, queries can cause problems.

The pure technical complexity of applying most database access infrastructures quickly engulfed the client code, causing developers to get stuck in the domain layer, making the model irrelevant.

The query framework may encapsulate most of the technical complexity, allowing developers to extract the exact data they need from the database in a more automated or declarative way, but this only solves part of the problem.

Unconstrained queries may pull specific fields from objects, violate encapsulation, or instantiate several specific objects from within the aggregation, making the aggregate root variable and preventing these objects from enforcing the rules of the domain model. The domain logic moves into the query and application layer code, and the entity and value objects become mere data containers.

Therefore:

For each type of aggregation that requires global access, create a service that provides the illusion that all objects of the aggregate root type are in a single memory collection. Access is set through a well-known global interface. Provides methods for adding and deleting objects, which encapsulate the insertion or deletion of actual data into the data store. Provides a method of selecting objects based on criteria that make sense to domain experts. Returns a collection of fully instantiated objects or objects whose property values meet the criteria, thereby encapsulating actual storage and query techniques, or returning proxies that give the illusion of aggregations that are fully instantiated in a lazy way. Provide warehousing only for aggregate roots that actually need to be accessed directly. Keep the application logic focused on the model, delegating all object storage and access to the repository.

Factory

The factory provides encapsulation when creating a complete, internally consistent aggregation or when a large value object becomes complex or displays too much internal structure. The creation of an object itself can be a major operation, but complex assembly operations are not suitable to be undertaken by the created object. Combining these responsibilities can result in incomprehensible and ugly designs. Allowing the client to assemble directly can confuse the client's design, break the encapsulation of the assembly object or collection, and excessively couple the client to the implementation of the created object [for example, the client here can be understood as the application layer or the UI layer].

Therefore:

Shift the responsibility for creating complex objects and aggregate instances to separate objects that may have no responsibility in the domain model, but are still part of the domain design. Provides an interface that encapsulates all complex assemblies and does not require clients to reference concrete classes that instantiate objects. A complete aggregation will be created as part of it, enforcing its immutability. Create a complex value object, probably after combining the element with the builder.

Author: Zachary_Fan

Source: http://www.cnblogs.com/Zachary-Fan/p/DDDReference3.html

If you want to get the message of your own article in time, you are welcome to scan the QR code below.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report