DDD建模系列(四)

简介: DDD建模系列(四)

一、管理面问题:传统scrum敏捷流程中的问题

设计和编码断层

在传统的迭代流程存在设计和编码断层,大致如下:

1、先看设计和编码断层

①、大部分的开发过程,弱化设计环节,简化设计环节,先把库表,接口定义个大概/七七八八,写个简单的设计文档就开始开发。

②、如果比较急,或者自认为对需求很熟悉,会省略这个已经简单到不能再简单,少到不能再少的设计流程,对着原型开始编码,开始建表,然后定义好API接口,就开始编码了。

上面的流程是轻量级的迭代流程。

敏捷迭代:周期快,你和开发经理去讨论他为什么不做好设计,他会说,不要把流程搞的那么重嘛!开发经理的意思,进度要紧,先把时间放在重要的事情上面。

开发经理的目标:编码搞定,改改上线,就是最重要的,什么软件生命质量,软件生命值,先靠边站着,回头再说。

这样导致的问题是:

①、初级开发并没有理解需求,其实并没有搞清楚需求,一周之后看成果,发现走弯路,或者白干了。另外,中高级甚至架构师,其实也有看走眼的时候。由于设计不充分,往往写到一半,会冒出一个一个的隐形字段,隐形流程,隐形接口,都是由于之前没有分析清楚,写着写着,都冒出来了。

②、数据驱动开发,从库表,到接口定义到开发代码,一气呵成,速度快,但是忘记做变和不变的隔离,造成了变和不变的紧密耦合,埋下无数地雷。

现在大家都是敏捷迭代,极速迭代,快速试错,流程不能太重。

所以,开发经理的理由也是非常充分的:后面的事情后面再说,先实现功能。

在看业务和开发隔离

业务干完PRD,人家就准备看下一个版本的需求,并等着验收这一个版本的产品。

开发这个时候在蒙头干活,吭哧吭哧写代码。

同一个词,同一个功能,如果理解有偏差,大家各自留心底,互不感知。

只有等到验收的时候,业务说,我说的流程不是这样的,你其实没有理解需求。当然,开发也不是傻子,不会坐以待毙,然后开始各种甩锅,各种扯皮。

根本的原因:业务和开发隔离。

如何强化设计与编码的依赖,拉通业务与开发的断层。

其实,DDD绝对是拯救传统开发流程的神药:它拉通业务与开发的隔离,强化设计与编码的依赖关系。

30f592539d58d78147fc3f79ec4e9b2f.png

拉通业务与开发的隔离的办法:引入领域专家,使用通用语言进行领域驱动建模。

什么是通用语言?

比如电商系统项目组的成员在一起讨论问题:

①、程序员A:我们购买商家的产品

②、程序员B:用户买商品

③、产品经理:我们采购店家商品

④、测试人员:用户购买物品

......................

以上大家其实要表达的意思都是一样的,但是不统一。

所以,通用语言最终结果,就是需求沟通没有歧义,同一个词,有大家都明确了定义。

在事件风暴过程中,通过团队交流达成共识的,能够简单,清晰,准确描述业务涵义和规则的语言就是通用语言。也就是说,通用语言是团队统一的语言,不管你在团队中承担什么角色,在同一个领域的软件生命周期里都使用统一的语言进行交流。

通用语言包含术语和用例场景,并且能够直接反映在代码中

通用语言的名词可以给领域对象命名,如商品,订单等,对应实体对象;而动词则表示一个动作或者事件,如商品已下单,订单已付款等,对应领域事件或者命令。

通用语言贯穿DDD的整个设计过程,作为项目团队沟通和协商形成的统一语言,基于它,你就能够开发出可读性更好的代码,将业务需求准确转化为代码设计。

DDD领域驱动的关键点和流程特点

领域驱动指的是以领域作为解决问题切入点,面对业务需求,先提炼出领域概念,并构建领域模型来表达业务问题,而构建过程中我们应该尽可能避免牵扯技术方案或者技术细节。

而编码实现更像是对领域模型的代码翻译,代码(变量名,方法名,类名)中要求能够表达领域概念,让人见码明义。

ff4bf740680532e820706f8dd7a830f6.png

特点之一:思维模式改变

实践DDD以前,最常使用的是数据库驱动设计

它的核心思路针对业务需求进行数据建模:根据业务需求提炼出类,然后通过ORM把类映射为表结构,并根据读写性能要求使用范式优化表与表之间的关联关系。

数据驱动是从技术的维度解决业务问题,得出的数据模型是对业务需求的直接翻译,并没有蕴含稳定的领域知识/规则

一旦需求发生变化,数据模型就得发生了变化,对应的库表的设计也需要进行调整。

这种设计思维导致变化从需求穿透到了数据层,中间并没有稳定的,不易变的层级进行阻隔,最终导致系统响应变化的能力很差。

特点之二:协同方式转变

数据驱动设计模式下,产品提需求,研发设计方案,并编码实现

