初识领域驱动设计(DDD)

重回研发后,常听同事提DDD(领域驱动设计),颇感好奇,似乎是一种软件架构设计的新范式,遂决定花时间学习了解一下。

常规学习三板斧:DDD是什么?DDD解决什么问题?DDD如何使用?

1、DDD是什么?

DDD是有关软件设计的一套思想和经验原则总结,是指导软件研发人员进行大型系统的架构设计时候的一套方法论体系。由Eric Evans 编著的《领域驱动设计》提出,原稿首版是2003年,随着分布式系统,微服务流行又重新变得火热。

DDD里面的核心概念是:领域、限界上下文、上下文映射、通用语言、实体、值对象、聚合与聚合根、领域服务、领域事件、分层架构和应用服务。

领域即一个组织所做的事情以及其中所包含的一切,每个组织都有其业务范围和做事方式,这个业务范围以及在其中进行的活动就是领域。领域界定了一个软件系统服务的对象和解决问题的范围。领域内部又区分通用领域、支撑领域和核心领域,核心领域是一个软件系统最关心和最重要的部分。领域的划分和精确定义离不开领域专家的指导。

限界上下文是一个显式边界,领域模型便存在于边界之内。即限界上下文是限定领域内不同领域模型生命周期的一个边界,有个很好的隐喻是:细胞质所以能够存在,是因为细胞膜限定了什么在细胞内,什么在细胞外,并且确定了什么物质可以通过细胞膜在边界内。限界上线文类似这个细胞膜的作用。

有了限界上下文,就更好理解通用语言的概念,通用语言即在一个限界上下文内所有的术语和词组都有特定的含义,跨越了上线文或者甚至跨越了领域,同一个名词语义就不同,通用语言对于产品和研发在讨论问题,或者不同组织之间讨论需求时候非常关键。有了通用语言可以减少吵架的概率。和领域类似,通用语言的定义和共识也需要领域专家的参与。

有了限界上下文,就有上下文之间的映射关系,映射关系比较多,常用的是开放主机服务和防腐层,RPC和REST都属于开放主机服务使用的服务协议,一般微服务的各系统之间关系就是典型的开放主机服务。

一般领域模型会主要包含领域对象、领域服务和领域事件,领域对象主要是实体和值对象。

实体就是具有唯一身份标识的对象,只要两个实体的身份标识一样,不管其他属性如何,就是同一个实体,同一个实体的状态随着时间会有持续的变化。

相应的值对象就没有唯一身份标识,主要用来度量或者描述领域中的一件东西,可以直接和其他值对象进行比较,当度量和描述改变时,就用另一个值对象替换。

聚合是一组业务和逻辑紧密关联的实体和值对象集合,是数据修改和持久化的基本单元;聚合内实现事务一致性,聚合外使用最终一致性。一般聚合里面有一个聚合根实体,对外暴露的概念也是这个聚合根实体。

DDD坚持面向对象的理念,核心业务逻辑一般是实体或值对象的内部函数。对于跨越多个实体和值对象才能实现的业务逻辑,即操作不属于某个实体或者值对象的职责时,往往通过一个单独的接口来实现,这个单独的接口就是领域服务。领域服务可以以多个领域对象作为输入进行计算,并产生一个值对象。

领域事件是用来通知其他领域对象或者服务完成上下游事务逻辑发出的消息,通过领域事件可以实现分布式事务,最终一致性和一些操作结果的通知。

分层架构讲求不同的业务编排放在不同的层,在一个工程的包目录中有最明显的体现,有利于工程的易读、易修改和易维护。严格的分层要求某层只能与直接位于其下方的层发生耦合,松散的分层允许任意上方层与任意下方层发生耦合。

应用服务层是系统对外的门户服务,一般不处理业务逻辑,是领域模型的直接客户,非常轻量,用于协调领域对象的操作。

2、DDD解决什么问题?

所有的软件架构与设计方法论都为了让研发的软件更加稳健、易扩展和易维护,DDD也不例外。当然DDD有其特别擅长的方面:

1)抽象业务需求,反应领域专家的思维模型,让软件更符合业务战略并产生业务价值。

在让领域专家介入软件设计这方面,DDD通过引入领域、领域模型、通用语言等概念,显式和精确的把领域专家的知识经验落地到软件系统的模块和组件中,会尽量屏蔽纯技术语言的局限性,更通畅并高效的表达软件的业务价值,减少软件上线后的功能跑偏。

2)统一语言和概念,更适合研发与需求方展开沟通合作

和第一条类似,领域模型和通用语言本身是没有技术偏向的,特别方便业务专家、产品经理和技术研发对同一个问题的沟通合作,减少不同角色认知差异造成的沟通障碍,让大家容易对同一需求达成共识,减少理解分歧和争吵的发生。

3)对复杂场景的业务效果更为明显

设计大型软件系统时候,业务场景、业务流程、用户角色、非功能性约束呈网状网交织状态,越是会凸显DDD进行软件设计的有效性;想想能把前两条搞定的方法论,研发人员会能省出更多时间在生产力coding上,本身就是一种高效。

3、DDD如何使用?

DDD的实践,从宏观到微观角度可分粗为战略设计和战术设计两个阶段。

战略设计是团队领导层或业务负责人关心的,该步骤需要针对产品愿景、业务要解决的问题域,规划核心域、通用域、支撑域做合适的资源投入。战略设计主要会定义领域,限界上下文和上下文映射。

战术设计是要设计限界上下文内的领域实体、值对象、聚合和聚合根、领域事件、领域服务,应用服务、以及创建实体的工厂方法,存储领域对象的资源库等细节方面。建议设计优先级是先值对象 → 再实体 → 再聚合 → 再领域服务→ 最后是应用服务,优先考虑领域是否应该为值对象,其次是否为实体,划分出聚合。不属于实体或值对象中的领域行为放到领域服务,需要协调聚合的领域行为设计为领域服务或者应用服务。

一般的步骤流程:

1)根据需求划分出初步的领域和限界上下文,以及上下文之间的关系;

2)进一步分析每个上下文内部,识别出哪些是实体,哪些是值对象;

3)对实体、值对象进行关联和聚合,划分出聚合的范畴和聚合根;

4)为聚合根设计仓储,并思考实体或值对象的创建方式;

5)通过分层架构实现编码,在工程中实践领域模型,并在实践中检验模型的合理性,倒推模型中不足的地方并重构。

4、DDD与微服务的关系?

一般这里是指DDD中的限界上下文与微服务之间的关系。

微服务是包含高度相关功能的一个开发部署单元,有自己的技术自治性,包括技术选型、弹性扩缩容、发布线上频率等;限界上下文(Bound Context)是根据领域逻辑的内聚情况形成的一个整体。

一个微服务可以包含一个或者多个限界上下文,根据团队大小、限界上下文复杂度和技术特性决定。

5、DDD落地面临的挑战?

1)缺乏领域专家指导

现实中领域专家是稀缺资源,尤其是创新型的业务领域。

2)代码实现层面缺少真正运行的最佳实践工程

大多数DDD代码演示都是一些demo样例,不是真实在跑的生产系统;尤其到了使用具体研发框架(例如SpringBoot),Service一般都是Spring创建的单例对象,这里面实现富血模型的多例对象,嵌在里面有时候不伦不类的;DDD倡导的用实体的save方法来实现对属性的update,也会出现很多误用场景。所以很多DDD工程都是看着目录结构像DDD指导设计的,而本质代码内容和没用DDD的工程相差不多。所以当前实际中用DDD来指导战略和战术设计会更加实用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值