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

05|跨越现实的障碍(中):富含知识还是代码坏味道?

从行为模式上看,还会遇到什么问题?
业务逻辑被富集到领域模型中
上下文对象中加入依赖关系
上下文对象揭示了领域知识的意图
上下文对象的封装使得不同上下文中的技术可以是完全异构的
上下文对象的获取放置在Repository上
角色对象的构造需要放置在能够触发技术调用的地方
通过装饰器构造角色对象
将角色抽象成接口
DCI范型要求逻辑汇聚于显式建模的上下文对象或角色对象
原味面向对象范型 vs. DCI范型
与模型关联的代码难以维护和改动
改不动的模型会影响知识的提炼循环
一个对象包含不同的上下文,导致模型僵硬和认知过载
解决方法:角色对象和上下文对象
导致模型僵化和潜在的性能问题
领域模型中的对象在多个上下文中发挥重要作用
思考题
上下文间的依赖关系
通过上下文对象分离不同上下文中的逻辑
通过角色对象分离不同上下文中的逻辑
逻辑汇聚于上下文还是实体?
因富含逻辑而产生的过大类
上下文过载问题
跨越现实的障碍(中):富含知识还是代码坏味道?

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

你好,我是徐昊。今天我们来聊聊如何有效地分离领域模型中的上下文。
上节课我们介绍了关联对象,以及如何通过关联对象建模聚合 / 关联关系,从而在不影响性能的情况下,更好地维持领域模型与软件实现的统一。
今天,我们来看另一个在关联领域模型与软件实现时经常遇到的问题:上下文过载(Context Overloading)。所谓上下文过载,就是指领域模型中的某个对象会在多个上下文中发挥重要作用,甚至是聚合根。一来这个对象本身会变得很复杂,造成模型僵化;二来可能会带来潜在的性能问题。
于是,将过载的上下文进行有效的分离,就成了我们现在需要面对的问题。方法上也有很多不同的选择,我主要介绍角色对象(Role Object)和上下文对象(Context Object)这两种。这两个方法与我们上节课讲的关联对象一脉相承,都是通过将隐含概念显式建模来解决问题。
同样地,在看到具体的解决方法之前,我们需要深入了解上下文过载会产生哪些问题。

因富含逻辑而产生的过大类

为了帮助你理解上下文过载会产生哪些问题,我还是借助极客时间专栏的例子来说明一下。当然,首先我们需要扩展这个领域模型。
在这个扩展了的模型中,包含了三个不同的上下文。
订阅:用户阅读订阅内容的上下文,根据订阅关系判断某些内容是否对用户可见;
社交:用户维护朋友关系的上下文,通过朋友关系分享动态与信息;
订单:用户购买订阅专栏的上下文,通过订单与支付,完成对专栏的订阅。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

领域模型设计中的上下文过载问题是一个常见挑战,本文提出了两种解决方法:角色对象和上下文对象。作者通过具体例子阐述了上下文过载可能导致的模型僵化、认知过载和性能问题,并指出了原味面向对象范型和DCI范型在解决上下文过载问题上的差异。解决方案包括针对不同上下文中的角色建模,将对应的逻辑富集到角色对象中,以及通过上下文对象分离不同上下文中的逻辑。这些方法使得软件实现、模型与统一语言更加紧密地关联在一起。总之,本文深入浅出地解释了上下文过载问题的根源和解决方案,对领域模型设计和软件实现具有重要的指导意义。

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

