What problem does DDD solve / why use DDD
You can write your answers in the comments area
DDD overall process (source: ThoughtWorks)
v1
v2
The biggest difference is that the event storm in the first step is replaced by the identification core domain of strategic design. Personally, I don't think it's suitable to discuss the core domain in advance when I'm not familiar with the new business, because I don't have enough information, all rely on speculation, and too much discussion in the early stage wastes time.
Personal understanding of DDD process
- early stage
- Value, pain point, demand
- Event storm
- Identify events
- command
- Domain NOUN
- Business modeling / strategic design (development and business modeling)
- Partition sub domain / core domain
- Bounded context
- Establish business model
- Model design / tactical design (modeling between development)
- model design
- api design
- Layered architecture
- Database design
- Code writing
- release
The output of the upper layer is the input of the lower layer.
DDD tactical design related concepts
concept | explain |
---|---|
Bounded context | A microservice has multiple bound contexts, which can be simply understood as modules, packages and namespaces. For example, there may be category aggregation in context a and category aggregation in context B. They are all called category, but they have different meanings |
polymerization | It is also a boundary that divides entity and value objects into aggregations and defines boundaries around aggregations |
Aggregate root | The primary entity in an aggregation can be composed of multiple entities and value objects. An aggregation has only one aggregation root |
entity | The aggregation root is an entity. An entity is not necessarily an aggregation root. An entity is an abstraction of multiple table models (it can be equivalent po or composed of multiple po) |
Value object | Object without ID (unique flag) |
Domain object | Including: aggregation, aggregation root, entity, value object and domain event. All objects in the domain layer are called domain objects |
DO | Domain Object, ibid., Domain Object. Location: domain layer |
DTO | Data Transfer Object. Significance of existence: the circulation object of upstream and downstream services. Location: interface layer |
PB | Proto Buffer, meaning of existence: the circulation object of GRPC upstream and downstream services is equivalent to DTO here. Location: interface layer |
PO | Persistence Object, persistent object. Significance: equivalent data table model. Location: infrastructure layer |
VO | View Object. Existential meaning: a kind of domain object, which is mainly used for query. Location: domain layer |
Value Object | Value object, location: domain layer |
BO | Business Object. Existential significance: a container for assembling two or more domain objects. Location: application layer |
DDD four layer structure
arrangement | duty |
---|---|
Interface layer / presentation layer | Be responsible for presenting information to users and interpreting user commands |
Interface layer / presentation layer | Be responsible for presenting information to users and interpreting user commands |
application layer | A thin layer used to choreograph one or more domain services and return domain objects or business objects to the interface layer |
Domain layer | The core layer is responsible for writing business logic. Operations such as database persistence are delegated to the infrastructure layer |
Infrastructure layer | Implementation of business object persistence; Call downstream services |
Circulation objects at all levels of DDD (current situation of message center)
DDD code directory
- server interface layer
- application layer
- Domain domain layer
- infra infrastructure layer
A microservice has multiple bound contexts. The lower directory of the domain layer refers to the division of the bound context. The lower level directories of other infra/persistent, server and application layers are subcontracted by module. The design up and down by module + gauge is a compromise scheme to solve the landing cost of four-tier directory design in each context.
The advantage of subcontracting by module is to solve domain noun conflicts. For example, there may be category aggregation in context A and category aggregation in context B.
Granularity division:
Realm > subdomain > bounded context > aggregate > aggregate root / entity / value object
Go GRPC DDD framework
Go GRPC DDD framework directory description
|-- application //application layer | |-- directories //Module (technical perspective), here refers to the developer directory module | | |-- assembler //Application layer object translator | | | |-- category.go | | | `-- developer_dir.go | | `-- developer_dir_app.go //Developer directory app | |-- example //Module (technical perspective), example module | | `-- example_app.go | |-- module3 //Module (technical perspective), example module 3 | | `-- xxxx_app.go | |-- module4 //Module (technical perspective), example module 4 | | `-- xxxx_app.go | `-- module5 //Module (technical perspective), example module 5 | `-- xxxx_app.go |-- build.yaml |-- domain //Domain layer | |-- directories //Boundary context (domain perspective), which refers to the boundary context of the developer directory | | |-- aggregate3 //Aggregation, example aggregate3 | | |-- category //Aggregation, classification | | | |-- category_repo.go //Classification aggregation warehousing interface | | | |-- category_service.go //Classification aggregation service | | | |-- entity //entity | | | |-- event //event | | | `-- vo //form object | | `-- developer_dir //Aggregation, developer directory aggregation | | |-- developer_dir_repo.go | | |-- developer_dir_service.go | | |-- entity | | |-- event | | `-- vo | |-- example //Bounded context (domain perspective), example context | | |-- aggregate1 | | |-- aggregate2 | | `-- example | | |-- entity | | |-- event | | |-- example_repo.go | | |-- example_service.go | | `-- vo | |-- ctx1 //Bounded context (domain perspective), example context 1 | | `-- aggregate1 | | |-- aggregate1_repo.go | | |-- aggregate1_service.go | | |-- entity | | |-- event | | `-- vo | |-- ctx2 | | |-- aggregate1 | | `-- aggregate2 |-- go.mod |-- go.sum |-- golangci.yml |-- infra //Infrastructure layer | |-- common | | |-- authorize.go | | |-- jwt.go | | |-- page_info.go | | |-- queue | | | |-- consumer.go | | | |-- etcd.go | | | |-- message.go | | | |-- mns_client.go | | | |-- queue_producer.go | | | |-- server.go | | | |-- setup.go | | | `-- topic_producer.go | | |-- rpc_client | | | `-- rpc_client.go | | `-- tree.go | |-- di | | |-- developer_dir.go | | `-- example.go | |-- persistent //Persistence layer | | |-- directories //modular | | | |-- assembler //Object Converter | | | `-- repsitory //Warehouse realization | | |-- example | | | `-- repsitory | | |-- module3 | | | `-- repsitory | | `-- module4 | | `-- repsitory | |-- pkg | | |-- businesscode | | | `-- businesscode.go | | |-- constant | | | `-- common.go | | |-- errcode | | | |-- common_errcode.go | | | `-- custom_errcode.go | | `-- utils | | |-- common.go | | `-- db_insert_build.go | |-- po //Persistent object, data table model | | |-- oa_developer_dir.go | | |-- oa_developer_dir_category.go | | |-- oa_developer_dir_suppliers.go | | `-- oa_developer_dir_user_down.go | |-- remote //Remote call | | `-- micro_basic_service | | `-- id_generation_service.go | `-- startup | |-- config.go | |-- mq_register.go | |-- register.go | `-- vars.go |-- main.go |-- micro-msgcenter-mng-service |-- proto //pb protocol | |-- micro_msgcenter_mng_service_proto | | `-- micro-msgcenter-mng-service | | |-- directories //modular | | |-- example //modular | | `-- module3 | |-- swagger_json.go | |-- server //Interface layer | |-- directories //modular | | `-- developer_dir.go | |-- example | | `-- example.go | |-- module3 | `-- module4 |-- xxx.yaml `-- vendor
PHP BFF directory structure
proto directory
BFF is divided into modules according to clearance context, and proto is also subcontracted according to clearance context
Case explanation
Message center business model divided according to strategic design
The implementation of product context is analyzed below.
Tactical design - model design in product context
api design
BFF
Interface name | Module (gauge context) | Controller (aggregate) | Behavior (event) | url |
---|---|---|---|---|
Get product application | product | product | get-applications | micro-msgcenter-mng-api.cc/product/... |
Get application scenarios | product | app | get-scenes | micro-msgcenter-mng-api.cc/product/... |
Add & modify application scenarios | product | app | set-scenes | micro-msgcenter-mng-api.cc/product/... |
GRPC
grpc interface name | Package name (microservice name underscore. Bounding context) | rpc Service name (aggregate Service) | rpc method (event / behavior) | Service path |
---|---|---|---|---|
Get product application | micro_msgcenter_mng_service.product | ProductService | GetApplications | micro_msgcenter_mng_service.product.ProductService/GetApplications |
Get application scenarios | micro_msgcenter_mng_service.app | AppService | GetScenes | micro_msgcenter_mng_service.app.AppService/GetScenes |
Add & modify application scenarios | micro_msgcenter_mng_service.app | AppService | SetScenes | micro_msgcenter_mng_service.app.AppService/SetScenes |
GRPC-Gateway
Interface name | Module (gauge context) | polymerization | Behavior (event) | url |
---|---|---|---|---|
Get product application | product | product | get-applications | micro-msgcenter-mng-service/product/product/get-applications |
Get application scenarios | product | app | get-scenes | micro-msgcenter-mng-service/product/app/get-scenes |
Add & modify application scenarios | product | app | set-scenes | micro-msgcenter-mng-service/product/app/set-scenes |
At the beginning of the design, it is not recommended that the boundary context name and the aggregation name have the same name;
The interface path is defined according to "gauge context / aggregation / behavior".
BFF obtains product application APIDOC definition
/** * @api {get} /product/product/get-applications Get product application * @apiDescription Get product application * @apiSampleRequest http://micro-msgcenter-mng-api.cc/product/product/get-applications * @apiVersion 2.0.0 * @apiName get-applications * @apiGroup /product/product * @apiSuccess {Boolean} success Return status * @apiSuccess {String} message Return message content * @apiSuccess {Object} data Result set * @apiSuccessExample {json} Success-Response: * HTTP/1.1 200 OK * { "success": true, "message": "", "error_code": "", "data": [ { "product_code": "product1", "product_name": "Product 1 ", "app": [ { "app_id": "1", "app_name": "app1", }, { "app_id": "2", "app_name": "app2", } ] } ] } */
As you can see, this interface requires data from product aggregation and application aggregation.
Because the combined object cannot belong to either product entity or application entity, it is a combination of two domain objects. There needs to be an object to load. This object is BO (business object).
Compared with microservices, microservices are only responsible for the fields within the microservices, and aggregation is only responsible for the aggregated entities.
The core of DDD is clear boundary division.
The following figure shows the service orchestration of the application layer
Aggregation design of applications and scenarios
The method of golang inheritance is used to realize entity definition and reduce the cumbersome definition of structure.
Different from the traditional table model, DDD entity is the abstraction of table model. An entity may be composed of multiple table models. Of course, these multiple table models belong to an aggregation. In this example, the application and scenario constitute an entity. The application is the aggregation root (primary entity), the scenario is the entity, and the aggregation root is the representative of communicating with external objects. The business operations of non primary entities need to be completed through the aggregation root. If you want to modify or view the application scenario, you need to operate through application aggregation:
Get scene: AppService.GetScenes(ctx, appId) // app = *entity.App Set the scene: AppService.SetScenes(ctx, app)
Instead of getting a scene service to operate
Get scene: ScenesService.GetScenes(ctx, sceneId) // scene= *entity.Scene Set the scene: ScenesService.SetScenes(ctx, scene)
Aggregation concept reference article: Deeply understand the aggregation mode of DDD
Circulation objects at all levels of DDD (recommended version)
problem
affair
other
What thinking models can be learned from DDD
Hierarchical thinking
"Any problem in the computer field can be solved by adding an indirect middle layer"
! [insert picture description here]
Classified thinking
For many problems, how to reduce the number of problems to be solved can be classified.
For example:
- How to make a hundred million
- How to keep healthy
- How to improve expression ability
- How to realize wealth freedom
- How to find a girlfriend
- How to have a happy family
- How to work efficiently
- How to communicate effectively
- How to take care of children
- How to improve your writing skills
- What kind of exercise is the healthiest
- How to run
Problem domain classification
It can also be more abstract. The higher the level of abstraction, the broader the field of vision, and the more problems to consider.
Boundary thinking
Example: the company's organizational structure is divided into departments / groups