Hello,大家好,我是人月聊IT。
今天我准备接着跟大家聊一下领域建模和领域驱动设计。首先提出一个明确的观点,就是领域建模很多思想是相当好的。但是就当前大部分的软件开发项目来讲,90%以上的项目其实都没有去完整实践领域驱动设计的必要性。基于这个话题,我今天准备分三个方面展开来讲。
1. 领域建模思想-横向分层
第一个就是进一步讲一讲领域建模的思想。大家都知道,领域建模的一个核心思想是一种横向分层领域驱动的思想,而我们传统的软件开发更多的是纵向从展现层到逻辑层到数据库层,一个个竖井式的纵向建设的思想。所以你开发一个功能虽然用了面向对象的开发语言,但很多时候你仍然是结构化的开发方法,仍然是数据库表驱动的开发方法。任何一个功能,你都在想这个表单录入以后,这个数据究竟存到哪一个数据库表里面去。或者是一个查询功能,一开始就在想,你要从哪一个数据表或者是视图里面把数据查询出来。所以你原来的很多开发,包括设计,都会跟你的前端的界面展现,跟你后端的数据库数据存储,包括你采用的开发框架做了相当多的一些耦合或者是绑定,从而导致你没有将重心真正去关注你领域层的逻辑上面去。
而领域建模的思想,它更多是一种横向分层的思想,从领域建模的整体的架构里面可以看到它最下面是基础设施层,中间是核心的领域层,在上面是应用层。通过横向分层,核心的重点就是它进一步希望去实现业务和技术的解耦。我们在前期进行架构设计的时候,我们的重心一定要放在你整个领域模型和领域层的构建上面。同时整个领域层它是跟技术无关的,跟你选择的开发语言、开发框架、是不是微服务架构都没有关系。同时,这个领域层跟你后端的数据库持久化存储也没有关系,跟你前端究竟是一个APP还是一个传统的Web页面也没有关系。把这些东西都抛掉以后,你的重心就是把整个核心的领域层设计好,而且这个领域层它可以灵活的后面去适配不同的上层的应用界面展现底层的数据库,只要是属于领域逻辑的核心的业务逻辑的,都应该在领域层里面实现,而不应该造成领域层逻辑的外泄。比如说,你把这个核心的业务规则外泄到你的上层的应用层里面,或者是你把这个核心的业务规则放到了你的数据库的存储过程里面,都不是合适的方式。这个才是领域建模、领域驱动最最核心的思想,这是我想强调的第一个点。
2.微服务的拆分粒度
第二个点,DDD领域驱动设计这本书包括Evans提出这么一个领域驱动的概念的时候,是在2004年还是2005年相当早的时间,就当时我还在中兴通讯,但是当时这本书已经有了。我们当时更多的实践的是叫RUP统一软件过程,包括基于RUP的一些相应的包括基于4 + 1软件架构设计视图的UML的面向对象的分析设计,我们更多的是在实践这个东西。领域建模的很多的内容,更多的是一个辅助,包括在小二十年前领域驱动设计也没有说相当的大火,实际领域驱动设计的进一步的火热,应该是再到16年开始,随着整个微服务架构设计的火热,因为在微服务架构里面出现了一个关键的需要解决的问题,就是我们常说的你微服务架构下面,你的微服务模块怎么样去做拆分,刚好领域驱动设计对微服务的拆分起到了一定的作用。
但是实际我们回过头来看,包括我前面也讲过,微服务的拆分我们谈到了两个关键点,微服务的拆分它有两种思路,一种是核心的数据和对象驱动的思路去做微服务的拆分,还有一种思路是按照实际的业务流程分析的思路去做微服务的拆分。我们传统的大的单体应用,比如说你有一个供应链系统,有一个HR的系统,这一些系统你要大拆小,更多的仍然是按照流程分析的思路,你拆出关键的阶段,每个阶段就是独立的微服务。但是如果你本身就在构建企业大的数字中台,因为中台的建设本来就是一种横向分层的思路,它和领域驱动里面讲到的横向分层很多思路是一致的,中台的建设的时候,你会看到它更多就是数据驱动对象驱动的思路。
所以说,你在构建一个企业复杂的大中台的时候,你基于领域驱动的思路去做微服务拆分是合适的,包括领域驱动里面谈到了你怎么样通过头脑风暴、事件风暴去识别关键的事件,通过事件的聚合找到关键的领域对象和聚合根,然后将每一个领域对象转成一个个的微服务。但是这里面又有一个问题,在实践的过程中,你会发现每一个领域对象如果都变成微服务,那微服务的粒度就太细了。你任何一个应用,会发现稍微一拆就是几十个微服务,这么多的微服务后面的管控治理都是灾难,包括我在前面讲领域驱动的时候也提到了,我们即使用领域驱动的思想去拆微服务也不是到每一个领域对象,而是基于相应的上下文限界上下文的一些分析,拆分出关键的业务子域,每个业务子域才是适合的一个微服务的粒度。但是,怎么样去拆分出关键的业务子域?哪一些相应的领域对象应该划到同一个业务子域里面?在领域驱动建模或者说分析里面,并没有给出一些标准化的详细的参考方法,这是我想强调的第二个点。
3.很多项目复杂度低,用DDD是杀鸡用牛刀
第三个点进一步再来解释,就是我刚才谈到的当前软件开发90%以上的项目,它实际没有必要去完完整整地去实践领域驱动设计,你去借鉴领域建模的很多的思想就可以了,包括我刚才谈到的横向分层的思想、聚合的思想、API驱动的思想,整个领域架构设计和开发框架和技术脱离,业务和技术解耦的思想都可以借鉴,但没有必要完完整整地去实践。其里面有两个原因。
第一个就是当前大部分的软件项目,很多东西,它的业务规则、业务逻辑本身就不复杂,你看着相应的需求、文档原型设计,你基本上马上都能够完完整整想清楚这个功能究竟怎么样去设计,怎么样去实现。那在这种情况下面,你再去生搬硬套的去套用DDD领域驱动的建模设计或者是开发的框架,完全没有必要,这完全就是杀鸡用牛刀。反而是将你的整个的源代码开发项目变得异常的重,异常的复杂,反而使后续相对的功能的变更更加的麻烦。对于这些简单功能,你用最最简单的方式实现,可能只需要两个小时,半天就能够全部完全开发好和实现完并上线的。但是你用了一些复杂的分层框架、复杂的领域建模,你会发现这个功能一做就是两三天,反而是开发效率和敏捷性都达不到要求。这是我想强调的第一个原因。
第二个原因,大家注意对于复杂的项目来讲,你如果仅仅是基于领域驱动建模领域驱动设计又不足够,包括DDD领域驱动设计这本书,它的一个副标题就叫应对软件复杂性之道。但是,软件的复杂性的应对不是简单的横向分层,也不是简单的你去重心放到领域层的逻辑,实现业务和技术的解耦。真正软件的复杂性还体现在一个关键的地方,对于大一点的软件,大一点的业务需求的实现,你会发现当去做了相应的业务的梳理分析以后,你还必须去考虑关键的东西,就是你识别出来的核心的领域对象或者是聚合根以后,这些领域对象之间,它横向还会发生相应的交互和联系。你在梳理业务以后梳理出来相应的业务规则,还需要去识别成相应的一些规则类,这些规则类又跟我刚才讲的核心的领域对象之间又会发生交互和联系。但是我刚才讲到的这一些内容,其实你仔细去看领域驱动架构设计建模的书,对于我刚才讲到的这一些关键点,它其实并没有很多系统化的分析设计的方法,反而是最最传统的RUP统一软件过程、最最传统的4+1软件架构视图,包括我们说的你基于面向对象的分析和设计的思想理念,你在做OOD之前,你在前面还有一个OOA,而领域驱动设计这本书里面其实讲面向对象分析这一块的内容,相对来说,我个人觉得实际是偏少的。
所以简单总结就是,对于简单项目你没有去应用DDD的必要性;对于复杂项目,你单纯用DDD,又没有办法解决我刚才讲到的一些软件复杂性的问题,导致你真正去用DDD的时候,会发现在落地的过程中,仍然会遇到相当多的问题或者是阻碍。这也是今天我为什么提出的一个重要观点,就是领域建模、领域驱动的很多思想是好的,但是大部分的软件项目,你去借鉴关键的思想就可以了,没有必要完完整整地去按照DDD领域驱动设计这本书的很多详细的思路去完全严格的一个步骤,一个步骤去实践,完全没有这个必要。
好了,今天的简单分享就到这个地方,希望对大家有所启发。再见!