First, the background
When discussing DDD landing with many WeChat friends, he also gave some of his own insights, but rarely had the opportunity to try how to solve some real scenarios by hand, so through the DDDinAction project, he landed and improved his ideas little by little through the code practice of the permission platform.
Of course, there are many people who want to find a DDD practical project code, so after iterating some codeMaker features, they will really land infosys-auth permission platform of infosys-plat to see how to write better code in DDD.
2. Requirements for permission platforms
2.1 List of General Requirements
- Build a unified permission platform to connect with company-wide permission application scenarios
- Implement a permissions model based on RBAC
- Provide API interface of web management platform, support dubbo, springboot API, and provide jar package access authentication of SDK
- Unified management of roles, permissions, users, system menus, etc
- The first version implements CURD for the core business model, and partially imports and exports functions
- Open up the approval flow platform to realize automatic permission approval
- Supports the application of fine-grained data permission rules, such as a user can only access the data of a list for the last three months
- Temporary authorization, such as a user opening a temporary authorization for another user and withdrawing it upon expiration
- Permission operation logging audit component access
- Permission risk auditing
2.2 System Participants
role | Use features | illustrate |
Permissions platform super administrator | Permissions all features of the platform | A separate table storage super administrator configuration may be required |
Line-of-business administrators | Configure roles and related system menu resources | Configured by a super administrator |
Individual access system users | Permission verification and control | SDK access |
2.3 Business Processes
In the demo case of this project, we focus on two important business processes to look at the business timing diagram
2.3.1 Permission building process
2.3.2 User authentication process
Third, the permission model
3.1 Permission Context Analysis
3.2 Permission Domain Model Documentation
It should be noted here that this project will not have too much modeling process, do not do too much identification of the corresponding scene, and try to ensure that an article can talk about the entire practical content, so it will directly give the modeling documents in related fields. Of course, if you have some questions about the code, you are also welcome to exchange and discuss.
3.3 Entity Division
Entity name | Entity description | Entity behavior |
AuthorityBO | Permissions model | Disable, enable, and determine whether a certain type of permission resource is available |
DataAuthorityBO | Data permissions model | |
SystemAuthorityBO | System permissions model | Build system permissions |
AdminAuthorityBO | Administrative authority model | |
UserAuthAggregateBO | Aggregation model from the perspective of user permissions | |
RoleAuthAggregateBO | Aggregation model from the perspective of role permissions | |
UserGroupBO | User group model | Determines whether the user group is associated with the specified role |
RoleBO | Role model | Disable, enable, associate the list of users |
RoleGroupBO | Role group model | |
RoleUserBO | Role user association model | |
SystemBO | System model | Add a module |
ModuleBO | Menu module model | Add a button |
MenuBO | Button model |
3.4 Value Object Division
Value object | Value object description | remark |
DataColumnBO | Data field model | There are additions, deletions, modifications, checks, etc., but they look more like configuration class objects, and the configuration objects are collectively called value objects here |
AuthorityTypeEnum | Permission type | Enumerated objects, in an enumeration class, are unified as value objects |
UserBO | User object | The user object is considered a business object in the user service, but in the permission system, it only relies on this object to achieve the integrity of the model and business, and the user state is not under the authority control, so it can be regarded as a value object, but it is under the domain.support package, indicating that it is an object under the support domain. |
DepartmentBO | Department object | Same as user objects |
Address | Provincial, city, and county objects | This object is considered a composite object, but it is only part of the permission aggregation, and has no actual behavior and state, so it can be regarded as a value object. |
It should be noted here that there is not much demonstration of the expression of value objects in this project demonstration, such as the UserID object for userId, of course, there are some big guy demo articles that will do this. In this project, the most basic data type is used to express the value object, and try not to increase the traversal and dependency depth of the object.
In the process of practice, we may not be able to pay too much attention to some rules that can be generated by value objects, rather than simply doing object encapsulation for some of the identified attributes, which will undoubtedly make the entire business object a little fragmented, and at the same time increase the difficulty of understanding the business, and practice will also be shackled with some concepts of DDD. I will have the opportunity to talk about this aspect later.
So in most cases, value objects don't actually need to use object wrapping completely, in my opinion, if you realize that this is a value object or you can divide an object or data structure is a value object. Encapsulating with basic types does not mean that we cannot express its rules and business scenarios, so it is not necessary to specify this as a value object at the domain layer, such as XXVO, but it is important to express which objects are value objects through the documentation.
3.5 Aggregate Root Identification
Aggregate root | Aggregate root description | polymerization |
AuthorityBO | Permissions, the permissions corresponding to the entire role are uniformly associated, and the internal permissions are data permissions, administrative permissions and system permissions | Roles can be associated with many permission resources, which currently identify three categories, and subsequent permission resources can be customized, that is, there is also this object of resources in this aggregation, but it is not paid special attention to, which is a metaphor. So permissions are approximately equal to resources. |
UserAuthAggregateBO | Permission aggregation model based on user perspective | Because it is an RBAC model, we cannot intuitively see what permissions the user has, then this permission is equivalent to a snapshot aggregation of the read scene, and the write is still managed through the role of permission resources |
RoleAuthAggregateBO | Permission aggregation model based on role perspective | When reading, because there is an overall AuthorityBO for aggregate management, then this role may correspond to multiple AuthorityBOs, so you need to see how many permission resources this role has through the role dimension. |
SystemBO | An aggregation model based on the system menu dimension | This is equivalent to a province, city and county model, the point is that this model is dynamically changing, and the permission system is more dependent on him, but the maintenance in the permission system is because this is a core permission resource, so for the permission and the system menu itself the system is an overall aggregate object, the system itself needs to shield the internal menu and buttons, the external dependence is the system and its internal menu button business indication to do reading dependence. |
4. Service in the field of authority
4.1 Domain Services Documentation
This document reflects the biggest difference between using DDD and not using DDD, because building a service interface for context-oriented aggregation is equivalent to abstracting and summarizing the underlying data table and related services as a whole, so it does not seem to be the kind of table and interface and service class. Due to the special distinction between different scenarios, and the use of relying on inversion so that the application layer does not call the infrastructure layer across layers, the overall scalability can be achieved, the flexibility is high, and maintenance and modification will become easier.
4.2 Area Competency Table
context | Corresponding module | Description of competence |
User groups | user | Group management of a certain type of user |
Role groups | role | Group management of a type of role |
role | role | Maintain roles and their associated role-user associations |
system | system | Maintain resources related to the system and its menu buttons |
Data fields | config | Provide data permissions related to metadata information management and maintenance |
Permissions | authority | Provide the abstraction ability of unified permission resources, and decouple roles and concrete resources |
Administrative authority | authority | Provides configuration associations for administrative-related permission resources |
Data permissions | authority | Provides configuration associations for data-related permission resources |
System permissions | authority | Provides configuration associations for system-related permission resources |
5. Permission Platform Cola Application Architecture
5.1 Permission Application Schema
5.2 Two practices of the anti-corrosion layer model
- An interface method encapsulation of downstream dependent interfaces at the domain layer is an implementation of the domain gateway, such as the dependence on cache operations, the dependency encapsulation of other downstream interfaces, and the returned and requested objects are counted in the domain, but need to be distinguished from the core model in the domain.
- The second is the business downstream services that the entire field depends on, such as user interfaces and departmental interfaces in the user center. This kind of thing builds dependent downstream interface methods in the ACL package of the infrastructure layer, and the internal implementation calls the downstream interface logic and returns it by domain object, and the request object can be converted to DTO by the domain object BO.
The above two methods have their own advantages and disadvantages, if the domain layer is encapsulated, the application layer can directly access the downstream interface across the domain layer to some extent. If you are building at the infrastructure layer, you may need to consider the transformation of objects and the business processing of downstream methods within the domain.
5.3 CQRS mode application
In this project, the core business module is separated by reading and writing, providing two sets of interfaces for reading and writing, and at the same time, the reading is also specially separated at the domain level. At the app level, command+executor is used to handle permission-related business processes at the application level, such as granting role authorization.
5.4 CQE mode application
In the domain layer, the various data business entities under bo are specifically classified, such as BO, EVENT, MsgBody. Therefore, when the application layer controls the business application through command+executor, the Evevnt will be converted through the CMD object of the application layer. One advantage of this is that it can be done asynchronously.
The code demonstration example is as follows:
What needs to be said here is that there are actually several applications of events, let's take a look:
In-domain events (events generated within the domain service)
Application-layer events (some application-layer events are also transaction-related), events with transactional characteristics, and other listening events
Messages extended by events (for example, because an event requires sending a message, or receiving a message)
Some of the above events sometimes use synchronous operations because of business characteristics, and sometimes asynchronous implementation, but it should be noted that because there are many application scenarios of events, excessive use may cause a certain degree of complexity and cannot ensure the continuity of the overall business, after all, the code is meant to be seen. A feasible way is to make a special distinction between different events, and at the same time associate the event with the event handler as much as possible to make dynamic configuration routing.
5.5 Specification Mode Application
Before using spec mode, I also reviewed Eric's book. An attempt was made in the query scenario of the system menu button in the application layer. It seems to work well, and several simple query interfaces are built in the SystemQueryFacadeIml of the application layer, and at the same time determine whether different query conditions are met through the specification mode, so that the number of external interfaces becomes very small, and the read logic of other modules can be closed. Here's a code example:
Internally, different query scenarios can be closed through specification routing. However, it should be noted that the application of the specification model in Eric's book is at the domain level, which is equivalent to different specifications for more complex table queries or statistical queries at the domain level. So before some friends said which layer the specification model is applied, my suggestion is that both the application layer and the infrastructure layer can be used. Of course, if it is a domain layer, if you practice according to Eric's book, the domain layer may need separate classes to build query SQL and query objects, so the DDD code you see is actually different for different practices.
5.6 Standalone Class Mode Application
Because the permission model is more complex, there will definitely be a lot of construction of the entire permission data here, so it is necessary to design the cache-related logic, so the cache prefixes of different business modules are defined in the domain layer, and the cache service classes of different business objects are built in the infrastructure layer. Since the application layer cannot reference the cache service class directly to the infrastructure layer, in order to maintain the consistency of the overall layered architecture, a CacheServiceGataWay interface is defined in the domain gateway package. Routing calls are made inside interface implementation methods through different business object identifiers.
The specific code is not screenshotted, if you are interested, you can take a look down.
5.7 Application of Occam's razor
When writing code, the code classes of different modules generated by CodeMaker are used at the beginning, but the control of aggregation in actual applications will make some generated code classes very embarrassing, such as the interface implementation under different permission types in the facadeimpl of the application layer, because the control of aggregation These different permission interfaces become relatively redundant, so it is shaved off by @Deprecated annotations, and the corresponding CURD goes to the Authority aggregation interface.
Of course, a similar situation has also appeared in the auth-adapter, so don't be surprised when you look at the code, so that the comparison is good and bad.
5.8 DDD strict layered architecture
Because the Cola architecture is adopted here, the implementation of the dubbo interface is placed in the application layer, so it seems that the domain layer and application layer that the interface implementation of springboot depends on are not very coordinated, of course, the reality is that there will not be two sets of external APIs with different styles in a project. Then I want to emphasize here that in this project, there will be no application layer across the domain layer to implement the call infrastructure layer interface.
Of course, after the auth-adapter module guarantees its responsibilities as a user interface layer, it is originally necessary to access the domain layer through the application layer, but in the project the application layer is the implementation layer of dubbo, so the auth-adapter accesses the application layer and the domain layer. Note that the application layer is accessed here because the command+executor class is used in some modules that want to be referenced. Without a dubbo implementation, the overall application layer would serve the auth-adapter separately. There will be no such special cross-layer call.
5.9 Service Dependency Description
Interconnect to the approval flow interface to implement automatic permission approval capabilities
Connect with the user center to obtain user and department data
Docking with provincial, municipal and county data services
6. Code project description
6.1 Project Home Page
To illustrate here in a unified way, my actual DDD code is basically in this project: https://gitee.com/codergit.com/dddin-action There are two engineering contents released in this iteration:
Infosys-auth platform code under the infosys-plat project
Stock-simple-demo under YoupinShop Project
6.2 Project Content
Provide basic additions, deletions, modifications, and checks for each business object
Provide a minimal middleware dependent environment, convenient for starting projects (theoretically only rely on the database), integrate cache, MQ is also more convenient, internal default to implement empty content for these, a small amount of development can achieve the full version
Provides Dubbo interface and Spring Boot interface implementation
Provide domain model documents, domain service documents, DDL documents
Add detailed annotations to the project code that handle each scenario
VII. Summary
The overall base code is supported by Tianhua-codeMaker, which can directly fill in the business method content.
Provide auth-common packages, no longer need to rely on coderman-utils, the overall dependency is closed.
Explain the theory of different scenarios, output different processing schemes to control the complexity of the project, and do code practice on the recent DDD theory learning.
There is also a lot of confusion in the process of implementation, so I also consulted some senior bosses, and at the same time built some feasible methods and ideas in the project according to my own understanding.
Article Source: https://mp.weixin.qq.com/s?__biz=MzI3MzEzMDI1OQ==&mid=2651835225&idx=1&sn=e18c2f4f21e70fdc9aaa0b941adeb448&chksm=f0dc9d25c7ab1433b9c6eb802be36998121afaed17253ba599d1d2e972a1db8ba7767044095e&scene=21#wechat_redirect