引用《领域驱动设计模式、原理与实践》
为了避免将代码库变成大泥球(BBoM)并因此减弱领域模型的完整性且最终减弱可用性,系统架构要支持技术复杂性与领域复杂性的分离。引起技术实现发生变化的原因与引起领域逻辑发生变化的原因显然不同,这就导致基础设施和领域逻辑问题会以不同速率发生变化
每一层都有各自的职责,显然这也是符合SRP的
DDD的标准形态
User Interface是用户接口层,主要用于处理用户发送的Restful请求和解析用户输入的配置文件等,并将信息传递给Application层的接口
根据DDD细化业务逻辑层模块
结合maven的module,项目中现在分了八个module
generator-assist-dao generator-assist-client-api assist-client-api assist-controller assist-service assist-infrastructure assist-common start
入口模块
包结构:
除了启动类,还有单元测试
生成的dao类
包结构:
现在实践落地时,这个模块是个空模块,why?
DDD中明确了repository概念,并属于domain层,但dao是对底层数据库的封装,具体实现类放在infrastructure层更合理
在COLA中,作者也是为了领域层的纯洁性,依赖反转了,repository接口定义在domain层,而实现在infra层
但在落地时,domain与infra出现了循环依赖,COLA把实现放在了app层,这样有些另类,所以暂时先把repository全部放在了service层
迷思:
1、基于mybatis的实现,mapper本身是接口,repository实现类放在domain层,不要接口,这样满足DDD分层规则,但离DIP差了一步
2、在《DDD之熵》中提过
DDD引入repository放在了领域层,一是对应聚合根的概念,二是抽象了数据库访问,,但DDD限界上下文可能不仅限于访问数据库,还可能访问同样属于外部设备的文件、网络与消息队列。为了隔离领域模型与外部设备,同样需要为它们定义抽象的出口端口,这些出口端口该放在哪里呢?如果依然放在领域层,就很难自圆其说。例如,出口端口EventPublisher支持将事件消息发布到消息队列,要将这样的接口放在领域层,就显得不伦不类了。倘若不放在位于内部核心的领域层,就只能放在领域层外部,这又违背了整洁架构思想
3、是不是有别的理论支撑解决问题2
为了生成api的swagger yaml文件
包结构:
通过swagger生成的api接口与api中的model
包结构:
controller层,放置controller
包结构:
按DDD分层规范,controller属于ui层,处理restful请求
为什么还有一个xxljob包,从能力区分,xxljob放到infra层才对。这个原因类似generator-assist-dao模块,xxljob的handler需要调用application service,需要依赖service module
因此可以把xxljob作为远程请求的一个入口,与controller一样归在ui层
这儿引出一点思考,controller真的是ui层吗?能划分到别的层吗?
有几种设计思路
从上面的分析,可以看出controller逻辑上是归到infra层,但物理上不能放到infra模块;也不能简单把controller看作MVC中的C,还有很多像xxljob样的入口
这儿是否可以借鉴《DDD之形》中的端口和适配器架构
把controller看作driving adapter,既然区分这么复杂,那可不可以简单点,加厚controller,整合入口与application service
简单点分成两部分:远程服务与本地服务
domain层,但现在还是三层结构的思路,什么类都有,app service,domain service,dto,event 甚至还有基础设施层类
包结构
基础设施层
包结构
现在的包结构很丰富,最常见的包就是gateway,配合acl与外部交互
U表示上游(Upstream)的被依赖方,D表示下游(Downstream)的依赖方。防腐层(ACL)放在下游,将上游的消息转化为下游的领域模型
结合generator-assist-dao模块的问题,是否可以扩大ACL,而不仅限于gateway中,像资源库一样,不必完全遵循DDD只抽象repository,像访问第三方应用,缓存,消息都可以抽象出来,契合端口履行的职责一样
generator-assist-dao generator-assist-client-api assist-client-api assist-ohs assist-service assist-acl start
根据上面的分析,这一层可以更厚实些
改名为assist-ohs
OHS,open host service 开放主机服务,定义公开服务的协议,包括通信的方式、传递消息的格式(协议)
包结构
domain层
包结构
扩大了基础设施层,隔离领域层与外部依赖,对所有外部环境一视同仁,无需针对资源库做特殊化处理,如此也可保证架构的简单性,repository、client、cahce...
领域层依赖port接口
包结构
模块划分以及包结构还只是一家之言,一是有充足的理论体系支撑,不管按DDD标准,还是变形,更多地有理有据,与团队、也与自己达成一致;二是domain的抽象,一切都是为了领域模型的稳定性和扩展性,形只是表象
我们这个项目还是太注重了形,最重要的domain还是过弱
https://cloud.tencent.com/developer/article/1805611