DDD初步认知
在写了无数3层架构的业务代码后,经常痛苦的发现,facade或者service层的业务逻辑膨胀的太厉害,一段时间后梳理整个业务逻辑会成为一个困难的事情。
问题出在哪?
业务膨胀的层中,往往包含这些逻辑:
- 对象转换
- 逻辑编排
- 资源存取
面向库表的编程中,这些逻辑会基于一个顺序流程在整个业务过程中反复。虽然可以做到一定的复用&抽象,但往往仅仅只是强制性的代码疏散,尽量做到代码复用等出发点而已。
这种方式导致了几个问题:
- 第一,围绕业务领域对象的逻辑散列至更多的地方,使得理解业务逻辑更为困难;
- 第二,代码即业务的初衷基本不现实,开发人员很难全局性的了解业务全貌;
- 第三,膨胀&散开的不可控导致分层测试很困难,实际module基本仅有最复杂的那个有关键业务逻辑,其它部分有缺乏场景的碎片逻辑,没啥可测性,无论大改小改都绕不开对这个模块的全面测试;
- 第四,因为这个膨胀的不可控,开发较难清晰界定任务所涉及的改动点,技术债务持续堆高;
DDD要怎么解决?
基于这些问题,发现DDD可以一定程度上解决。
首先,分层仍然存在,但是单纯的贫血模型转型为领域对象后,可以将部分逻辑内聚其中。比如对象转换,数据校验等。
其次,针对资源,一般有数据库,缓存,mq等,可以按上下文抽出一个独立的资源接口单独提供数据存取服务。
最后,在领域上下文中提炼出领域服务,围绕领域对象的领域行为下沉到领域服务中进行。
如果需要接入其它外部服务,可以引入facade防腐层,防止外部的变化影响当前模块的内部逻辑。
这样一来,业务膨胀层的主要内容就只剩下逻辑编排。经过上述改造后,逻辑编排就进化为单纯的领域上下文逻辑编排。在DDD中,这对应应用服务层。
业务领域的高内聚,低耦合是什么?
逻辑上有强相关性的类,物理上最好能收敛在一个module中。同理,逻辑上弱相关的类,物理上尽量分离到不同的module;
一个业务领域,按场景会分散聚合出一定数量的业务上下文,按具体业务上下文进行逻辑聚合,而不是从技术维度将逻辑分散到那些handler,processor,helper之类中去;
参考资料:
https://tech.meituan.com/2017/12/22/ddd-in-practice.html