六边形架构
adapter 端口适配器/一切的入口/出口实现
controller
mq
redis
mysql
application 应用层/负责编排
infrastructrue->adapter->application->domain
|
\/
rpcclient
infrastructrue
- 负责具体数据库实现
- PO 转 DO
- 工具类,mq类等,
- 并通过DI注入上层
adapter
- 负责定义入口,可以通过rest,grpc,graphql等方式对外部暴露
- 实现 do 转 vo的适配器
application 应用层是很轻的一层
- 负责编排domain服务与第三方服务
- 第三方服务(通过防腐层external),
- 不参与任何业务代码编写(参与调度repo调度第三方,调度领域服务与领域方法)
domain层
- 聚焦业务,理论上只要引入DI模块,不引入外部任何依赖实现 ,
- 其中对领域的业务操作写在实体内, 对象的操作以及编排写在领域服务内(理论上对业务的操作不会调用getset方法,直接使用成员变量) (充血模型) 3.业务代码指的是 (写操作) (cqrs) 4.factory创建复杂对象
rpcclient层
- 提供本服务的rpcclient给 其他同构服务用,如果是异构服务请考虑grpc
cqrs command操作返回void,然后用service去聚合 在每个command操作执行完成时都将发布领域事件
- 基础设施层为什么在是在下层
- 因为 repository impl repostiroyImpl 所以使用这种架构并通过DI
- 依赖 理论上 domain层只引入 bean管理的依赖来实现可被依赖注入, interface层引入mvc依赖 , 基础设施层引入具体依赖(mysql , mq )
- 需要微服务额外提供RPC客户端的, 可以新增一个模块 rpc 来提供被别的服务访问的能力 如 feignClient/grpc等
- domain的业务方法 返回值为VOID 遵循cqrs,理论上domain的setter为private,使用构造器创建,构造即合理,所以在构造器里面调用setter,在setter里面验证
- 想办法去掉domain的getter方法,do需要转换为PO,所以需要一层getter.
聚合 Aggergate 代表多个实体 只有聚合才能拥有资源库
聚合根 AggergateRoot 聚合根是一个实体, 通过ID可以从聚合根访问与该聚合根 管理的实体
实体 Entity 领域对象 DO
值对象 ValueObject 不含生命周期 依赖于 上层实体 如项目中的address
领域服务 DomainService
领域时间 DomainEvent
命令和查询职责分离 CQRS
领域 (子域/核心域) 子域 (业务系统中的域 通用子域/支撑子域) 限界上下文 依据拆分域 协作上下文
对象核心问题 PO 即是数据库对应对象 与数据库完全对应 DO 则是领域对象 可能包含ValueObject ,是一个高内部的对象,里面包含了一些行为功能 Command 传入的命令对象 ,一般在做修改,删除时传入 Query 传入的查询对象, 一般在做复杂查询传入 QueryResult 查询返回的对象 DTO 一般是在Service中用到,复杂组装复杂通用返回值 1.PO 和DO 的转换一般在adapter层完成, 在domain 只有do对象 没有po对象 2.do和 QueryResult/DTO的转换一般在 application层完成, 3.command和do的转换一般也是在application层完成
1.事件总线
- 比如在User领域,触发了UserSave事件,则发出UserSave事件,事件以描述名词为命名,不以具体触发事项命名。
id 自增主建 bigint 字符 使用 varchar 2的n方, 如果为256 则改为255 数字 使用int 如非特殊补位要求 length默认 小数字 使用tinyint 时间使用 datetime
以落库限制为标准,该上的唯一索引就上,使用逻辑外键代理物理外键 关于查询优化索引,非不必要则不加,加的时候要多考虑一下。
首先所有字段要求非空,默认值以业务控制为准,不以数据库主导