传统三层架构与DDD架构

DDD 是什么

2004 年,Eric Evans 在发表了一部名为《Domain Driven Design》的著作,其中提及了一套从系统分析到软件设计的方法论——领域驱动设计,简称 DDD,领域建模的思想随即铺展开来。

DDD 设计的目标是实现软件系统与业务需求的高度契合,提高开发效率和质量,同时也能更好地应对复杂性和变化性。它强调以业务为中心,通过深入领域知识和建立有效的领域模型,来驱动软件设计和开发的整个过程。
其中几个核心理论提炼如下:

1. 领域驱动设计——软件设计复杂性解决之道。它是为了解决复杂软件设计的一种优秀方案,但不是唯一。

2. 它把所有的业务规则、定义、范围、知识等抽象成了一个大的概念,叫做领域。比如用户支付的业务场景,叫做交易域;平台提供售后等服务叫做服务域(或客服域),还有其他诸如金融域,人效域,物流域等。

3. 它应对复杂性的思想,总结下来既简单,又精炼,叫做“分而治之”。把最大化的领域(复杂问题)分为下层的一个个子域,同时每个子域又规定好边界和核心实体,通过一系列的拆分、归类、衍生,最终找到最优解。

4. 业务是在变的,如何从多变的业务环境中,保持内核的稳定性和扩展性,适应多变的业务发展,这是应对复杂性的第二个关键点。

5. 领域模型是一套贯穿了整个软件,从设计到交付的生命周期的方法论,因为他的共识性,可以让开发、产品、架构师围绕着统一的模型去设计和探讨,不至于走样。

6. 领域模型的图形表达方式,在实操上除了实体模型图的表达比较特殊,其他的时序、状态机、流程图其实无特殊性。

7. 领域模型是业务的抽象,这点很关键,同时领域模型的设计应该是基于现实,但不等于现实。

8. 评论领域模型设计是否优秀的方法很简单:5 年后,剔除掉所有的增值域,第一版建设的域模型是否还符合优秀的稳定性、扩展性和灵活性。

9. 领域模型不是所有的软件工程都适合,我经常会问面试者一个问题,一个 FBI(数据看板系统),一个电商交易系统,它们都适合用 DDD 吗,为什么?

传统三层架构

传统服务通常使用三层架构:

• 门面层: 作为服务暴露的入口,处理所有的外部请求。部分情况下,门面层甚至不需要单独定义对象而是直接使用服务层的实体定义。

• 服务层: 作为核心业务层,包含所有业务逻辑。并对基础层能力进行简单组合提供一定的能力复用。通常服务层会进行实体定义来防止下层对象体直接暴露给外部服务,导致底层任何变化都有可能直接传递到外部,非常不稳定。

• 基础层: 用来存放 dao 和外部 rpc 服务的封装,二者可以拆分为不同的 module,也可合二为一,以不同 package 进行隔离。

三层架构特点就是简单,适用于一些无复杂业务场景的小型应用,或者“数据不可变”作为基础原则的 DOP(面向数据编程)服务。

但是当业务场景稍微复杂一些、调用层级较多时,可复用性、可维护性就都非常差了,很多代码都耦合在一起,牵一发动全身。

DDD 架构

DDD 架构可以看做是整洁架构的一种实现,分层职责如下:

• 适配层: 用来做外部不同端请求的适配器,隔离不同端的协议差异,包装不同端不同样式的响应体。

• 应用层: 用例、任务入口、消息队列监听均在这一层,可以理解为业务流程的入口,通过聚合根的构造执行相应的命令操作。

• 领域服务层: 包含核心的领域服务定义,并定义了 gateway 来做一层依赖倒置,使基础设施层仅做实现。

• 基础设施层包含一切基础能力:数据库、ES、远程调用封装等等。

优点

• 核心稳定: 领域模型在依赖链上是顶层角色,不依赖任何其他模块,所以极其稳定。其他任何业务域、存储、边缘能力的变化都不会对领域模型造成影响。

• 敏捷: 适合不同团队一起开发和维护而不会产生冲突。

• 可拆分: 当有届上下文随着演进逐渐膨胀时,很容易拆分成微服务。

• 可扩展: 添加新的功能非常简单,从而使得开发人员能够更快的部署和调整。

• 可演进: 良好的可测试性带来非常低的重构成本,不会随着不断迭代导致项目成为难以修改的“大泥球”。

如此多的优点自然带来明确的缺点

• 专业性要求较高: 需要对业务、架构原则理解深刻的人员进行设计和维护,不恰当的领域模型将使后续迭代极为痛苦。

• 开发成本高: 复杂的架构设计,更多的架构分层,自然带来代码行数的指数级增长。尤其是项目前期的开发任务变得异常繁重。

• 不再适合简单的业务场景: 实现一个简单的 CRUD 显得过于复杂。

• 改变决策困难: 尝试使用整洁架构需要和团队的管理层和其他成员达成一致,这往往需要非常强大的说服力。如果在架构演进过程中想切换回其他架构模式也十分困难,几乎是整个项目级别的重构工作。

你可能感兴趣的:(架构)