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

简介: 近年来领域驱动设计(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,应该尽量去遵守其约定,走领域模型做查询。

相关文章
|
1月前
|
领域建模
架构设计 DDD领域建模 核心概念
【1月更文挑战第6天】架构设计 DDD领域建模 核心概念
|
前端开发 Java 数据库连接
领域驱动设计:从学习到实践(一)
产品同学将需求分析完和开发同学进行需求评审,评审完毕后开发同学开始基于需求进行设计,一般会落到数据库设计,将库表设计完毕后,再向上进行分层开发。如果是前后端分离的项目,会在前期约定接口,进行基于契约的并行开发。所以,我们称这种方式为数据驱动开发,或基于数据模型的开发。
领域驱动设计:从学习到实践(一)
|
Cloud Native 架构师 Devops
云原生时代领域驱动设计(DDD)的价值——从《没有银弹》说起
软件开发需要面对本质困难和附属困难。云原生、DevOps实践大幅降低了附属困难,使得架构师可以全力聚焦于业务复杂性,而DDD恰是管理业务复杂性的有效方法。
1540 0
云原生时代领域驱动设计(DDD)的价值——从《没有银弹》说起
|
领域建模 微服务
领域驱动设计总结——落地与思考
本文为领域驱动设计系列总结的第六篇,主要对领域驱动设计概念做个介绍,本系列领域驱动设计总结主要是在Eric Evans 所编写的《领域驱动设计》 一书的基础上进行归纳和总结。 本文也是领域驱动设计总结系列最后一篇,主要是简单的探讨下,领域驱动设计的落地方式,以及对这整个系列做一个总结。
311 0
|
设计模式 程序员 项目管理
领域驱动设计揭秘
领域驱动设计揭秘
|
存储 消息中间件 JSON
领域驱动设计:从理论到实践,一文带你掌握DDD!
学习DDD一个半月,最开始学习DDD的原因是因为我负责的业务线,涉及的系统非常多,想借鉴领域驱动设计的思想,看后续如何对系统进行重构。在没有学习DDD之前,感觉DDD可能属于那种“虚头巴脑”的东西,学完DDD之后,感觉。。。嗯。。。真香!
1403 0
领域驱动设计:从理论到实践,一文带你掌握DDD!
|
敏捷开发 监控 架构师
DDD 领域驱动设计落地实践系列:微服务拆分之道
在前面的两篇文章中,笔者给大家介绍了 DDD 核心思想、重要概念以及如何进行 DDD 进行微服务实践的大致过程,后续的文章中将逐渐深入 DDD 的实践细节,包括领域模型与代码模型的映射以及具体的微服务设计实例等。当下微服务盛行,微服务架构解决了单点系统的可用性问题、突破单节点服务的性能瓶颈同时提升了整个系统的稳定性。因此各大公司纷纷转向微服务架构,但是在实际的微服务拆分过程中也会遇到不少的问题。而 DDD 中的领域模型构建以及边界上下文的划分天然的和微服务划分有着异曲同工之妙,因此结合 DD 领域驱动设计来进行微服务拆分是一种比较好的微服务拆分方案。那么今天就和大家聊聊怎么进行微服务拆分。
DDD 领域驱动设计落地实践系列:微服务拆分之道
|
消息中间件 设计模式 弹性计算
聊一聊中台和DDD(领域驱动设计)
本次分享价值:本次分享主要针对中台、微服务和领域模型的理念、本质及其构建方法论进行探讨。对领域分析的价值所在就是寻求“千变万化”中相对的“稳定性、第一性”,然后通过合理的架构分析及抽象隔离业务的复杂度和技术复杂度,隔离业务领域的稳定性和易变性,从架构上精巧、快速的支撑业务的变化。
11609 0
|
存储 消息中间件 设计模式
领域驱动设计(DDD)实践之路(二):事件驱动与CQRS
这是“领域驱动设计实践之路”系列的第二篇文章,分析了如何应用事件来分离软件核心复杂度。探究CQRS为什么广泛应用于DDD项目中,以及如何落地实现CQRS框架。当然我们也要警惕一些失败的教训,利弊分析以后再去抉择正确的应对之道。
1359 0