166. DDD战术设计改造实践(一):DDD简介

前言

在快速发展的互联网行业中,企业的业务需求和技术架构之间的关系愈发紧密。如何在复杂多变的业务环境中保持系统的稳定性、灵活性与可扩展性,一直都是技术团队面临的重要挑战。

注:由于篇幅有限,本系列文章以实践为主,DDD相关基础概念请读者自行查阅资料了解。希望通过这篇文章,能够帮助同行们更好地理解DDD战术设计在复杂业务系统中的应用,并为未来的技术创新与业务发展提供借鉴与启发。

一、 DDD是什么

在这里插入图片描述
在开始之前,我们还是先简单聊一下DDD(Domain-Driven Design 领域驱动设计),本文假设读者对DDD已经有一些了解,不会对DDD的一些基础概念做过多的解释和说明,读者也可以直接跳过本节内容。

谈到DDD,我们都会不由自主的把它跟大型复杂系统挂钩,晦涩的概念、实践方式参差不齐,这些因素都使得我们对其敬而远之。其实,DDD作为一种软件设计思想一直存在在软件的生命周期中,它无关系统的大小。比如像上下文拆分、实体、值对象、资源库这些概念,并不只是存在大型系统中,而是作为软件模型的本质存在所有的系统中。

DDD为我们提供了两种设计:战略设计和战术设计

  • 战略设计作为一种思想和规范,去指导业务领域划分,偏向整体业务模型设计
  • 战术设计偏向编码与技术架构实现,战术设计把技术模型从业务模型中抽离出来,使代码==业务本身,所以说战术设计与技术编码是息息相关的。

我们知道,业务问题是所有产品开发的基础,在DDD中,我们可以把业务到技术实现的过程分为两个空间:问题空间和解决方案空间:

在这里插入图片描述

我们把领域拆分为多个子域,并通过上下文映射图提取出实体的限界上下文,这一过程就是DDD的战略设计;

而把问题空间的领域、子域概念通过解决方案空间的描述语言实现软件模型,这就是DDD的战术设计。

本篇实践主要针对战术设计,不会过多的介绍战略设计。

DDD能为我们带来什么

  • 清晰的模型边界:DDD不是创建模型,而是模仿并实现现实世界的业务模型,模型边界清晰了,软件可维护性和可扩展性也就随之增加了

  • 更好的企业架构:根据康威定律,软件架构对应企业组织架构,领域划分的越合理,企业架构就越清晰,可以帮助企业建立更高效的组织架构

  • 敏捷、迭代式和持续建模:DDD遵循敏捷工作方法,可以降低持续迭代对软件可维护性的冲击

究其根底,DDD带来的是从业务模型到软件模型的转换,让固有的软件模型更加贴近复杂多变的业务,降低软件后期的维护成本,使软件变更更加灵活。

二、架构演进-六边形架构

一个软件架构的优劣,可以用它满足用户需求所需要的成本来衡量。如果该成本很低,并且在系统的整个生命周期内一直都能维持这样的低成本,那么这个系统的设计就是优良的。如果该系统的每次发布都会提升下一次变更的成本,那么这个设计就是不好的。

——架构整洁之道

就像《架构整洁之道》一书所说,如果一个系统的每次发布都会提升下一次变更的成本,那么这个设计就是不好的。那么DDD战术设计推崇的架构模式是如何控制变更成本的呢?

我们知道,架构与底层工具应该是完全独立的,一个良好的架构应该围绕业务来展开,这样的架构设计可以在脱离架构、工具及使用环境的情况下完整的描述业务用例。并且,架构应该在满足业务需要的前提下,尽可能地允许用户能自由的选择工具。即架构定义了一系列的服务接口,这些接口的具体实现(使用何种组件、框架),应该与架构是独立的。

此外,良好的架构设计应该尽可能地允许用户推迟和延后决定使用什么框架、数据库、web服务以及其它与环境相关的工具(例如spring、hibernate、mybatis、数据存储、消息组件等)。同时,良好的架构还应该让我们能很容易的改变这些决定。总之,良好的架构应该只关注业务用例本身,并能将它们与其它周边因素隔离开来。

下面笔者将带大家一起看一下DDD架构的演进过程。

2.1 分层架构

在这里插入图片描述

在最初设计时,多数分层架构为了层级职责清晰,会比较偏向严格分层架构。但是经过多次的转手和迭代后,严格分层架构会逐步演变成松散分层架构,各层职责越来越不清晰。比如可能为了方便,直接在controller里直接通过dao访问数据库;service的职责也越来越混乱,里面可能混杂了基础设施的远程调用、资源库获取等等不属于它的职责。长此以往,对系统的可维护性带来巨大的挑战,成员之间互相接手时需要花费大量的时间才能真正上手,随时都会有踩雷的风险,无法做到研发资源的最大化利用。

