Baidu Search: DDD Domain driven design
Original address: http://www.cnblogs.com/netfocus/archive/2011/10/10/2204949.html
Domain model of domain driven design
Add a navigation, detailed thinking about how to design aggregations, see this article.
2004 Eric Evans published Domain-driven design–tackling Complexity in the heart of software (field-driven design), referred to as Evans DDD. The domain-driven design is divided into two stages:
A common language that can be understood by a domain expert, designer, and developer as a tool of communication, discovering domain concepts in the process of communication, and then designing these concepts into a domain model;
The domain model-driven software is designed to implement the domain model by code;
Thus, the core of domain-driven design is to establish the correct domain model.
Why it is important to build a domain model
Domain-driven design tells us that building a domain model is important and necessary when implementing a business system through software, because the domain model has the following characteristics:
- The domain model is an abstraction of a domain with a certain boundary, which reflects the nature of the user's business needs in the domain, and the domain model has the boundary, which only reflects the parts we are concerned about in the field;
- The domain model reflects only the business and is irrelevant to any technology implementation; The domain model can not only reflect some entity concepts in the field, such as goods, books, application records, addresses, etc., but also reflect some process concepts in the field, such as funds transfer, etc.
- The domain model ensures that the business logic of our software is in one place, and that it helps to improve the maintainability, business understanding and reusability of the software;
- Domain models can help developers to transform domain knowledge into software constructs relatively smoothly;
- The domain model runs through the whole process of software analysis, design, and development, and domain experts, designers, developers communicate with each other through the domain model, and share knowledge and information with each other, because everyone is facing the same model, so it can prevent the demand from aliasing, so that software design developers can make the software really meet the needs;
- To establish the correct domain model is not simple, need domain experts, design, developers to actively communicate together, and then to make everyone's understanding of the field continue to deepen, and constantly refine and refine the domain model;
- In order to see the domain model, we need to represent it in a number of ways, but it is the most common way to express domain models, but it is not the only way of expression, the code or text description can also express the domain model;
- Domain model is the core of the whole software, is the most valuable and competitive part of software, and the design of domain model with good enough and business requirement can respond to the change of demand more quickly;
Domain Universal language (UBIQUITOUS LANGUAGE)
We recognize that it is absolutely necessary to work together to develop a domain model by software experts and domain experts, but that approach is often difficult because of some basic communication barriers. Developers are preoccupied with classes, methods, algorithms, patterns, schemas, and so on, and always want to correspond to the concepts and program artifacts in real life. They want to see what object classes to build and how to model the relationships between the object classes. They will be accustomed to thinking in terms of encapsulation, inheritance, polymorphism and other object-oriented programming, and will talk to them anytime and anywhere, which is too normal for them, and developers are developers. But domain experts often know nothing about it, and they have little idea about software libraries, frameworks, persistence, or even databases. They only know their specific field expertise. For example, in the air traffic monitoring sample, domain experts know planes, routes, elevations, longitude, latitude, know that the plane deviates from the normal route and knows the launch of the aircraft. They discuss these things in their own terms, which are sometimes difficult for the layman to understand directly. If one person says something, other people don't understand it, or worse, it's wrong to interpret it as something else, what's the chance to make sure the project is successful?
In the process of communication, translation is required in order for other people to understand these concepts. Developers may try to use the language of the foreign pedestrian to parse some design patterns, but this will certainly succeed. Domain experts may also create a new jargon to try to express their ideas. In this painful communication process, this type of translation does not help in the process of building knowledge.
One of the core principles of domain-driven design is the use of a model-based language. Because the model is the common denominator in the field of software, it is suitable for the construction of this common language. Using the model as the core skeleton of the language requires the team to use a consistent language for all communication, as is the case in code. When you share knowledge and model, your team uses speeches, text, and graphics. It is necessary to ensure that the language used by the team appears consistent across all forms of communication, known as the "universal language (Ubiquitous Language)". The common language should be extensively tried in the modeling process to facilitate communication between software experts and domain experts, thus discovering the main domain concepts to be used in the model.
Best practices for translating domain models into code implementations
Having a model that looks right doesn't mean that the model can be directly converted to code, or that its implementation might violate some of the software design principles that we don't recommend. How do we transform from model to code, and let the code have scalability, maintainability, high performance and other indicators? In addition, a model that faithfully reflects the domain may lead to a series of problems with object persistence or an unacceptable performance issue. So what should we do?
We should closely correlate domain modeling and design, tightly tying domain models and software coding implementations, and models are built with software and design in mind. Developers will be added to the modeling process. The main idea is to choose a model that can be properly represented in the software so that the design process is smooth and model-based. The close association of the code with the model under it makes the code more meaningful and more relevant to the model. With the participation of the developer, there will be feedback. It ensures that the model is implemented as software. If there is an error somewhere, it will be identified at an early stage and the problem will be easily corrected. The person who writes the code knows the model well and feels it is the responsibility to maintain its integrity. They realize that a change to the code actually implies a change to the model, and that they refactor the code if the code doesn't show the original model. If the analyst separates from the implementation process, he will no longer care about the limitations introduced in the development process. The end result is that the model is no longer practical. Any technician who wants to contribute to the model must spend some time touching the code, regardless of the main role he has in the project. Anyone responsible for modifying the code must learn to represent the model in code. Each developer must be involved in a certain level of domain discussion and be contacted by a domain expert.
The angle of thinking when modeling a domain
"User demand" cannot be equated to "user", and capturing "model in user's mind" cannot be equated to "user-centric design domain model". There is a point in Lao Tzu's book: There is no thought of profit. Here, there is the benefit of building a domain model, no use, that is, the inclusion of user needs. For example, a cup is filled with a glass of water, we make the cup, the production of an empty cup, that is, to pour out the water, before it can be installed, for example, a house to live, we build a house, the building is empty, only the empty to accommodate people's lives. Therefore, when building a domain model, users should be placed outside the model in order to accommodate the needs of users.
So, my understanding is:
- We can not design the domain model as a user-centric starting point to think about the problem, can not always think about what the user will do to the system, but should be from an objective point of view, according to user needs to excavate the relevant things in the field, thinking about the essence of these things and their changing laws as the starting point to think about the problem.
- The domain model excludes the objective world model outside the human, but the domain model contains the actor role, but generally does not let the actor role occupy the main position in the domain model, if the actor role in the domain model occupies the main position, then the domain model of each system will become no difference , because the software system is a human-computer interaction system, are people-based activity records or tracking; for example, if the forum is man-led, then the domain model is: People post, people replies, human knot paste, and so on; in the case of DDD, if it is human-centric, it becomes: shipper's consignment, consignee's receipt of goods , payer payment, etc; Therefore, when we talk about domain models, we have already ruled out human factors by default, because the domain is only meaningful to people, people are outside the realm, and if people are also in the field, the domain model will be difficult to maintain objectivity. Domain models are objective models that are irrelevant to who and how to use them. To sum up, domain modeling is the creation of virtual models that allow us to use real people instead of building virtual spaces to mimic reality.
With Eric Evans (the father of DDD) a cargo transport system in his book is a simple illustration. After some user needs have been discussed, Eric describes the domain model as the user needs are relatively clear:
- A cargo (cargo) involves multiple customers (customer, such as shipper, consignee, payer), each customer undertakes a different role;
- The cargo target has been specified, i.e. the cargo has a shipping target;
- A series of carrier movement (transport actions) satisfying the specification (specification) are carried out to accomplish the transportation target;
From the above description, we can see that he completely did not from the user's point of view to describe the domain model, but in the field of related things as the starting point, considering the nature of these things and their changes in law. The above description is completely goods-centric, the customer as the goods in a certain scenario may be involved in the relevant role, such as the goods will be related to the shipper, consignee, payer, the goods have a definite target, the goods will go through a series of transport movements to reach the destination; I think that the user-centric thinking of the domain model is just on the surface of the demand, not the essence of the real demand; we need to work hard to excavate the essence of the user's needs when we do the domain modeling, so that we can really realize the user's demand;
For a distinction between the two concepts of user and participant, you can look at the following example:
Imagine two of people playing football games, the operator (user) is the driver, it drives the field of football games, each "person" (participant) activities. Here is a hypothesis, assuming that operator A is manipulating a player A, and that player A has information about someone B, then there is the view that a is a mirror of B, A is a domain participant, and a is the driver.
A classic layered architecture for domain-driven design
User interface/Presentation layer
Responsible for presenting information to users and interpreting user commands. In a more granular way, it is:
- Request the application layer to get the data that the user needs to show;
- Sending a command to the application layer requires it to execute a user command;
A thin layer that defines all the tasks the software needs to accomplish. External to the presentation layer to provide a variety of application functions (including queries or commands), internal calls to the domain layer (domain objects or Domain Services) to complete a variety of business logic, the application layer does not contain business logic.
Responsible for expressing business concepts, business status information and business rules, the domain model is at this level and is the core of the business software.
This layer provides common technical capabilities for other tiers, provides inter-layer communication, implements persistence mechanisms for the domain layer, and, in short, the infrastructure layer can support the technical needs of other tiers through architecture and frameworks;
Overview of all modes used in the domain-driven design process
The design of the association
The association itself is not a pattern, but it is very important in the process of modeling the domain, so it is necessary to discuss how the association between objects is designed before exploring the various patterns. I think the object's associated design can follow some of the following principles:
- As few associations as possible, the complex association between objects is easy to form a network of objects, which is detrimental to our understanding and maintenance of individual objects, and it is difficult to divide the boundaries between objects and objects; In addition, reducing correlation helps to simplify the traversal between objects;
- It may be natural to have a lot of connections, and we usually use a set to represent 1-to-many relationships. However, we often need to consider the performance problem, especially when there are so many elements in the set, it is often necessary to obtain the associated collection information through a singleton query.
- Associate as far as possible to maintain a one-way association;
- When establishing an association, we need to dig deeper into whether there are any associated constraints, and if so, it is better to add this constraint to this association; often such constraints can simplify the association, that is, many-to-many can be simplified to 1-to-many, or 1-to-many simplifies to 1 to 1;
Entities are domain concepts that need to be uniquely identified in the domain. Because we sometimes need to distinguish which entity is. There are two entities, and if the unique identities are different, then even if all other attributes of the entity are the same, we think that they are two distinct entities; because entities have lifecycles, entities may be persisted to the database after being created, and then taken out at some point. So, if we don't define an identity that uniquely distinguishes the entity, then we can't tell whether it's the entity or the entity. In addition, you should not define too many attributes or behaviors for an entity, but should look for associations, discover other entities or value objects, and transfer attributes or behaviors to other associated entities or value objects. For example, the customer entity, he has some address information, because the address information is a complete business meaning of the concept, so we can define an address object, and then transfer the information of the customer's addresses related to the Location object. If you do not have an address object, and you put these addresses directly on the customer object, and if for some other similar address information is directly on the customer, it will cause the customer object is confusing, the structure is not clear, It ultimately makes it difficult to maintain and understand;
In the field, not every thing must have a unique identity, that is, we do not care about the object is which, but only care about what the object is. For example, if there are two customer addresses in the same address, we would assume that the two customer addresses are the same. This means that as long as the address information, we think it is the same address. The way to express it is that if the values of all the properties of two objects are the same, we would consider them to be the same object, then we can design the object as a value object. Therefore, the value object does not have a unique identity, which is the maximum difference between it and the entity. In addition, the value object determines whether the same object is the same if all properties are the same, if the same is considered the same value object, and if we distinguish whether it is the same entity, we only see whether the entity's unique identity is the same, regardless of whether the entity's attributes are the same, and the other obvious characteristic of the value object is immutable, That is, all properties are read-only. Because the properties are read-only, they can be shared safely, and when sharing value objects, there are generally two ways to replicate and share them, depending on the actual situation. In addition, we should design the value object as simple as possible, do not let it reference many other objects, because he is just a value, like int a = 3 Then "3" is a value we mean in the traditional sense, and the value object can actually be the same as the "3" here, is also a value, but is represented by the object. So, when we compare the equality of two value objects in the C # language, the two methods of GetHashCode and equals are overridden to compare the value of the object, while the value object is read-only, but can be replaced by the whole. Just as you change the value of A to "4" (a = 4;), replace the value "3" with "4" directly. The same is true for value objects, when you want to modify the Address object reference of the customer, not by Customer.Address.Street, because the value object is read-only and it is a complete, indivisible whole. We can do this: customer.address = new Address (...);
Domain Services (domain service)
Some concepts in the domain are less suited to modeling as objects, which are categorized into entity objects or value objects, because they are essentially operations, some actions, not things. These actions or actions often involve multiple domain objects and need to coordinate these domain objects together to accomplish this action or action. If you forcibly assign these operational responsibilities to any one object, the assigned object is to assume some responsibility that should not be assumed, thus causing the object's responsibilities to be ambiguous and confusing. However, class-based object-oriented languages stipulate that any attribute or behavior must be placed inside the object. So we need to look for a new pattern to represent this operation across multiple objects, and DDD thinks that the service is a natural paradigm that corresponds to this operation across multiple objects, so there is a pattern of domain services. Unlike domain objects, Domain Services are named after the beginning of a verb, such as a money transfer service that can be named Moneytransferservice. Of course, you can also understand the service as an object, but this is somewhat different from the general sense of the object. Because general domain objects are stateful and behavioral, Domain Services have no state but behavior. It is important to emphasize that domain services are stateless, and that the meaning of the existence is to coordinate the domain objects to complete an operation, and all the states are stored in the corresponding domain objects. I think that the model (entity) and the service (scene) is a division of the domain, the model focuses on the individual behavior of the field, the group behavior of the field of interest, the static structure of the model concerned domain, the dynamic function of the scene focus field. This is also in line with the reality of the various phenomena, there are static, there are independent collaboration.
Another important feature of Domain Services is the ability to avoid domain logic leaks to the application layer. Because if there is no domain service, then the application layer will call the domain object to complete the operation that should belong to the domain service, so that the domain layer may leak part of the domain knowledge to the application layer. Because the application layer needs to understand the business capabilities of each domain object, what information it has, and what other domain objects it might interact with, how to interact, and so on. Therefore, the introduction of domain Services can effectively prevent the logic leakage of the domain layer to the application layer. For the application layer, from an understandable point of view, the easy-to-understand but well-defined interface provided by the calling domain service is certainly much easier to manipulate than the domain object directly. Here also seems to see the domain service has the function of façade, hehe.
When it comes to Domain Services, you need to mention that there are typically three services in the software: application-level services, Domain Services, and basic services.
- Get input (such as an XML request);
- Send a message to the domain layer service, requiring it to implement the business logic of the transfer;
- When the domain layer service is successfully processed, the basic layer service is called to send an email notification;
- Get the source and target accounts, respectively, notify the source and target account to deduct the amount and increase the amount of action;
- Provide return results to the application layer;
Basic Tier Services
According to the application layer request, send email notification;
Therefore, from the above example can be clearly seen, the responsibility of each service;
Aggregation and aggregation root (aggregate,aggregate root)
Aggregation, which realizes the cohesion of the domain model by defining the clear affiliation and boundary between objects, and avoids the complex formation of difficult-to-maintain object networks. Aggregations define a set of related objects that have cohesive relationships, and we think of aggregations as a unit of modified data.
Aggregation has some of the following characteristics:
- Each aggregation has a root and a boundary, which defines what entities or value objects are inside an aggregation, and the root is an entity within the aggregation;
- Objects within the aggregation can be referenced to each other, but aggregate external if you want to access an object inside an aggregate, you must start navigating through the aggregation root, and never bypass the aggregate root to directly access the objects within the aggregation, that is, the aggregate root is the only element that the external can keep a reference to it;
- The unique identities of entities other than root within the aggregation are local identities, i.e. they are kept unique within the aggregation, as they are always subordinate to this aggregation;
- The aggregation root is responsible for dealing with other external objects and maintaining its own internal business rules;
- Based on the above concepts of aggregation, we can infer that the cell from the database query is also aggregated into a single unit, that is, we cannot directly query the aggregate inside of a non-root object;
- Objects inside the aggregation can maintain references to other aggregate roots;
- Deleting an aggregate root must also delete all related objects within that aggregation, because they all belong to an aggregation, which is a complete concept;
Questions about how to identify aggregations and aggregate roots:
I think we can start from a business perspective and then slowly analyze what the objects are:
- There is the meaning of the existence of independence, that it is not dependent on the existence of other objects it makes sense;
- can be accessed independently, or it must be navigated by some other object;
How do I identify aggregations?
I think this needs to be analyzed in depth from a business perspective which objects their relationships are cohesive, i.e. we consider them as a whole, and then we can put them in an aggregation. The so-called relationships are cohesive, meaning that there must be a fixed rule between these objects, and a fixed rule is a consistency rule that must remain constant when the data changes. When we modify an aggregation, we must ensure that all objects within the entire aggregation meet this fixed rule at the transaction level. As a recommendation, aggregations are not as large as possible, or even the ability to maintain aggregated business rule integrity at the transaction level can lead to some performance issues. There are analysis reports that typically in most domain models, 70% of aggregations usually have only one entity, the aggregate root, which does not contain other entities, contains only some value objects, and, in the other 30% aggregations, basically only two to three entities. This means that most aggregations are just one entity, which is also the aggregate root.
How do I identify the aggregation root?
If an aggregation has only one entity, then the entity is the aggregate root, and if there are multiple entities, then we can think about which object in the aggregation has a separate meaning and can interact directly with the outside.
The factory in DDD is also a pattern that embodies the idea of encapsulation. The reason for introducing Factory mode in DDD is that sometimes creating a domain object is a complex thing, not just a simple new operation. Just as an object encapsulates an internal implementation (we can use the object's behavior without knowing the object's internal implementation), the factory is used to encapsulate the knowledge needed to create a complex object, especially aggregations, and the factory's role is to hide the details of the object being created. The customer passes to the factory some simple parameters, and the factory can create a complex domain object internally and then return it to the customer. Other elements in the domain model are not suitable for doing this, so it is necessary to introduce this new pattern to the factory. When a factory creates a complex domain object, it usually knows what business rules to satisfy (it knows how to instantiate an object, and then what initialization is done on that object, which is the details of creating the object), and if the passed in parameters conform to the business rules that created the object, the object can be created smoothly. But if the expected object cannot be created because of an invalid argument, an exception should be thrown to ensure that an incorrect object is not created. Of course, we don't always need to create objects through factories, in fact, in most cases the creation of domain objects is not too complex, so we just need to simply use the constructor to create the object. Hiding the benefits of creating objects is obvious, so that the business logic of the domain layer is not compromised to the application layer, and the burden of the application layer is mitigated, it simply calls the domain factory to create the desired object.
- The purpose of warehousing is to be designed for this reason: the object in the domain model has not been persisted in memory since it was created, persisted to the database when it is inactive, and then rebuilt when needed. Rebuilding an object is the process of recreating the object based on the state of the stored object in the database, so that the reconstructed object is a process of dealing with the database. From a broader perspective, we often get one or more objects from a similar set from a set of places, adding objects to the collection or removing objects. In other words, we need to provide a mechanism that can provide a similar set of interfaces to help us manage objects. Warehousing is designed on the basis of such ideas;
- The objects stored inside the warehouse must be aggregated, because the domain model mentioned above is divided by the concept of aggregation; aggregation is a boundary of the object we update, in fact we view the whole aggregation as a whole concept, either taken out together or deleted together. We will never individually query or update sub-objects within a single aggregation. Therefore, we only design the warehouse for aggregation.
- Warehousing also has an important feature is divided into warehousing definition and warehousing implementation, in the domain model we define the interface of warehousing, and in the infrastructure layer to achieve specific warehousing. The reason for this is that because the implementation behind warehousing is all about dealing with databases, we do not want customers (such as the application layer) to focus on the issue of how to get data from the database, because doing so will cause the customer (application layer) code to be confusing and will likely ignore the existence of the domain model. So we need to provide a simple and straightforward interface for the customer to use, to make sure that the customer can get the domain object in the simplest way, so that it can focus on coordinating the domain object to complete the business logic without being disturbed by any data access code. This approach to isolating package changes through an interface is actually common. Because the client is facing the abstract interface is not a specific implementation, so we can at any time replace the real implementation of warehousing, which is very helpful for us to do unit testing.
- Although warehousing can manage objects in memory like a collection, warehousing is generally not responsible for transactional processing. The general transaction is given to something called a unit of work. For more information about work cells I'll talk about it in the discussion below.
- In addition, warehousing in the design of the query interface, may also use the specification mode (specification pattern), I have seen the most powerful specification mode should be LINQ and DLINQ query. In general, we will choose the appropriate warehouse query interface design According to the flexibility of the query in the project. In general, it is only necessary to define a simple and straightforward query interface with fixed query parameters. You may need to use the specification mode only if the query condition is dynamically specified.
General steps for designing a domain model
- Establish a preliminary domain model based on the requirements, identify some obvious domain concepts and their associations, the association can temporarily have no direction but need to have (1:1,1:N,M:N) These relations, can use the text precise without ambiguity to describe the meaning of each domain concept and the main information contained;
- Analyze the main software application functions, identify the main application layer of the class, so as to help early detection of what is the application layer of responsibility, which is the domain layer of responsibility;
- Further analysis of domain models to identify which are entities, which are value objects, and which are domain services;
- Analyze correlation, identify the direction of the relationship or remove some unwanted correlations through a deeper analysis of the business and tradeoffs between various software design principles and performance;
- It is difficult to find the aggregation boundary and the aggregation root, because you often encounter a lot of ambiguous choices in the process of analysis, so we need to accumulate some analytical experience to find the right aggregation root.
- For the aggregation of the root is equipped with warehousing, in general, for an aggregation allocation of a warehouse, at this time as long as the design of the storage interface;
- Take a look at the scene, determine the domain model we designed to effectively solve business needs;
- Consider how to create a domain entity or value object, either through a factory or directly through a constructor;
- Stop to refactor the model. Looking for a model where there is some doubt or a bad place, such as thinking about whether some objects should be linked to the navigation or should be obtained from warehousing? is the aggregation design correct? Consider how the model is performing, and so on;
Domain modeling is a process of continuous reconstruction and continuous improvement of the model, in which the changes are reflected in the model, and the model continues to refine and move in the right direction. Domain modeling is the process of communication between domain experts, designers, and developers, and is the basis for everyone to work and think.
How other tiers interact with the domain layer in a layered architecture
As can be seen from the classic domain-driven design hierarchy, the upper layer of the domain is the application layer and the underlying infrastructure layer. So how does the domain layer interact with other layers?
For application-level functionality that affects the state of domain objects in the domain layer
The general application layer starts a unit of work first, and then:
- In the case of modifying domain objects, the domain objects are acquired through warehousing, and the related business methods of the domain objects are called to complete the business logic processing.
- For new domain objects, create a domain object from a constructor or factory, and if necessary, continue to do some work on the newly created domain object and add the newly created domain object to the warehouse;
- For the deletion of the domain object, the domain object can be removed from the warehousing, and then removed from the warehouse, or you can directly pass a domain object to delete the unique identity to the warehouse notification that it removes the unique identity of the corresponding domain object;
- If a business logic involves multiple domain objects, call the relevant domain service in the domain layer to complete the operation;
Note that all domain objects mentioned above are aggregated only, and can be obtained through the IOC container when the application layer needs to acquire the warehousing interface and the domain service interface. Finally, the work unit commits the transaction to persist the state of all related domain objects to the database in a transactional manner;
Several implementation methods of unit of work (working unit)
- Snapshot-based implementations, where a domain object is taken out, saves a backed-up object, and then, when persisted, compares the state of the most recent object with the state of the backed-up object, if it is not the same, it is considered modified and then persisted The advantage of this design is that the object does not have to tell the work unit of its own state to be modified, and the disadvantage is obvious, that is performance may be low, backup objects and the state of the comparison object is modified, when the object itself is very complex, is often a relatively time-consuming step, And it is difficult to realize the deep copy of the object and to judge whether the property is modified or not;
- No snapshot-based, but storage-related updates or new or deleted interfaces are called when an object in the warehousing notification work cell is added or updated or deleted. This way the unit of work can also know which objects need to be persisted when doing data persistence, which theoretically does not require the support of the ORM framework, does not have any inclination to the domain model, and also supports the mode of the work unit well. This approach is good for friends who don't want to use the Advanced ORM Framework;
- No snapshot-based or warehousing tells the work cell that the data has changed. Instead of using the idea of AOP, a transparent proxy is used to intercept. In NHibernate, our properties are usually declared as virtual, and one reason is that nhibernate generates a transparent proxy that automatically notifies the working unit that the state of the work Cell object has been updated when the object's properties are modified. The unit of work also knows which objects need to be persisted. This method has little inclination to the domain model, and can support the working cell mode well, if using NHibernate as ORM, this method is more useful.
- Microsoft is generally the method, that is, to let the domain object implementation. The inotifiypropertychanged interface in the NET Framework, and then invokes the OnPropertyChanged method on the last line of the set method for each property to notify others of their own state modification. This method is relatively strong in the field model.
Query functionality that does not affect the state of domain objects in the domain layer
You can find out the required data directly from the warehouse. However, the general domain layer of the storage provided by the query function may not meet the needs of the interface display, you may need to call different warehouses multiple times to obtain the data needed to display, in fact, for this kind of query, I will talk about this can be directly through the CQRS architecture to achieve. That is, for queries, we can not invoke anything at the domain level at the application layer, but rather directly through some other query engine implemented with another technical architecture, such as querying any data from a database table or multiple tables directly by constructing a parameterized SQL system. This will not only be high performance, but also reduce the burden of the domain layer. Domain model is not suitable for the application layer to provide a variety of query services, because often the interface to display data is a combination of many objects of information, is a non-object concept of information, like a report;
Why object-oriented is more adaptable to business change than process-oriented
Objects will be required to separate the needs of the class, as with the storage box to wrap things up one after another, the demand has changed, divided into several situations, the most serious is the big change, then each storage box to open the change, this method is not necessarily beneficial; So all we have to do is open these two lockers and change them, without affecting the rest of the locker.
And the process is to put everything in a large storage box, modify a section later, will cause other parts of instability, a bug fix, triggered a new countless bugs, and finally the programmer caught in the burn, such as Japan's Tokyo Electric Power company staff to deal with the nuclear crisis, like the exhausted Ah.
Therefore, we can not be coarse-grained to see the change in demand, that the demand has changed, is a wide range, everything has boundaries, Lao Tzu said, no desire to pay, what things have to observe its boundaries, although the demand can be expressed in terms of "demand", talking about the change in demand, does not mean the maximum boundary range changes, so the problem
In fact, it is the local circle-boundary. When we were young, we wrote the old three paragraph was the same reason, the respective responsibilities are clear, the demarcation boundary is clear, through the transitional sentence to realize the connecting-interface. Why the organization needs to be divided into different departments, is also the boundary thinking. It is easy to draw circles, but how to draw is difficult, so oo thinking is very important.
Changes in demand are caused by boundaries, and if the boundaries of change are equal to the entire field, then it is a completely different project. It takes a lot of domain knowledge to master the boundary. Otherwise, into the bank even business responsibilities are not clear, how to circle it?
Process-oriented is the word without boundaries (even if there is only the largest boundary), it does not require independence, it can be called across the boundary, which is easy to cause the cause of the bug, causing the bug is not necessarily a technical error, more is a logic error. Separate encapsulation is the draw circle, all the boundaries are implemented by the interface. Do not change or small to change the interface, will not hold a body to start. If the boundary is considered in the process, then it has risen to oo thinking, that is, the object language is not used, but the object is already implied. To be blunt, the most important difference between object-oriented and process-oriented is: decomposition. Decomposition of the boundary. From the requirements to the final implementation of all through.
The object-oriented essence is boundary division, encapsulation, not only to the demand changes can quantify, reduce the impact surface; because boundary demarcation also limits the scope of the error, OO is also good for bugs such as software later.
The software world always has bug,bug is clean, just like the human world is always imperfect and the dark side, the crux of the problem is: God uses space and time boundary to the human world suffering disaster and other imperfections in a range, and the software world if you do not use OO methods to divide the boundary, once the error , how bad would it be to track it down?
The world of software is actually similar to the human world, sometimes problems, to explore the cause of a look, the original is two seemingly unrelated factors caused, the ancients had to often praying, we programmers in their own software on-line running, probably in the heart also in praying do not make a big mistake, if our software to take OO encapsulation, We will be calm, certainly will be wrong, but we have predetermined the boundaries, so there will be no serious consequences, and there will not be difficult to trace the devil bug.
Some other topics for domain-driven design
The above is only about the basic content of DDD, and there are many other important things in ddd that are not mentioned above, such as:
- Model context, context mapping, context sharing;
- How to apply analysis mode and design pattern to DDD;
- Some tips on flexible design;
- If you maintain the integrity of the model and the knowledge of continuous integration;
- How to refine the model, identify the core model and the common sub-domain;
These topics are important, because space is limited and I have limited knowledge of the current, and in order to highlight the focus of this article, so do not give them a detailed introduction, we are interested can read their own.
Some related extensions read the CQRS architecture
The core idea is to completely separate the query and command parts of the application, both of which can be implemented with completely different models and techniques. For example, the command part can be implemented by domain-driven design, and the query part can be implemented directly in the fastest non-object-oriented way, such as SQL. There are many benefits to this idea:
- The domain model that implements the command part does not often do some trade-offs for how the domain object may be queried;
- Because the command and query are completely separated, so these two parts can be implemented with different technical architectures, including database design can be divided into design, each part can give full play to its strengths;
- High performance, command side because there is no return value, can be like message queue to accept commands, placed in the queue, slowly processing, after processing, can be asynchronous to notify the query side, so that the query can do data synchronization processing;
Event Sourcing (incident traceability)
For aggregations in DDD, the current state of the aggregation is not saved, but each event that occurs on the object is saved. When you want to rebuild an aggregate object, you can return the object to a particular state by backtracking these events (that is, by having these events re-occurring), because sometimes a single aggregation can have a lot of events, so if you want to retrace the events from the beginning every time you rebuild the object, it will cause poor performance. So we'll create a snapshot of the aggregation at some point. This allows us to start creating aggregate objects based on a snapshot.
The DCI Architecture emphasizes that the software should realistically simulate the interaction of objects in real life, and that the code should accurately and earthy reflect the user's mental model. In DCI, there are three concepts: the data model, the role model, and the context. The data model represents the structure of the program, and currently we understand that the domain model in DDD is a good representation of the data model, the role model represents how the data interacts, a role defines the interaction of an "identity", the context corresponds to the business scenario, the business use case is used, and it is not the system use case. Business use cases are only business-related; When the software runs, the system creates the appropriate scene based on the user's actions, and passes the relevant data objects as scene participants to the scene, then the scene knows what role to assign to each object, and when the object is given a role, it becomes an interactive object. And then interacting with other objects; The process is consistent with the objects we understand in real life;
The idea of DCI is the same as what the Domain Services in DDD do, but the angle of implementation is somewhat different. Domain Services in DDD The starting point is that when some duties are not well suited to any one domain object, this responsibility often corresponds to an activity or conversion process in the domain, and we should consider placing it in a service at this time. For example funds transfer, we should provide a fund transfer service to correspond to the domain concept of funds transfer. But what the domain service does internally is to coordinate multiple domain objects to accomplish one thing. As a result, Domain Services in DDD are often in a passive position when it comes to coordinating domain objects, and the domain service informs each object to do what he or she can do, and so on. In this process, we don't seem to see the meaning of interaction between objects, because the whole process is implemented by Domain Services in a process-oriented mindset. DCI, in turn, introduces roles, gives roles the ability to interact, and then interacts between roles, allowing us to see the process of interacting between objects and objects. But the premise is that the objects are really interacting. Because the real life is not all objects in the interaction, such as have A, B, C three objects, a notify B to do things, a notify C to do things, at this time can be considered between a and B,a and C is in the interaction, but B and c no interaction between. So we need to distinguish that from the situation. Example of funds transfer, A is equivalent to a transfer service, B is equivalent to account number 2 1,c. Therefore, the fund transfers This business scenario, uses the domain service to be more natural. Some people think that DCI can replace the domain service in ddd, I am skeptical.
Four-color prototype analysis mode moment-time segment prototype (Moment-interval archetype)
Represents an activity that occurs at a certain point in time or over a period. Use pink to indicate that MI is abbreviated.
Party-Location-item prototype (part-place-thing archetype)
The person or thing that participates in an activity is the place where the activity takes place. Use a green representation. Abbreviated to PPT.
Description Prototype (Description archetype)
Represents an essential description of the PPT. It is not a classification of PPT! Description is a collection of properties that are abstracted from the PPT and are invariant in generality. Use a blue representation, abbreviated as DESC.
For example, there is a person called Zhang San, if an alien asks you what is Zhang three? What would you say? It may be said that Zhang San is an individual, but aliens do not know what "man" is. And what would you do? You will say: Zhang San is an objective existence which consists of a head, two hands, two feet, and a body. Although the aliens still do not know what people are, but I can borrow this example to show you what is "Description". In this example, Zhang San is a ppt, and "by a head, two hands, two feet, and a body composed of an objective existence" is the Zhang San of the description, head, hands, feet, body is the essence of the human nature of the constant commonality of the set of attributes. But we humans are more intelligent, will be abstract summary and naming, has put this description with a word to replace, that is "person". So there is the so-called Zhang San is the person's argument.
Character prototypes (role archetype)
Character is what we usually understand as "identity." Use a yellow representation, abbreviated to role. Why is there a concept of character? Because there are activities, only PPT (participants) with a specific role (identity) are allowed to participate in the activity. For example, a person can only have a teacher's role in order to attend classes (an activity); a person can participate in elections and be elected only by a lawful citizen; but some activities do not need a role, such as a person does not need to have any role to sleep (a kind of activity). Of course, it is wrong to say that people do not need a role to sleep, where is wrong? Because we can understand this: an objective existence as long as the role of "people" can sleep, in fact, we have the DESC as a role to see. Therefore, in fact, the concept of character is very broad, can not be used in our usual understanding of the narrow sense of "identity" to understand, because "teachers", "legal citizens", "people" can be regarded as a role. Therefore, it should be said that any activity requires participants with a certain role to participate.
Summarize the four-color prototype in one sentence: what kind of person or organization or object participates in an activity at a certain moment or time in a particular role. "What kind of" is desc, "person or organization or object" is ppt, "role" is the roles, and "a certain time or a certain period of activity" is mi.
These things if you learn DDD after the study will have a better understanding of DDD, but I think that ddd relatively basic, if we have already understood the basis of DDD and then learn these things will be more effective and easy to grasp.
I hope this article is helpful to everyone.
Domain model of domain driven design