如何落地业务建模
徐昊
Thoughtworks 中国区 CTO
24830 人已学习
新⼈⾸单¥68
登录后,你可以任选2讲全文学习
课程目录
已完结/共 32 讲
如何落地业务建模
15
15
1.0x
00:00/00:00
登录|注册

04|跨越现实的障碍(上):要性能还是要模型?

通过集体逻辑揭示意图
隔离技术实现细节与领域逻辑
水平扩展 vs. 垂直扩展
单机单体架构 vs. 多层架构
虚拟镜像
集合与数据库的等价
面向对象数据库
一次性读入全部数据 vs. N+1问题
代码坏味道
性能问题
延迟加载
问题在建模思路上的根源
逻辑富集于模型中
聚合与聚合根(Aggregation Root)
微服务和云原生时代
云原生分布式架构
多层单体架构
单机时代
提炼知识的循环
统一语言与模型关联
模型与软件实现关联
领域模型中的隐式概念
隐式概念
关联对象的优势
多层架构彻底割裂了集合与数据库
Smalltalk中集合与数据库是等价的
集合遍历与N+1
无法封装的数据库开销
建模聚合(Aggregation)
实现模式
需要找到能够维持模型与软件实现统一的办法
架构风格的变化
平衡的权责关系
两关联一循环
思考题
关联对象(Association Object)
领域驱动设计
跨越现实的障碍(上):要性能还是要模型?

该思维导图由 AI 生成,仅供参考

你好,我是徐昊。今天我们来聊聊通过关联对象(Assocation Object)建模聚合(Aggregation)。
在前面三节课,我们学习了领域驱动设计中的“两关联一循环”:模型与软件实现关联;统一语言与模型关联;提炼知识的循环。其中,统一语言与提炼知识的循环作为一种更为平衡的权责关系,促进了业务方与技术方更好的协作。而这一切又是以模型与软件实现关联为基础。
然而落地到实践中,关联模型与软件实现总有一些让人纠结与苦恼的地方。引起这些苦恼的主要原因是架构风格的变化我们已经从单机时代过渡到了多层单体架构,以及云原生分布式架构,但我们所采用的建模思路与编程风格并没有彻底跟上时代的步伐,这种差异通常会以性能问题或是代码坏味道的形式出现。
如果我们想要真正发挥出领域驱动设计的作用,就需要在不同架构风格下,找到能够维持模型与软件实现统一的办法。这也是这个领域常看常新,总能产生新实践的原因。
因而接下来,我会用三节课来介绍一组实现模式,帮助我们应对从单机架构过渡到多层架构,保持模型与软件实现的关联。这些模式也是我们后面学习在微服务和云原生时代,实施领域驱动设计方法的基础。
今天这节课,我们就先从关联对象这一方法开始讲起。关联对象是一个古老的设计 / 分析模式,Martin Fowler 在《分析模式》中讨论过它。Peter Coad 将它视为一种常见的业务构成模式,并应用到业务分析中。而我大概从 2005 年开始,使用它建模领域驱动设计中的聚合与关联关系,以解决领域模型(Domain Model)中对技术组件的封装问题。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

