• DDD领域驱动设计:业务分析神奇


    1. DDD设计篇:运用事件风暴法进行业务领域建模、统一语言建模

    image-20211006215713551

    1.1 如何成为优秀架构师?

    架构师 = 技术大牛?

    架构师不仅需要懂技术,还要懂业务。

    只有将业务落地到技术,开发出对用户有价值的产品,技术才是有价值的。

    什么是业务架构师?

    掌握了业务领域知识,掌握了业务痛点,然后用技术方案,解决业务痛点,才能为公司创造价值。

    架构师

    • 要能够将业务转换为技术

    • 能合理运用技术支撑业务

    客户买单,不是买技术,而是买你用技术解决我业务痛点的技术方案。

    所以上面一步步分析后,业务痛点是关键

    1.2.1 对业务及其痛点,有深刻的理解与思考

    不仅要理解业务,还要挖掘出业务痛点,才才可以用对应的技术来解决问题

    • 分析业务流程

    • 理解业务规则

    • 挖掘业务痛点

    1.2.2 能够将技术落地,产生业务价值

    • 规划高远却落不了地
    • 快速研发产生业务价值

    关键难题:

    • 如何快速有效地学习业务领域知识
    • 如何深入地理解与挖掘业务痛点
    • 如何通过技术的手段落地业务

    image-20211006193444872

    系统没那么复杂时,需要领域驱动吗?

    系统不复杂时,领域驱动有点大材小用,以前互联网时代没到来,没有发生数据和需求井喷,业务也不复杂,所以不会流行起来。

    现在基本都需要,特别是互联网业务。

    1.2 领域驱动设计在什么时候起作用?

    1.2.1 在新项目开发中起作用?

    image-20211006193826980

    1. 深刻理解业务,进行领域建模

    2. 然后把业务转换为领域模型,

    3. 再用领域模型指导数据库设计和程序设计

    4. 按照贫血模型或者充血模型转换为程序设计

    这个时候,一开始需要花大量时间进行领域建模。

    但是新项目有一些特点

    1、复杂度没那么高

    2、要快速交付

    怎么办?一开始没办法,用领域驱动,是考虑长远,在日后,项目需求变更、维护。

    1.2.2 在老项目维护中起作用?

    image-20211006194413194

    image-20211006194424835

    面对老项目越来越复杂时,领域驱动会更好的发挥作用

    image-20211006194714773

    快速交付?

    通过领域驱动设计,提高维护的质量,使得可以在业务不断迭代、市场激烈竞争、技术快速更新、系统越来越庞大时,依然能快速交付高质量的产品。

    我们采用整洁架构,将业务代码和技术框架,通过一个中间层进行解耦。

    今后,我们的业务代码随着业务不断迭代,技术框架也可以不断迭代调整,互不影响。

    1.2.3 在技术架构演化中起作用?

    1.3 领域驱动的解决之道

    image-20211006195220682

    首先,业务负责人(或产品经理),以故事的形式,将功能分发给多个敏捷团队,每个敏捷团队负责一个功能模块。

    每个敏捷团队,在开发的过程中,结合领域驱动设计和微服务架构理念,设计功能。

    我们按照业务去拆

    微服务如何拆分?

    接口怎么划定?

    怎么将每次的需求只落到一个微服务里?

    让每个微服务,都是软件变化的一个原因,

    今后因为这个原因而发生的变更,都只发生在这个微服务。微服务的优势才真正发挥出来了。

    每次需求变更时,基于领域驱动设计,进行业务建模,

    最后把对业务建模的变更,落实到对微服务的变更

    我们的系统才能高质量的低成本维护下去。

    在我们结合领域驱动设计和微服务架构理念去做设计时,都是有一定的成本的,从而提高了系统设计的复杂度。

    复杂度的增加,进一步降低了交付速度。又和我们的初衷产生矛盾。

    我们的初衷,通过领域驱动设计和微服务,简化设计,降低维护成本,提高交付速度

    而使用它们的成本,又会降低交付速度

    这个矛盾怎么解决?

    架构团队,架构一个支持微服务,支持领域驱动的架构,把我们在领域驱动中的一些复杂的设计,比如聚合、仓库、工厂下沉,落地到技术框架里,

    一边基于业务领域模型,建立业务领域层,

    一边将各个技术框架,通过适配器进行解耦。

    这就是整洁架构。

    image-20211006201106413

    1.3.1 为什么需要领域驱动设计指导微服务的划分?

    首先看下,传统的烟囱式的数据库设计

    image-20211006195535129

    这样的数据库设计,使用的时候,比如获取商品信息这个数据的时候,各个微服务都要去读取商品表,

    一旦商品表发生变更,各个模块都要变更代码。

    这样维护成本非常高。

    怎么办?

    那我们希望某一次变更,只需要改某个微服务的代码,缩小需求变更的影响范围

    1.3.2小而专的微服务设计

    小:拆分微服务

    专:单一职责原则(容易被忽略)

    怎么做?

    要求每个表只能有一个微服务直接操作数据库,其他微服务想要操作是不行的,只能调用对应微服务的接口。

    这样设计后,商品表变更,只会影响到商品维护这个微服务。

    只要对外接口不变,其他微服务也不需要改代码,影响很小

    image-20211006200056410

    对数据表进行规划,哪个微服务操作哪些表。

    提高内聚,从业务角度分析整理,划分清楚边界。

    业界现在最有效的做这个事情的方法,就是领域驱动设计,

    通过对业务的梳理,逐步建立起限界上下文。

    然后基于限界上下文设计和开发系统

    1.3.3 跨库关联查询解决方案

    image-20211006202338414

    方案:按照领域模型建模,建立好关联关系,底层架构自动帮我补填数据。

    比如我下单,我只关心查订单数据,我建立领域模型时,建立了订单和其他模块的业务关系,配置好业务关系,底层架构自动帮我补填数据。

    1.4 本课程要解决的问题

    领域驱动设计的作用与意义

    真正的目的不在于开发新项目,新项目没有那么复杂,而在于,日后的维护,系统越来越复杂时,体现出来。

    一开始用领域驱动的意义,在于,日后的维护,系统复杂的时候,提高代码质量,降低交付时间。

    怎样正确地进行业务领域建模

    今天的内容

    事件风暴

    image-20211006203725526

    image-20211006203738605

    image-20211006203906407

    image-20211006203928922

    image-20211006203953635

    需求变更

    image-20211006204039799

    image-20211006204124648

    为什么越来越复杂?

    这是软件发展的必然规律

    image-20211006204204655

    image-20211006204232919

    传统的设计方式,随着新需求的到来,不断地往payoff()方法里塞代码。

    这样会导致代码质量不断下降,维护成本不断提高。

    软件退化的根源,不是需求变更

    当我们需求变更的时候,我们适时地调整代码。进行解耦和功能扩展,再去实现需求,就能够实现高质量代码

    image-20211006204552356

    那么我们怎样适时调整代码,解耦和扩展呢?

    当发生10次、50次、100次变更后,可能就迷失方向了

    我们需要一个方法,无论多少次变更,都能够产生高质量代码

    当我们需求变更时,把变更还原到真实世界里,真实世界是什么样子,我们软件就怎么变更。

    这样,无论发生多少次变更,我们也能找到方向。

    image-20211006204846712

    在领域模型里变更,思考设计

    image-20211006205024005

    面对变更,传统设计方式如下图,直接塞代码。

    image-20211006205055562

    而领域驱动的设计方式,我们先将新需求,还原到领域模型上,进行分析

    image-20211006205239226

    image-20211006205252884

    我们要增加折扣,而且有多种不同方式的折扣。

    我们需要思考,付款和折扣有什么关系?

    折扣的功能,怎么添加到现有功能里?

    传统思考方式:折扣是在付款的时候折扣,就写在付款的逻辑里

    那么难道不写在付款里?为什么不该写在付款里?是基于什么原则去思考的吗?

    有,单一职责原则

    image-20211006210027762

    image-20211006210129424

    image-20211006210145290

    image-20211006210218981

    抽象出限界上下文,每个限界上下文就是一个微服务

    每个微服务是软件变化的一个原因,有需求变更,只需要改某个微服务

    怎样将模型转换为程序设计

    明天分享

    支持领域驱动设计的架构设计

    第三天的分享内容

    1.5 单一职责原则(SRP)

    软件系统中的每个元素只完成自己职责内的事,将其他的事交给别人去做。

    “职责”通常理解为一个事情,与该事情相关的事都是它的职责。

    一个所谓职责,其实是软件变化的一个原因。

    软件质量如何衡量?高还是低?

    关键:维护成本

    一个需求来了,我要改3个模块的代码

    一个需求来了,我要改1个模块的代码

    要求我们

    平时,就要整理代码。

    把同一个原因的代码放一起。

    不同原因的代码分开放

    image-20211006205845163

    现在要增加折扣,问自己两个问题:

    付款变了,要不要变折扣?不要

    折扣发生变更,付款要不要变?要

    折扣是付款的另一个变化原因,不应该把折扣放进付款里

    1.6 领域驱动设计与传统软件开发有什么不同?

    项目不变更,不需要添加新功能,不会越来越复杂,就不需要使用DDD

    新项目里用领域驱动设计,是为了日后需求变更,维护起来更容易。

    按照领域驱动设计,每次变更的时候,不是直接coding,而是把新需求,先放到领域模型里,在领域模型里设计,还原到真实世界。

    领域驱动设计更适合老项目

    是不是增加了工作量呢?

    需要有一个支持领域驱动的底层架构

    如何设计这样一个底层架构?

    在第三天的课里

    1.7 案例:远程智慧医疗系统

    对前面的思想进行实战

    image-20211006210951136

    1.7.1 期初:传统的诊所管理系统

    image-20211006211029507

    护士接待患者,指引患者挂号,

    然后由医生去看

    医生建议患者去检查,做B超、验血

    患者去交钱,验血

    医生看报告,开药

    患者交钱去药房拿药

    1.7.2 统一语言与领域建模

    image-20211006212048308

    用客户的语言,理解业务

    1.7.3 事件风暴

    image-20211006212510847

    image-20211006212558102

    迭代会议之前,开一个事件风暴会议

    image-20211006212811086

    image-20211006212938651

    已确诊和已开药是否是同一个事件?

    image-20211006213010632

    查找医生算不算一个事件?

    只是个查询,不需要记录,预约了才要记录

    领域事件分析全了么?还有已排班,已注册

    image-20211006213213808

    分析和事件相关联人和事

    image-20211006213349061

    预约是一个命令

    触发者 是患者

    相关的还有预约时间

    出诊计划,哪个医生、哪个科室,什么时间出诊

    梳理人和事的关系,

    人和事是不是聚合

    image-20211006213556589

    image-20211006213612230

    药品明细和处方是一个部分和整体的关系,有聚合关系,贴一个紫色便签

    是不是聚合关系?

    如果是聚合关系,部分的生命周期一定是在整体里

    比如,处方产生了,才有药品明细,当处方删除,药品明细才会删除

    1.7.4 领域建模

    image-20211006214033246

    image-20211006214313502

    image-20211006214215846

    image-20211006214413014

    2 DDD实践篇:通过领域模型落地系统设计:数据库、聚合、工厂与仓库

    image-20211006220303418

    2.1 将领域模型转为数据库设计

    表、表之间的关系

    2.2 将领域模型转为程序设计

    image-20211006220527857

    实体、值对象(不要太纠结)

    实体:每个同学,有一个编号学号,

    值对象:同学、老师

    image-20211006220756643

    贫血模型的设计

    image-20211006221030021

    充血模型的设计

    image-20211006221117782

    充血模型的service,把订单作为一个整体,订单对象里有依赖的其他对象的,定义了他们的关系。订单service不需要处理订单和订单明细的依赖关系。

    订单service只需要保存订单,也不需要关心保存到两个表

    image-20211006221417059

    订单和订单明细是聚合关系,订单仓库来做保存到具体的表的事情。

    查询的时候,订单工厂,会补查用户、用户地址等信息

    好处:

    service不需要关注底层,只需要关注业务逻辑判断

    是不是要为每个领域对象设计一个仓库和工厂?

    框架

    2.3 聚合

    image-20211006222050553

    对象和对象之间有整体和不分关系的时候,只操作整体

    订单和订单明细是整体与部分的关系。聚合关系

    查询和保存操作都是对订单,订单明细的查询和保存操作在订单里完成

    订单就是聚合根

    2.4 工厂(Factory)/仓库(Repository)

    image-20211006222527714

    2.5 领域驱动设计的分层架构

    image-20211006222620189

    dao变成了仓库,做了更具体的事情

    2.6 互联网转型:远程接诊平台

    image-20211006222804928

    2.7 互联网转型带来的阵痛

    image-20211006222846608

    2.8 系统规划与架构设计

    image-20211006223009698

    互联网转型后的领域建模设计

    image-20211006223053780

    image-20211006223316190

    image-20211006223443525

    image-20211006223636714

    image-20211006223831853

    image-20211006223847585

    image-20211006224114736

    image-20211006224957236

    CQRS命令查询指责分离

    image-20211006225216710

    image-20211006225420095

    image-20211006225500612

    image-20211006225808784

    2.9 四色建模法

    image-20211006225922971

    image-20211006230043182

    image-20211006230218464

    image-20211006230338555

    image-20211006230442460

    image-20211006232007375

    image-20211006232037931

    通过适配器,解耦业务代码和技术架构

    image-20211006234343393

    image-20211006234704540

    image-20211006234814257

    image-20211006234839997

    image-20211006234925225

    image-20211006235207792

    image-20211006235254381

    image-20211006235423299

    image-20211006235458621

    image-20211006235701389

    image-20211006235740810

    image-20211007000014674

    image-20211007000038638

    image-20211007000054822

    image-20211007000203707

    image-20211007000237235

    image-20211007000247415

    image-20211007003812957

    image-20211007005122362

    image-20211007005237941

    image-20211007005416460

    image-20211007005508960

    image-20211007005718782

    image-20211007010113105

    image-20211007010249353

    总结

    • 领域驱动设计适合大型复杂项目,不适合初始项目

    • 领域驱动设计适合频繁需求变更的项目

    • 通过领域建模,划分限界上下文,根据限界上下文拆分微服务

    • 有新需求或者需求变更,先将需求放在领域模型内讨论设计,再将领域模型转为数据库设计和程序设计

    • 领域驱动设计时,可以采取事件风暴会议形式,和领域专家一起,使用统一语言讨论,一起设计领域对象和关系

    • 事件风暴会议需要确定一些事情:分析有哪些领域事件、确定有哪些和领域事件相关的人和事、确定触发事件的命令、确定领域事件关联的人和事有没有聚合关系

    • 将领域模型分配到各个限界上下文中,构建上下文地图

    • 新需求的代码写在哪个模块里,采用单一职责原则作为指导

    • 单一职责中的职责是指引起软件变化的一个原因

    • 平时,就要整理代码,把同一个原因的代码放一起,不同原因的代码分开放

    • 软件退化的根源不是需求变更,而是在需求变更时,没有及时调整代码,没有正确的调整代码

    • 贫血模型设计的代码,领域对象只有状态,service层包含各种行为,service层很重

    • 充血模型设计的代码,更符合面向对象,领域对象不仅封装了状态,还有各种修改状态的行为,service层更轻,service层只处理业务逻辑的封装、事务、权限

    作者: 元宝爸爸

    出处:https://www.cnblogs.com/wozixiaoyao/p/11965398.html

    版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际」知识共享许可协议进行许可。

    觉得文章不错,点个关注呗!

  • 相关阅读:
    idea 严重: Error configuring application listener of class org.springframework.web.context.Context 后面省略
    idea 新建 maven项目遇到的一些问题
    常用的DOS命令
    我对速汇金业务的理解
    和同事下班路上讨论心得(服务器部署的几点问题)
    5/6月学习工作总结(压力越大,意志越坚定)
    苏州银行对公久悬户
    苏州银行对公定存通项目
    苏州银行对公存款业务模块维护
    [转载]一个人的失败,99%失败于“脾气”
  • 原文地址:https://www.cnblogs.com/xinrong2019/p/15384387.html
Copyright © 2020-2023  润新知