目录
文章目录
- 目录
- 传统分层架构存在的问题
- 领域驱动设计
- 领域驱动设计思想
- 领域驱动设计面临的问题
传统分层架构存在的问题
传统的分层架构会在 Service 层、Manager 层实现具体的业务逻辑,使用 DO、DTO、BO、VO 等进行数据传输,数据和行为基本完全隔离。
- Service 层:相对具体的业务逻辑服务层。
- Manager 层:通用业务处理层,具有有如下特征:
- 对第三方平台封装的层,预处理返回结果及转化异常信息。
- 对 Service 层通用能力的下沉,如:缓存方案、中间件通用处理。
- 与 DAO 层交互,对多个 DAO 的组合复用。
这样的分层架构存在一个问题:因为分层采用的是包的形式进行的层间隔离,所以需要每一位开发人员都理解并且自觉遵守以上规范,但是在实际工作中因为开发人员对 Service 层和 Manager 层的区别并不特别清楚,或难以完全遵守手册中的规范,就导致 Manager 层除了沉底一些通用能力以外和 Service 层并没有什么本质区别。在实际的业务代码中 Service 层和 Manager 层都充斥了大量的第三方依赖,对系统的稳定性有很大的影响。每依赖一个第三方服务都要各种异常问题,这些异常处理的代码往往会和业务代码混在一起,当这种代码多了以后会使代码的可读性非常差。随着业务迭代速度也很快, Service 层和 Manager 层代码量迅速膨胀,业务逻辑变得越来越复杂。
领域驱动设计
领域驱动设计的概念是 2004 年 Evic Evans 在他的著作《Domain-Driven Design : Tackling Complexity in the Heart of Software》(领域驱动设计:软件核心复杂性应对之道)中提出的。
领域驱动设计是一套方法论,指导我们将复杂问题进行拆分、拆分出各个子系统间的关联以及是如何运转的,帮助我们解决大型的复杂系统在落地中遇到的问题。简而言之,DDD 是一个分而治之的过程,是一系列分而治之的方法论。
Evic Evans 在著作中将软件系统的设计分为 2 个部分:
- 战略设计:提出了域、子域、限界上下文等重要概念,指导我们如何拆分一个复杂的系统。
- 战术设计:提出了实体、值对象、领域服务、领域事件、聚合、工厂、资源库等重要概念,指导我们对于拆分出来的单个子系统如何进行落地,在落地过程中应该遵循哪些原则。
以电子商务系统举例,大型电子商务系统的拆分过程中我们可以把电商系统这个单体应用拆分成:订单子系统、库存子系统、物流子系统、搜索推荐子系统等等。
DDD 在战略层面上的域、子域、限界上下文的划分思想和微服务的划分不谋而合。微服务的划分是也是将一个大的问题拆分成若干个小的问题,每一个小的问题用一个或多个微服务来解决。
- 域对应一个问题空间,也就是上例中的电商系统;
- 子域是把域这个大的问题空间拆分成若干个小的更容易解决的问题空间,也就是单体应用向微服务演进过程中划分出来的各个子系统;
- 限界上下文是解决方案空间,每个子域对应一个或多个解决方案空间。
而 DDD 的战术设计部分就是指导我们如何落地一个系统才可以使系统具备高可扩展性、高可读性。
系统最终都要以代码的形式落地,而落地的工作都是由普通的开发人员来完成,系统是否具备高可扩展性、高可读性直接影响了整个团队的效率。
总结一下,DDD 在软件开发中的主要起到如下作用:
- 帮助分析理解复杂业务领域问题,描述业务中涉及的实体及其相互之间的关系,是需求分析的产物,与问题域相关。
- 是需求分析人员与用户交流的有力工具,是彼此交流的语言。
- 分析如何满足系统功能性需求,指导项目后续的系统设计。
领域驱动设计思想
DDD 的革命性在于其是面向对象分析的方法论,它利用面向对象的特性(封装、多态)有效地化解复杂性,而传统 J2EE 或 SSH 框架等事务性编程模型只关心数据。这些数据对象除了简单的 setter/getter method 外,不包含任何业务逻辑,业务逻辑都是以过程式的代码写在 Service 层中。这种方式极易上手,但随着业务的发展,系统也很容易变得混乱复杂。
DDD 关心的是业务中的领域划分(战略设计)和领域建模(战术设计),其开发过程不再以数据模型(Data Model)为起点,而是以领域模型为出发点,研发过程如下图所示。
领域模型对应的是业务实体,在程序中主要表现为类、聚合根和值对象,它更加关注业务语义的显性化表达,而不是数据的存储和数据之间的关系。
领域驱动设计面临的问题
DDD 尚存在一些争议,当前的核心问题是针对软件开发导致软件结构越来越混乱,越来越复杂,越来越难以维护的问题,开出的药方超越了当前众多公司的发展阶段和实操水平。
换句话说,当前大多数互联网企业软件开发经验尚且薄浅,缺乏积累和人才积累,盲目运用 DDD 技术开发,会极大增加开发成本。DDD 对开发者素质要求非常高,甚至达到了专家级要求,主要反映在三个方面:
- DDD 的设计和开发成本非常高。首先需要雇佣领域专家和掌握 DDD 设计与开发方法的开发者,在开发之前必须前置领域设计流程,在项目建设工期非常紧张的情况下,DDD 将导致开发效率降低,开发难度增大,开发工作量剧增的问题,不利于项目建设过程中的贯彻和坚持;
- DDD 缺乏成熟的 IT 大厂实践、分享和技术支持。目前社区资源不足,开源工程,例如:github/micro-company、github/ddd-leaven-akka-v2 和大型实践项目比较少。了解和掌握 DDD 的软件工程师凤毛麟角、不同公司业务场景各不相同、真正理解垂直市场的领域专家和全面掌握 DDD 设计的专家就更少了;
- DDD 的思想范式相对 CRUD、MVC 过于复杂,概念繁多,过于抽象,表述不够清晰,难以理解,不易被初级开发者掌握。DDD 的范式流派目前主要有 EDA、CQRS、Event Sourcing、In-Memory、DCI、CSP 等流派,它们之间互有冲突,不分伯仲,各自从某一个角度出发,解决部分问题,但也引出了其它新问题,例如:数据一致性危机,事务危机和代码复杂度问题,在当前绝大多数公司和业务场景下,必须混合使用,目前尚未出现大一统的理论架构。当前仍缺乏成熟的配套技术以降低开发者学习和运用其的难度和成本。主要体现在缺乏类似 Spring 这种现象级别的成熟框架,允许一个在校生学习一个月就基本可以进行生产级的代码开发工作。当前尚且不够成熟的 DDD 框架 AxonFramework、AKKA 或国产 JdonFramework 等学习成本比较高,不易被缺乏开发经验的工程师快速掌握应用。