领域驱动设计中的关联对象建模聚合方法是本文的核心内容。文章首先介绍了领域驱动设计中聚合关系的问题,以及在应用领域驱动设计时遇到的数据库开销和N+1问题。作者提出了通过查询语句一次性定位所需分页的解决方法,并探讨了可能引发的逻辑泄露问题。随后,文章指出了造成这种两难局面的根源,并解释了为什么内存中的集合与数据库是等价的。接着,文章阐述了多层架构对集合与数据库的割裂,以及如何使用关联对象来解决这一问题。作者详细介绍了关联对象的定义和实现,以及如何将领域对象与技术实现分离。最后,文章提出了将关联对象与领域对象结合的方法。通过深入浅出的方式,本文为读者提供了领域驱动设计中关联对象建模聚合的方法,为实施领域驱动设计的人员提供了有益的指导。 文章通过引入关联对象,实现了领域逻辑与技术实现细节的隔离,解决了数据库开销和N+1问题。关联对象的引入不仅带来了隔离效果,还能从概念上帮助获得更好的领域模型,通过集体逻辑的直接建模,揭示了意图。这种方法能够更好地解决性能与逻辑封装的问题,为读者提供了实用的解决方案。文章通过具体的例子和代码演示,使读者能够更好地理解和应用领域驱动设计中的关联对象建模聚合方法。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《如何落地业务建模》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(46)

  • 最新
  • 精选
  • Geek_3531cc
    置顶
    感谢老师的好文章。我这边有个疑问,专栏聚合了内容同理也可以用关联对象模式,那如果作者需要对专栏里的其中一个内容进行修改,需要先获取专栏然后通过关联对象获取要修改的内容进行修改,再将整个专栏聚合进行保存,这样是否还是没有保障到性能呢?

    作者回复: 可以在关联对象上直接增加方法,关联对象表示聚合逻辑。灵活很多

    2021-07-01
    2
    7
  • 阿鸡
    想请问为什么不直接在UserRepository中添加关于分页的逻辑?虽然能感觉到不太恰当,但是好像也没暴露逻辑,并且user也没依赖具体db实现

    作者回复: 这样user就退化为纯粹的无逻辑数据对象了,也就是贫血对象

    2021-07-02
    6
    15
  • webmin
    以前只是觉得语言中对象与关系型数据库之间的转换非常不自然,从未问过为什么会是这样,感谢老师今天帮我理清这层关系,原来二者在单体架构时期是等价,是因为后来分层以后才被割裂了,感觉现在的多层是把以前在语言内部实现的机制给放大化了,且为了通用性把CRUD等细节暴露出来了,导致编程语言在使用时感觉不那么自然和一体化了。 通过将隐式的概念显式化建模,就我自己的理解是需要把隐藏背后想表达的真实意途给找出来,比如今天的例子就是要操作数据,操作数据可以是操作数据库也可以是操作NOSQL等其它各种实现方式,第一反应是操作数据库是一种惯性思维,它并不是真正想要做的事。

    作者回复: 之前在美国的DDD大会上很多实践者严肃地讨论要不要放弃关系型数据库。

    2021-07-03
    10
  • 赵晏龙
    关联对象我更多的是用来解决业务上的多对多关系,至于分页这个逻辑,我倒是目前还没遇到过这样的场景,不过看完有一些疑问:Subscription虽然通过接口隔离了数据库操作,但是如果Subscription本身有一些业务逻辑呢?是否就考虑把接口换成抽象类,在抽象类中实现业务? 另外,在我看来,这种方式应该只在遇到数据库性能问题的时候使用,不应该作为通用方法来使用。有一些影响领域模型只对业务模型进行实现的单一职责。 另另另另外,CQRS邪教您如何解读的?

    作者回复: 作为通用方法建模的是集合逻辑。有整整五年 我们在全球范围内 看到使用cqrs的项目几乎都失败了 仍然很多人前赴后继 不是邪教是什么

    2021-07-05
    4
    6
  • Jxin
    关于内容: 1.基础类型偏执。这是一个坏味道,但仅在个人或者小团队的小项目中能看到它被认真对待(也只有刻意训练,践行代码健身操时能被认真对待)。一旦项目变大时间变长人数变多,不知不觉就被抛弃了(毕竟这么写对于不理解的人来说真的会被骂死。一段代码要求阅读者有比较高的认知才能有比较好的可读性。以教育阅读者为前题的同理心写出来的代码还算得上同理心吗?)。 2.CQRS。就这个分页场景,我多半是以单独的查询模型来承接。只有在命令/写操作才会构建聚合来实现。这么想来,似乎破坏了一个聚合模型应有的完整性。停顿几秒钟,这里我本觉得只是遵循CQRS,但实际上只是单纯不希望领域聚合实体具备任何io操作。确实,这样没有依赖任何除jdk程序库之外的技术代码,但是pojo对象的行为运行期具备db操作,而这自然又会牵扯到框架,那么这个pojo对象便不再纯粹,只能算是伪pojo。概念的咬文嚼字没有意义,不过伪pojo多了io操作这个不可靠因素,测试验证自然也得多些操作和心思,这是好是坏呢,从长期看又如何?。合理了模型的概念却提高了迭代维护时的心智负担,这是个问题。毕竟我们学习概念,并非想捧着去吵架,而是想通过概念解决自己的实际问题。 课后题: 1.隐式概念:规则,流程,参数(一个函数入参太多时,往往会引起我们的关注和思考,看看这里是不是有一个隐式的概念能包含这些参数) 2.发现有滞后性,基本只有在迭代中,坏味道积累到一定程度,引发注意,重新定义和审视时才能发现。但更多的时候是被遗漏。不过漏了本身感觉也并非不合理,不见得就是麻烦。

    作者回复: pojo是幻想 cqrs是邪教

    2021-07-02
    3
    4
  • Oops!
    集合是面向对象模型中广泛存在的概念,如果全都使用关联对象进行建模, 是否会导致类爆炸呢? 有什么可以遵循的规则或者方法来鉴别哪些隐式的集合概念使用关联对象进行建模比较好, 哪些则不然呢? 是不是如果两个对象之间仅仅是简单的包含关系, 可以先用系统提供的集合容器来建模实现, 等到业务复杂了, 需要对这个集合进行除了增删改查之外的操作时, 再使用关联对象进行建模?

    作者回复: 需要持久化或者来着三方系统的聚合

    2021-07-01
    4
  • 张振华
    老师有没有好的项目和代码,推荐一下。结合着研究下

    作者回复: 没

    2021-08-11
    2
    3
  • OWL
    关联对象确实是一种很巧妙的方法。但是也有疑惑,比如UserRepo获取user后,修改其部分subscriptions,容易产生修改逻辑后UserRepo.set(user)。而其实应该是在Subscriptions关联对象上操作。关联对象隐藏了Subscription聚合的Repo。 而Eric的DDD中,则是大聚合拆分出多个小聚合,然后通过小聚合中持有聚合根的Id相互关联。同时小聚合自然有自己的repo。而这种拆分,模型的完整性和独立性也减弱,所以需要结合service来完成业务。 既然引入关联对象,完全去Repo如何?UsersRepo直接用Users来替代。

    作者回复: 可以

    2021-08-05
    2
  • 马若飞
    “集合作为面向对象中的重要概念,被吸纳入这些语言后,就去掉了与数据库的强关联”——从语言演进历史得出问题本源,膜拜!

    作者回复: 哥 别这样

    2021-07-15
    2
  • 吴鹏
    看到作者thoughtWorks背景毫不犹豫就订阅了,看到这里就感觉值回票价了

    编辑回复: 满是惊喜,值得拥有

    2021-07-02
    2
收起评论
显示
设置
留言
46
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部