浅谈领域驱动设计实践——董炎焱

简介: 近年来领域驱动设计(Domain Drive Design)大火。那么我们为什么要学习领域驱动设计,它适合用于哪些场景?怎么去用?在用的过程中,又有哪些需要注意的地方呢?

关于可组装开发理念

Gartner在其发布的《企业机构在2022年需要探索的重要战略技术趋势》中提出了Composable Applications组装式应用的概念,指出组装式应用由以业务为中心的模块化组件构成,具备更易使用和可重复使用的代码,可加速新软件解决方案的上市时间,并释放企业价值。

那么具体如何实现组装式应用呢?其核心是封装业务能力Packaged Business Capability,简称PBC)。在不断变化的业务环境中,业务适应性需求将引导企业转向使用支持快速、安全和高效应用变化的技术架构。在这种背景下,需要将一个个的业务对象或功能模块化,以实现快速“组装”或替换。组装式应用增强了这种适应性。有利于更安全更高效更快的变更和迭代,提升敏捷性减少重复劳动

在这点上,领域驱动设计(DDD与之不谋而合。

领域驱动设计的“新”

传统的系统架构多采用MVC三层模型设计,即Controller->Service->Dao分层结构,所有的业务逻辑都集中在Service层。随着业务持续发展,这种面向事务脚本进行编码的方式,会使代码臃肿,可复用性差架构腐化很快。

image.png

领域驱动设计是对面向事务脚本编程的进一步升华:

  • 它强调“领域”的概念,将服务提供(Service层划分为domain层和App
  • 把现实对象映射到代码中的领域对象,提升代码可读性
  • 通过稳定的领域模型来提供代码复,提升研发效率和代码质量
  • Infrastructure层包括所有对基础设施和其他服务的依赖。在Mapper之上封装Gateway,用于领域层调用;调用MQ库发送消息等逻辑都也在Infrastructure
  •  Domain层对基础设施的依赖通过DIP(依赖倒转)解耦,Domain层可以独⽴存在

目前使用较多的是由阿里DDD专家 张建飞设计的COLA架构,详见https://github.com/alibaba/COLA,这里不做赘述

领域驱动设计是YYDS吗?

领域驱动模型设计能够构造高扩展性高可维护性快速迭代的架构。在实体比较复杂、各实体关联比较多,操作中可能涉及其他实体方法比较紧密的时候,用领域驱动设计是比较好的选择。它能使功能操作逻辑易于理解,模块分界清晰,易于后期扩展改造,较好地支撑产品演进。

如果是一个较小型的项目后期演进一般,操作多是简单的crud,实体属性比较少且并不涉及复杂业务逻辑。这时使用领域驱动设计我倒觉得有点大材小用,反而传统的MVC架构就足以应对,且开发起来更加简洁。因为领域驱动设计开发会涉及比较多的DO<->领域模型<->VO/CO/DTO对象的转换,在简单的业务逻辑背景下,这些转换看起来占比比较重,使得代码不是那么简洁,俗话说:杀鸡焉用牛刀?

当然,在现阶段和未来,绝大多数的应用都不只是“简单”的,领域模型驱动设计会得到更好的发展和普及。也不排除将来会出现更好的开发设计模式,因为哪里有需求,哪里就有解决问题的办法。

我们怎么更好地去用它?

比如某个应用以公司的“资产”为核心对象之一,衍生出很多相关的功能和操作。“资产”这个对象本身包含二三十种属性,围绕“资产”的业务逻辑包含:资产查验,标准化管理,属性列表完善,上、下架,审批,用户对该资产是否有权限等等。这些业务逻辑往往比较复杂,如果都通过dao->Service层来处理,会带来以下的种种问题:service层非常臃肿,代码比较散乱,重复性代码较多,业务方法不够内聚,维护梳理障碍,扩展/变更性差……

如果将“资产”作为领域模型,除了它的属性外,将其涉及的业务操作抽象成方法也放在里面,那么对于代码可读性、对象及对象操作的范围边界、业务模块等将会比较清晰。

用领域模型设计后,service层的代码是这样的:

image.png

我们将多变的业务逻辑从service层拆出来,整合进领域和gateway,服务层专注于服务本身。从上面的图中可以看到,一个业务操作涉及了多个领域的多个业务方法单元,不仅实现了业务逻辑复用,是不是还很简洁明了呢?

这里要提示一点:要注意领域驱动设计的思考抽象方法,要尽可能遵循其约定,避免在后续的迭代更新过程中沦为之前的实体作用。

下面是一些使用心得分享:

领域类需要完整的构造

我们通常是通过两种方法来构造领域类:(1)数据库的表结构(2)抽象业务操作的实体和相关业务方法。

要注意的是:领域类一定要构造完整,对于不同的使用领域类的场景下,领域类对外的暴露都是完整且一致的。 不要出现部分属性没有初始化的情况。

尽量将逻辑沉淀为领域类中的方法,保持较好的结构和复用率

避免写着写着就绕开领域模型,增加逻辑直接调用Mapper处理业务。这是大多数习惯传统MVC架构的程序员在使用DDD之初一段时间内常犯的问题。

Gateway不要揉太多业务逻辑

      在底层infrastructure模块,gateway的作用主要是为了让domain类与基础设施层解耦,如领域类的保存行为不应该感知后端存储是MySQL还是其他数据库等,所有的业务逻辑应该沉淀在domain类中,通过gateway来对接不同的基础设施。

懒加载技巧

      领域对象会与其他的领域对象产生关联,每次构造领域对象会导致大量关联领域对象的初始化。大多数的领域对象初始化不仅会消耗内存和计算量,还会进行数据库IO,从而影响响应速度,导致领域对象初始化速度慢。 所以尽可能将这种依赖通过方法懒加载的方式暴露。

抛弃部分CQRS,走领域模型做查询

      我们有些习惯在查询场景下绕过领域层,直接select多条记录,存储为DO返回给Client端。但是这会导致越来越多的冗余逻辑存在,破坏代码结构,影响领域层的沉淀。所以不管出于何种考虑,既然选择了DDD,应该尽量去遵守其约定,走领域模型做查询。

相关文章
|
微服务 测试技术 Java
阿里技术专家详解 DDD 系列- Domain Primitive
关于DDD的一系列文章,希望能继续在总结前人的基础上发扬光大DDD的思想,但是通过一套我认为合理的代码结构、框架和约束,来降低DDD的实践门槛,提升代码质量、可测试性、安全性、健壮性。
63063 17
阿里技术专家详解 DDD 系列- Domain Primitive
|
机器学习/深度学习 计算机视觉 知识图谱
YOLOv11改进策略【注意力机制篇】| SENet V2 优化SE注意力机制,聚合通道和全局信息
YOLOv11改进策略【注意力机制篇】| SENet V2 优化SE注意力机制,聚合通道和全局信息
561 1
YOLOv11改进策略【注意力机制篇】| SENet V2 优化SE注意力机制,聚合通道和全局信息
|
算法 决策智能
基于GA-PSO遗传粒子群混合优化算法的TSP问题求解matlab仿真
本文介绍了基于GA-PSO遗传粒子群混合优化算法解决旅行商问题(TSP)的方法。TSP旨在寻找访问一系列城市并返回起点的最短路径,属于NP难问题。文中详细阐述了遗传算法(GA)和粒子群优化算法(PSO)的基本原理及其在TSP中的应用,展示了如何通过编码、选择、交叉、变异及速度和位置更新等操作优化路径。算法在MATLAB2022a上实现,实验结果表明该方法能有效提高求解效率和解的质量。
|
前端开发 架构师 Java
领域驱动设计DDD从入门到代码实践
在本文中,作者将借鉴《实现领域驱动设计》的做法,介绍领域驱动设计的基本概念的同时,用一个虚拟的公司和一个虚拟的项目,把领域驱动设计进行落地实践。
15783 11
领域驱动设计DDD从入门到代码实践
|
安全 Java 数据库连接
Spring Boot 优雅关机时异步线程安全优化
Spring Boot 优雅关机时异步线程安全优化
683 1
|
消息中间件 存储 Java
RocketMQ技术详解:从基础知识到内部设计原理
RocketMQ技术详解:从基础知识到内部设计原理
640 2
|
存储 分布式计算 监控
Spark中广播变量
【8月更文挑战第13天】
715 0
|
移动开发 JavaScript 小程序
uView Radio 单选框
uView Radio 单选框
521 0
|
机器学习/深度学习 人工智能 运维
构建高效自动化运维系统:DevOps与AI的融合
【5月更文挑战第19天】 在数字化转型的浪潮中,企业IT运维面临着日益复杂的挑战。传统的手动运维方式已经无法满足快速迭代和高可靠性的需求。本文探讨了如何通过结合DevOps理念和人工智能(AI)技术,构建一个高效的自动化运维系统。文章首先回顾了DevOps的核心原则及其在自动化运维中的应用,接着分析了AI如何增强故障预测、智能决策和自动化流程的能力。最后,提出了一个综合DevOps与AI技术的自动化运维框架,并讨论了其在实际部署中的优势和潜在挑战。
uiu
|
存储 分布式计算 网络协议
带你快速进阶:HDFS架构与操作
带你快速进阶:HDFS架构与操作
uiu
938 0
带你快速进阶:HDFS架构与操作