2.2 DDD架构模型

在这里插入图片描述

为了把业务逻辑和技术实现分离开来,DDD分层架构独立出了一个领域层,用于业务逻辑的聚合。并且应用依赖倒置,使整个框架更加容易扩展,做到技术细节与业务逻辑的完全解耦。

在实际应用中,很少会有完全的依赖倒置,而是下面这种架构模型:

在这里插入图片描述

我们只对更偏向技术细节的层级(基础设施层)进行依赖倒置,用户接口层和应用服务层一般都比较简单,所以他们还是上下级的关系。

在应用了部分依赖倒置之后,实际上分层的概念就比较模糊了,我们会看到领域层被用户接口层和基础设施层包裹在整个架构的最内层,这个时候我们的架构模型就变成了下面这种模型:六边形架构模型(也叫整洁架构,或洋葱圈架构)

2.3 六边形架构

在这里插入图片描述
通过上面对架构演进的介绍,可以看到六边形架构并不是一种新颖的架构模型,而是从另外一种角度看待分层模型,它应用依赖倒置原则把分层架构推平,然后往里面加入了一些对称性。六边形架构是一种具有持久生命力的架构模型,当有新的客户端接入时,只需要添加一个入站适配器和对应的出站适配器,然后入站适配器把客户输入转换成API所理解的参数,输入和输出都可以通过多样化的方式来实现。

并且,六边形架构符合整洁架构的依赖关系原则:外层的变更不会影响到内层的代码。比如上图,我们把外层的基础设施由数据库换成其他组件时(如将MySQL换成了Redis),对我们内部的业务逻辑是没有任何影响的

三、编码实战

3.1 架构及模块划分

在这里插入图片描述

模块介绍

本次编码实战,我们使用的架构完全是对应了刚才介绍的六边形架构,主要包括以下模块:

  • starter:启动器/用户界面层;如:controller、provider、task、consumer

我们这里的做法是把starter启动器和用户界面层整合到一起。其它做法:单独一层只放springboot的启动器和加载相关组件,但需要独立出一层用户界面层(因为starter和用户界面层比较轻,所以可以整合为一层)

  • application:应用服务层,对应传统分层架构的service层,但更加轻量;应用服务层只用来编排业务逻辑,不做复杂业务的实现细节;

注意:application中的service绝对不允许平级调用,只允许调用domain层中的聚合、领域服务、资源库(如果出现平级调用的情况,就应该考虑把调用逻辑放在领域层中用于多业务复用)

  • domain:领域层,从传统分层架构service层中抽取的一层,用于存放领域模型和领域服务,通过领域模型和领域服务聚合所有业务逻辑;在领域层中,只能输入和输出领域模型,再由其他上层根据需要转为需要的模型结构

domain中的service,除通用子域外,不允许平级调用

  • infra-repository:基础设施层-资源库,对应传统分层架构中的dao,但职责范围更广,只要是与资源、持久化数据(mysql、redis、ES等数据存储组件)相关都可以放在这里

  • infra-remote:基础设施层-外部服务;其他限界上下文的远程调用

  • shared:公共组件,如:基础常量、工具类、cache、interceptor、configuration等相关配置组件

3.1.1 与传统三层架构的对比

关键改进项:业务编排、依赖倒置、可插拔组件

业务编排:相对于传统三层架构,DDD架构模型把业务逻辑层拆分为应用服务层+领域层,应用服务层只做业务编排,具体的业务聚合逻辑交给领域层来实现。

优势:解耦业务编排和业务实现,使业务逻辑更加清晰,任何人都可以花费极短的时间了解业务逻辑,并安全的对代码进行扩展和优化。

依赖倒置:应用依赖倒置后,领域层成为整个架构的最内层(注意不是最底层),它不依赖任何外部组件,它只关心当前上下文相关的领域模型

优势:真正面向对象,以业务为核心,符合稳定依赖原则

可插拔组件:领域层不需要关心基础设施使用的技术组件,它只定义基础设施接口,输入和输出都是领域模型,并应用依赖倒置,让具体细节由各个基础设施通过插件的方式去实现;

优势:在更改底层技术组件时(例如mysqlRPC、数据增加缓存等等),领域模型的业务逻辑不需要做任何改变或以最小的改动就可以满足技术层面的优化升级

3.1.2 设计原则

整体架构遵循了组件设计基本原则:

  • 领域模型的聚合逻辑完全独立于其他各层,遵循共同闭包原则

  • 业务逻辑聚合在领域模型和领域服务中,遵循共同复用原则

  • 基础设施组件可插拔,易扩展和修改,遵循稳定依赖原则

  • 基础设施层应用依赖倒置,由技术实现细节去依赖领域层定义的业务抽象,遵循稳定抽象和无依赖环原则

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值