这种协同式的弊端在于:无法形成能够消除认知差异的模型

产品同学从业务角度提出需求,这些需求可能是易变的,定制化的。

而研发同学在缺少行业经验的情况下,往往会选择直译,即根据需求直接转换为数据模型。

而研发同学从技术实现角度设计技术方案,其中涉及很多的技术细节,产品同学无法从中判断是否与自己提出的业务诉求和产品规划相一致,最终形成认知差异。且认知差异会随着迭代不断被放大,最后系统形成一个大泥球。

e6fd8e8aad0ef9b3f74928bd937966a0.png

DDD通过解锁新角色"领域专家“,以及模型驱动设计,有效地降低产品和研发的认知差异。

领域专家是具有丰富行业经验和领域知识储备的人,他们能够在易变的,定制化的需求中提炼出清晰的边界,稳定的,可复用的领域概念和业务规则,并携手产品和研发共同构建出领域模型。

设计的根本思想:分离变和不变。

保证领域模型的稳定性,提升代码的生命值。

领域模型是对业务需求的知识表达形式,它不涉及具体的技术细节(但能够指导研发同学进行编码实现),因此消除了产品和研发在需求认知上的鸿沟。

而模型驱动设计则要求领域模型能够关联业务需求和编码实现,模型的变更意味着需求变更和代码变更,协作围绕模型中心。

b050fae78d6f5795d5f21e85e94753c7.png

特点之三:精炼循环

精炼循环指的是在统一语言,提炼领域概念,明确边界,构建模型,绑定实现过程中,这些环节相互影响,相互反馈,在不断的迭代试错,不断反馈,不断调整,最终沉淀出稳定的,深层次的模型的过程。

比如:我们在提炼领域概念的时候会觉得统一语言定义不合理/有歧义,此时我们就会调整统一语言的定义,并重新进行提炼领域模型。

通过精炼循环,我们逐步形成稳定的领域模型,设计的根本思想:分离变和不变。

①、识别出稳定的领域模型

②、分离出不稳定的领域模型

保证领域模型的稳定性,提升代码的生命值。

在DDD中,让领域专家来主导概念提炼,边界划分等宏观设计,原因就在于领域专家的经验和行业洞见来源于过去已经迭代的无数个精炼循环,因此由这些宏观设计推导出来的领域模型,往往都是非常稳定的。

精炼循环的核心是循环,它避免知识只朝单一方向流动,最终因各环节上的认知差异,最终导致模型无法在产品,领域专家和研发中达成一致,模型与实现割裂。

相关文章
|
存储 自然语言处理 前端开发
领域驱动设计(DDD)-基础思想
一、序言     领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。在领域驱动设计理念上,各路大侠的观点也是各有不同,能力有限、欢迎留言讨论。 二、领域驱动设计 DDD是什么 wiki释义:     领域驱动设计(英语:Domain-driven design,缩写 DDD)是一种通过将实现连接到持续进化的模型[1]来满足复杂
7495 0
|
2天前
|
敏捷开发 架构师
DDD建模系列(三)
DDD建模系列(三)
|
2天前
|
设计模式 前端开发 Java
DDD建模系列(五)
DDD建模系列(五)
|
2天前
|
存储 前端开发 中间件
DDD建模系列(二)
DDD建模系列(二)
|
2天前
|
架构师
DDD建模系列(一)
DDD建模系列(一)
|
设计模式 供应链 领域建模
DDD模型初探
DDD模型初探
111 0
|
消息中间件 JavaScript 小程序
领域驱动设计(DDD)的几种典型架构介绍
领域驱动设计(DDD)的几种典型架构介绍
|
人机交互
领域驱动设计总结——如何运用模型
本文为领域驱动设计系列总结的第二篇,主要对领域驱动设计概念做个介绍,本系列领域驱动设计总结主要是在Eric Evans 所编写的《领域驱动设计》 一书的基础上进行归纳和总结。本文主要介绍在领域驱动设计中如何运用模型
113 0
|
存储 消息中间件 JSON
领域驱动设计:从理论到实践,一文带你掌握DDD!
学习DDD一个半月,最开始学习DDD的原因是因为我负责的业务线,涉及的系统非常多,想借鉴领域驱动设计的思想,看后续如何对系统进行重构。在没有学习DDD之前,感觉DDD可能属于那种“虚头巴脑”的东西,学完DDD之后,感觉。。。嗯。。。真香!
1658 0
领域驱动设计:从理论到实践,一文带你掌握DDD!
|
设计模式 缓存 Java
DDD分层
为什么分层 引用《领域驱动设计模式、原理与实践》 为了避免将代码库变成大泥球(BBoM)并因此减弱领域模型的完整性且最终减弱可用性,系统架构要支持技术复杂性与领域复杂性的分离。引起技术实现发生变化的原因与引起领域逻辑发生变化的原因显然不同,这就导致基础设施和领域逻辑问题会以不同速率发生变化 每一层都有各自的职责,显然这也是符合SRP的
541 0
DDD分层