全部留言(63)

  • 最新
  • 精选
  • Geek_0e3b40
    置顶
    想问一下,文中的图是用什么工具画出来的?

    作者回复: keynote

    2021-07-24
    2
    2
  • Jxin
    1.徐昊老师的代码看起来很舒服啊。就是喜欢看这种面相意图的的代码,看代码就像在看故事。 2.关于上下文,徐昊老师的这个写法我是第一次见,很有意思,长见识了。我自己一般是将上下文作为一个《应用层》到《领域层》中间的层级(乐衷于加层),用于区分不同的《领域层》。这样其实上下文就作为分包的边界在代码中体现,也算是模型与实现关联。 3.对应的仓储层不会在UserRep中收入多个上下文的操作,而是独立的BuyerRep,ReaderRep。这样做其实可以更好的分隔复杂性。但顺着老师对这些模型的定义来看,并不是很合适。因为Buyer,Reader的定义是User的角色,是一种派生。分隔包会弱化这层派生关系。可是,也不只有老师这种定义方式,如果我定义Buyer,Reader都是独立的聚合模型,与User是平级的,它们之间是聚合间平级的关系,而非 data和role的派生关系,那么在包层级上明确分隔就挺合理。拿微信来说,微信用户和微信视频号用户都是用户的派生角色吗?微信视频号用户有自己独立的用户体系,它与微信用户是两个聚合的关联关系,一个微信用户可以关联多个微信视频号用户。定义不同一切就不同。 4.我认为包结构,模块结构都算是代码的组成部分,所以也可以用来做模型与实现的关联。不知道徐昊老师怎么看? 5.感觉还是上下文分包比上下文类模型协作风险低些。这么好看的代码(真心的,没有反义),碰上不懂的弟兄,被用错,写废的概率感觉还挺高。放到大型项目,团队协作,这真的挺让人担忧。这又涉及到一个决策点,是模型的简单重要还是模型的准确重要。我认为跳出来,看哪个对当前的团队当前的处境效益较高就哪个重要。如果硬要选一个,我选简单,可读比卓越重要(来自《实现模式》的价值观),可读要有同理心。

    作者回复: 扮演并不是派生关系 之所以不把角色做成聚合根 因为它们不是独立的对象 不会用reader buyer表 数据上都是user表。所以并不是微信和微信视频号的关系。那是关联而不是扮演。分包除非有arch unit去加测试 否则不如对象约束力强。最后 简单与否在于是否与概念中的模型一致,而不在于代码的写法

    2021-07-07
    4
    14
  • 邓志国
    把社交的上下文传递到reader里,是不是让reader耦合了社交呢?

    作者回复: 实现随便耦合 接口看不出来就行 耦合不是坏事 不当耦合才是

    2021-07-18
    4
    13
  • 卓然
    不要user模型,直接建模reader,buyer,contact不行吗?

    作者回复: 不行 实体是一个 行为不同

    2021-07-17
    3
  • 赵晏龙
    到了角色一步,我觉得我遇到的问题基本就解决了,因为我会把【角色】作为【聚合根】使用,可以解释为:在特定上下文中,Buyer、Reader、Contact就是聚合根,User只是一个在它们之间起到关联作用的类,只在【关联关系】相关逻辑上下文中进行使用。我觉得这样建模能够更进一步的将模型解耦。 所以我并没有很好的理解,我这样的解决方案是否还存在老师您讲的后面这些问题。

    作者回复: 可以 扮演角色 有不同的实现方法

    2021-07-06
    2
  • 与非
    在订单上下文,聚合根不应该不应该是Order吗?在支付上下文中聚合根不应该是Payment.为啥是Buyer呢

    作者回复: 聚合与生命周期相关

    2021-10-24
    2
    1
  • 在最后一个赠送课程的例子里,是不是可以用领域服务这概念去包装赠送的逻辑呢,因为从另一个角度看,赠送的业务逻辑,也的确是需要通过多个上下文协作完成,好像放领域服务里也合适

    作者回复: 我也不喜欢游离于上下文之外的服务 那不过是过程的另一个名字 不够面向对象

    2021-07-05
    4
    1
  • 狩月
    在实现中加入上下文依赖, 这样是不是隐藏了“必须得是friend才能赠送订阅”这个领域知识? 毕竟从领域层已经看不到这个逻辑了, 业务逻辑相当于下放了?

    作者回复: 然而模型表达不了规则 怎么也要到代码里

    2021-07-05
    3
    1
  • 飞翔
    老师 ddd能用在写框架上嘛 比如写个zookeper

    作者回复: 没必要

    2022-03-17
    2
  • 此方彼方Francis
    实现随便耦合能展开讲讲吗?

    作者回复: 这个不需要讲吧

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