Like the people see you how like, hate your people see you how hate
When I just came to the company, Teacher Lai said: we did not develop documents, you want to get familiar with the business, get the requirements from the product to compare the code!! When I started looking at projects
Business development pain points
-
How is the software being written now?
- I am not satisfied with the existing code, I know it is messy, but I do not know how to start to solve
- Have you ever heard of a business structure that is elegant in its entirety and allows for local corruption? I have never seen
- Complexity is high, and increasingly uncontrollable
- The constant influx of new product requirements documents (PRDS)
-
How can your code become domain?
- Can the system support business sorting from different perspectives from different dimensions?
- Does the code reflect the contents of the PRD?
- How do products and technologies blend together?
- What does structuring of code mean?
-
Can business code and technical code be decoupled?
- Business and technology are independent of each other
- I want to use something that’s outsourced, and as a codebase, I don’t trust the quality
- In our big family of technical teams, some people are obviously suitable for business field development, and some are suitable for technical system development. How to manage people in layers?
- Trying to get business ideas out of code, wake up! You look at the code and just ask, “What’s for dinner?” I ate an egg-fried rice cooked in a wok with eggs and rice bought by Park Park (not in commercials).
-
Business uncertainty
- How to elegantly solve: business logic extension, business model extension, business process extension
- Do you dare to touch your if statement? Its logic is all over the world
- I often have new requirements to add fields, and even add tables, add r & D do not know their own
- It has to respond to a variety of individual needs, but it also has to keep itself from corruption
-
Research and development (
- How do you get developers to know where the code is right away when they get the requirements, and build the wheel and the concept without being different
- Don’t talk to me about various methodologies, architectural ideas, I just want to know how to implement this PRD well
Sources of complexity for business development
- Fundamental source
- There are many different service scenarios
- More personalized needs
- There are many business terms, and each term may correspond to a large number of fields, logic, and processes
- Business process is long, any node error will cause the whole bug
- Our company is a B2B project, and every enterprise in every industry has different business demands
- Attached source
- Lack of top-level design, resulting in arbitrary code
- Thousands of different code styles and designs
- There is no top-level logic, who is the man (woman) who comes forward
- The coupling of business and technology, the code itself does not reflect the nature of the business
- Poor quality and interpretability of the code itself
- Environmental factors (team size, staff turnover, project flow)
- Lack of top-level design, resulting in arbitrary code
DDD
-
Do you know DDD? DDD(Domain-Driven Design), don’t let its fancy name make you think it’s out of reach (but it’s obscure!). . DDD concept is originated in 2004 in his most influential book “Domain-Driven Design – Complexity in the Heart of Software” dzj3000 by Eric Evans, a leading modelling expert. Domain-driven Design: Solutions to Software core Complexity). , which introduced the concept of domain-driven design (DDD).
- Domain-driven design is generally divided into two phases:
1. Use a common language that can be understood by domain experts, designers and developers as a tool to communicate with each other, discover and dig out some major domain concepts in the process of continuous communication, and then design these concepts into a domain model; 2. Software design is driven by domain model, and the domain model is represented by code. The initial details of domain requirements are worked out at the functional level through discussions among domain experts.
See here for your own ammunition :DDD(Domain-driven Design) summary
- Domain-driven design is generally divided into two phases:
-
DDD is an architectural idea that really solves a business problem:
- Unify business design and business development, product and r&d
- Unification is at the Domain layer, and the essence of DDD is at this layer
- The role of business experts is largely missing in the Field of the Internet, in fact, the expert is the one who knows better
- Business and technology decoupling
- In essence, DDD is about taking technology out of the business: making the business central and technology an accessory
- Technology is for business
- The Domain layer is the core of the business: do not escape and leak business models and rules to other layers
- A domain-centered layered architecture, with technical means to isolate by reversing dependencies
- It’s business-oriented design and programming, not database-oriented programming, and not technology-oriented programming (to do a good job of a business, not the more advanced the technology and not the database to add fields)
- Centralizing business logic at domain level enables product and r&d to have a common code exchange site
- In essence, DDD is about taking technology out of the business: making the business central and technology an accessory
- Change the past
Service + database
Technology-driven development patterns- Start with the business and let the code explain the business (improve the business presentation of the code)
- Start with a model of the core concept
- Unify business design and business development, product and r&d
Can you write DDD
DDD is an architectural idea, not an existing framework. The lack of sufficient constraints at the code level leads to a high threshold for DDD in practical application and easy deviation in understanding.
- The framework is easy to learn, but the idea is difficult to learn (just like the original process-oriented to object-oriented time, full of doubts)
- There are too few DDD best practices and no standards
- From the above, DDD only gives me the results, but does not give me the process guidance. At the beginning, there are always so many possibilities that extend into more unknowability
- The core appeal of DDD is to bind business and system architectures, but it lacks domain-oriented architecture: it is not enough to support complex project requirements
- The implementation of DDD into code tests the object-oriented thinking of research and development
- However, the long-term thinking of database oriented programming causes the degradation of object oriented thinking ability learned in books
- It’s easy to go back to the old ways
- DDD concepts are hard and confusing to understand
- DDD modeling, please have you ever won an award?
DDD practice
Teacher Lai assigned me a task to extract and process those events with low weight and no impact on the core process (such as Sms, data statistics, file conversion and other events requiring asynchronous processing), and you need to write a service or tool to deal with these tasks. From the time I got this assignment, everything was zero. In the process of DDD learning, materials are overwhelmed. There are frameworks to support complex projects and practical projects to step into DDD. We should take the essence of DDD and discard the dregs.
- The collision of subjective and objective
- Based on DDD architecture, it is designed for complex business scenarios
- The code framework provides enough constraints to provide a good DDD implementation environment
- Reduce the threshold of DDD to reduce the burden of r&d and prevent landing deviation
- Reduce complexity and make business assets reusable
- Help resolve business uncertainty
- Extensions of business logic, processes, logical models, data models, polymorphic systems
- The framework itself is extensible
- Extended business pack (hot deployment), service isolation by the framework’s own ClassLoader mechanism
- Based on DDD architecture, it is designed for complex business scenarios
Thought and Practice – the creation of top-level design
-
DomianModel: The domain, the heart of DDD
-
DomianService: domain service. The completion of a complete business activity, such as statistics. Data statistics is a multi-step process in tasks, including filtering, data verification, and source classification, which corresponds to DomainStep.
-
DomainStep: a service consists of multiple steps. Step, an abstraction that hides business details and separates business activities. (divide-and-conquer)
Popular Science class: Divide-and-conquer, literally meaning “Divide and Conquer”, is to Divide a complex 1 problem into two or more same or similar sub-problems, and then Divide the sub-problems into smaller sub-problems until the sub-problems can be solved directly and easily. The solution of the original problem is the combination of the solutions of the sub-problems. This idea is the basis of many efficient algorithms, such as sorting algorithms (quicksort, merge sort), Fourier transforms (fast Fourier transforms), and so on. The basic idea of divide-and-conquer is to divide a big problem that is difficult to solve directly into smaller, identical problems so that they can be broken down separately and divided and conquered.
There are steps that must be choreographed to ensure that they are executed in order. In different service scenarios, the sequence and classification of steps vary. For example: inquiry behavior, which is done in B2B by steps (A, B, C, D); In the B2C scenario, receiving orders consists of steps C, D, E, F, and H. So DomainStep is a choreographed service.
Since there are steps, there are also steps to be arranged, some of which can be pre-calculated, and some of which can be dynamically calculated. For example, the pre-sorting API needs to be called at C, and the subsequent steps can be determined according to the returned results. Examples of dynamic arrangement will be provided later (the general idea here is to use topological sorting to arrange steps).
StepExecute (step executor) is required to execute the steps after step choreography is complete. Exceptions may be thrown during step execution. If the previous steps need to be rolled back, expand DomianStep’s subclass RevokableDomainStep to implement service rollback. These mechanisms are a Saga Pattern implemented by StepExecute.
-
DomainExtension: Extension point to realize service polymorphism.
How to achieve different choreography of steps in different scenarios? Within the same business scope, the execution logic of different scenarios may be different, for example: to initiate an inquiry, some buyers ask for 0 futures quotes, some ask for quotes within the price range, etc.?
The above requirements are essentially business polymorphisms. This brings us to DomainExtension: business scope is defined, but logically different business function points, i.e. business polymorphism, need to be implemented in different scenarios. The use of extension points converges to DomainAbility, which manages multiple levels of classification through its tags.
- Depending on the overall design, the extension mechanism also needs to be layered:
- DomainExtension: The lowest level extension point that addresses the uncertainty of business execution logic
- LayoutStepExt: Step choreography extension points to address the uncertainty of business processes
- ModelAttachmentExt: To solve the uncertainty of business model, can be simply understood as how to solve the problem of database field in multi-business scenario
- Depending on the overall design, the extension mechanism also needs to be layered:
-
IdentityResolver: business identity matcher, extension point mechanism, implements service polymorphism. However, when running a service, you need to determine whether the service belongs to you according to the DomainModel, and bind it to an extension point implementation to complete the mechanism of locating extension points. In essence, IdentityResolver converges the if judgment conditions of a previously scattered business logic, making these business judgments explicit, tangible, and given a name. DomainExtension is equivalent to the code block after if explicit, tangible, and can be organized.
List the dimensions of the business scenario: the order of a merchant, whether the warehouse is overstocked, whether the order contains contraband, etc
-
Pattern: a horizontal business Pattern that can be superimposed in any dimension according to the valid content of IdentityResolver+DomainExtension above. Each Pattern+DomianExtension can have an independent Spring context. Through context isolation, Bean references between different modules cannot be directly carried out, so as to achieve module isolation at run time.
-
DomainAbility: the presence of fine-grained DomainStep. The medium connecting DomainStep to DomainExtension, thus providing Step with the ability to manage calls to DomainExtension.
Abstract top-level design
- Next, here’s what you need to do:
- Combing the business
- Business abstract
- Refine the extension point DomainExtension
- Step DomainStep
- Model extension ModelAttachmentExt
- Realize one’s ownDomainModelTo build a domain model of your business
- Exception mechanism
- Error code specification
- Core and support domains and interactions
Domain Primitive
Whether the domain model is clear or not determines whether the design is good or not. A good domain has a clear internal structure and low evolution cost.
-
The general steps for designing a domain model are as follows:
- Demarcate domain and boundary context from requirements, and relationships between contexts
- The division of entity and value object, and the aggregation of related relations
- The Repository design provides a way to create objects and values (with an anticorrosive layer)
- In the engineering practice domain model, and in practice to test the rationality of the model, backward in the model and reconstruction.
-
In terms of Domain Primitive, we have to mention Domain Primitive. From InquiryMain above, we can see that there are not only properties but also behaviors and all methods of extraction are stateless, such as verification, creation, filtering, etc. (Anemia model to hyperemia model)
- DP is a traditional Value Object, which is Immutable
- DP is a complete conceptual whole with precise definition
- DP uses native languages in the business domain
- DP can be the smallest part of a business domain or can build complex combinations
Please refer to DDD series – Domain Primitive for more details here
Think about it: I believe that many people have been exposed to the object-oriented process before, re-look at the process, its programming ideas around events, analysis of the solution steps to solve the problem and then function steps. In our daily code, we have long been used to the anemia model. As a technical detail, it brings us more simplicity. In the process of code writing, there is no need to think too much about reuse and behavior. If an anemia model is viewed as int, CHAR, etc., the whole call process of the entire anemia model is half process-oriented and half object-oriented. Of course, not all objects have stateless behaviors, so in the design of objects, we try to think deeply about them to explore behaviors and actions rather than think about temporary relief.
The design of the field will certainly not be smooth, and the business needs continuous running-in order to create a smooth implementation. Take InquiryMain as an entity
@domain (code = InquiryDomain.ID, name = "InquiryDomain ")
public class InquiryDomain {
public static final String ID = "core";
}
Copy the code
@Getter
@Log4j
public class InquiryMain implements InquiryDomainModel {
private Long id;
private String inquiryNo;
// ...
@Setter
private String activity;
@Setter
private String step;
private OfferIntegrin offerIntegrin; / / entity
private InquiryItemIntegrin inquiryItemIntegrin; // as a value object
private InquiryMain validate(a) throws Exception {
// Base validation of the model itself
return this;
}
public IDomainModel createWith(Object objectBean) {
/ / verification
/ / conversion
return null;
}
public List<String> filterOffer(Predicate predicate) {
return new ArrayList<>();
}
// ...
}
Copy the code
-
An object can become an entity when it can be distinguished by an identifier (not an attribute). Entities are persistent and have business logic. There should not be too many attributes in the design of entities, but rather look for associations
-
Value objects are easy to model as entities after we’re used to database-oriented implementation code. However, as a value object, it has invariance, equality and substitutability. The existence of a value object can simplify the design better, so we should clarify the attachment relationship between the entity and the value object. As you can see from DDD’s value object definition, a value object is conceptually common to the model. As a model, it does not allow outsiders to modify the values it has created. Such as inquiry sheet, inquiry details price, quantity and so on fixed after a series of operations can not change its value from the outside, then the price and quantity of inquiry details can be regarded as the attributes of the value object.
Entity and value objects are relatively easy to understand and directly linked to business. We can model entity and value objects according to business division, but aggregation requires us to use business rules as a reference to help us design technology.
- Aggregation and aggregation root Since each aggregation has a boundary, it indicates that in technical design, aggregation is the basic unit to deal with transactions, so aggregation is a big family, they share the obligations of advancing and advancing together. External aggregation access to this aggregation can only be obtained from the aggregation root due to boundary isolation.
Domain services and procedures
@DomainService(domain = InquiryDomain.ID)
public class SubmitInquiryService implements BaseService<InquiryMain.ServiceException> {
@Override
public boolean handler(InquiryMain objectBean) throws ServiceException {
return false; }}Copy the code
- Service
- It is neither an entity nor a category of value objects; it has important domain actions or operations
- The service is stateless
- Operational design domain of services
The purpose of a domain service is to assist a domain object to perform an operation, and since all the state of the operation is in the domain object, it should be simple to create a domain service for the developer of the service.
@Step
public class InquiryPersistStep implements IDomainStep<InquiryMain.ServiceException> {
@Autowired
private InquiryRepository inquiryRepository;
@Override
public void execute(InquiryMain model) throws ServiceException {}@Override
public String activityCode(a) {
return Steps.Inquiry.InquiryPersist;
}
@Override
public String stepCode(a) {
returnSteps.Inquiry.Activity; }}Copy the code
-
Domain events what happens to a domain when it goes through a serviced operation can be viewed as domain events, which are the modeling of activities occurring within the domain. For example, to initiate an inquiry, it is necessary to inform the brand bidder, and the “you have an inquiry sheet to quote” is a field event.
- Creating domain events maintains two characteristics
- It’s immutable
- Domain events should carry contextual data information that is relevant when the event occurs, but not state data for the entire aggregation root. For example, when the quotation is notified, the quotation data will be transmitted instead of the whole aggregation inquiry sheet.
For the realization of domain events, the Event Driven Architecture can be used to realize domain events in microservices. According to the principle of “DDD”, “one transaction only updates one aggregation root”, the message middleware can be considered to be introduced to realize domain events through the way of asynchronization. Different transactions are used for different aggregation roots within the microservice. However, as the implementation of middleware is extremely complex, Step is used to explain.
- Creating domain events maintains two characteristics
-
Steps are the more granular existence of domain services that disassemble the business activity of asking for an inquiry and abstract it into business steps. In the introduction of DDD, EDA is used to handle an event
- The same
- Both implement the open and close principle
- But they all face the design problem of granularity
- The difference between
- Step debugging and troubleshooting is more convenient, and Step execution in StepExecute retains the call stack
- Step makes it easier to implement dependencies and sequences, while THE distribution mechanism of events under EDA can be complex and may destroy its benefits
- Step, combined with business identity, makes it easy to implement choreography in different scenarios
- Step supports dynamic choreography
Step execution can be asynchronous, so StepExecute also needs to support multi-threaded operation and can also be implemented by introducing message middleware. However, the introduction of message-oriented middleware has gaps in the tasks assigned to me by Teacher Lai, so I choose to discard it. It is also suitable for me to support multi-threaded operation. The way steps operate (sequential or multi-threaded) and choreography is governed by DomainAbility. In order to ensure data consistency in microservice architecture, transactions also need to be introduced. In StepExecute, Saga’s policy compensation mechanism is selected. Please refer here to replenish your ammo :Pattern: Saga
- The same
Anticorrosive coating
The data flow
Due to the entry of external data, the anti-corrosion layer is needed to provide protection for the top-level design, and the access to the external context is escaped once (technical selection: MapStruct).
- The introduction of a coating may be considered in the following situations: [3]
- Models in external context need to be translated into models understood by the context.
- For the team collaboration between different contexts, if it is an enshrine relationship, it is recommended to introduce an anti-corrosion layer to avoid the erosion of the local context by external context changes.
- This access is used extensively in this context to avoid overreaching changes.
- If multiple internal contexts need access to external contexts, consider placing them in a generic context.
The last
The top-level design of domain design is relatively simple, but building a business-appropriate domain model is difficult. In the process of development is in continuous refinement, with multiple testers, developers, product managers to achieve the best results. Therefore, the creation of domain models is so integral to the business that other people’s designs may not be suitable for you. The implementation of domain models facilitates team communication, and the concept of domain models helps us understand domain-driven design and achieve some highly cohesive, low-coupling code implementations.
DDD is only a small part of the overall mission design. In addition to domain model design, we also have a lot of other designs to implement a system, such as database design, cache design, framework selection, high concurrency solution (due to the characteristics of the task, not considered), consistency selection, performance pressure measurement scheme, monitoring and alarm scheme, etc. All of these need a lot of learning and accumulation at ordinary times. As a qualified developer, I think it is really not easy to have so many technical skills in addition to DDD domain driven design. Of course, the above article has buried many holes due to different emphases, such as the specific description of tasks, technology selection, step rearrangement, data consistency and other problems have not been fully explained. This will definitely be filled in later, but I will try my best to achieve the best solution.
reference
[1] Domain-Driven Design [2]DDD [3] DDD Series – Domain Primitive [4] Practice of Domain-Driven Design in Internet Business Development [5] Practice of DOMain-Driven Design (DDD) (Ii) Event driven with CQRS [6]DDDplus