解决DDD最大难题-如何划分领域
本文书接上回《反DDD模式之“复用”》,关注公众号(老肖想当外语大佬)获取信息:
最新文章更新;
DDD框架源码(.NET、Java双平台);
加群畅聊,建模分析、技术实现交流;
视频和直播在B站。
背景
最近直播的时候,看到一条留言,问我是否有关于如何划分领域的文章,翻看了一下,发现关于这么重要的问题,居然没有专门、认真、细致地讲过。也难怪不少人说不接地气,整天搞些虚头巴脑的东西。但没有讲的原因,我还是要为自己辩解几句的,不是不想讲,也不是不能讲,而是我潜意识里觉得本质的东西讲明白了,这个问题就太简单,没必要讲。
当然,如果你是我的老粉丝,关注过我过往输出的内容,那么你也知道,早前也是有在我们FireUG社区的DDD公开课里专门讲这个话题(【DDD 领域驱动设计 | PART V:如何识别领域边界?】 https://b23.tv/sRqAC8O )。
时至今日,我自己对于软件工程的认知又经过了一轮迭代,重新来解读一下这个问题。
先说答案
问:如何划分领域?
答:基于如下两条可以得出一个领域:
当你有一个需求,叫创建xxx时,那么这个xxx就是一个聚合根;
我们可以视作一个聚合根就是一个领域;
如何解读
例如,一个系统中,需要创建一个用户,那么用户就是聚合根,用户就是一个领域,诸如此类的需求是非常容易识别的,我相信不论你的软件设计经验如何,都是可以基于这个规则来做出判断的。
当然你会说,我有一个需求是给用户创建收货地址,那么这个收货地址是不是聚合根呢?这就要看,你创建的是“收货地址”,还是“用户的收货地址”,如果你认为是“收货地址”,那么它就应该是聚合根,如果你认为是“用户的收货地址”,意味着这个需求,仅仅是给“用户的收货地址属性”添加新值。
又比如订单,你是认为是“创建订单”还是“用户的订单”呢?我想大部分人会直觉上选择“创建订单”,为什么会有这样的直觉?我想,你一定会得出一个答案,“订单”足够复杂。
那么这样看来,理解业务的标准是不是又变成了“复杂的就分开”这么一个不太好衡量的判断呢?不妨你把它反过来看,就有答案了,那就是“简单的就合并”。
还是前面的例子,还是收货地址,因为存在一个需求叫“创建收货地址”或者“创建用户的收货地址”,我分不清楚,没关系,我们就默认视作存在这个聚合根,存在“收货地址”这个领域。然后我们在考虑,这个领域独立存在对我们有没有好处,这个领域合并进“用户”领域,我们是否可以接受。如果我们有充分的把握说合并没有问题,那么就合并,否则,就让它成为一个领域,并保持边界明确。
为什么基于创建xxx来判断
也许,你会有疑问,为什么基于“创建xxx”需求来判断聚合根?核心逻辑就是这类需求,意味着xxx不可分割的整体,意味xxx就是最小的完整范围,相当于我们基于这类需求,识别出了系统内的“原子单元”,就像一片片乐高积木一样,不可再拆分。
本质是什么
在我看来,这样划分领域的方法的本质,就是我们先认为边界就在那里,凡是有创建xxx的需求,即存在一个领域,只是说我们经过思考,某些领域合并进去是比较确定复杂度是可以掌控的,那么我们才做出了合并领域的决定。
所以,与其说这是如何划分领域,不如说,这是思考什么时候合并领域。
底层价值观的支撑
如果你是跟随本系列文章一路阅读过来的话,一定知道,我对于软件设计的核心观点是:
DDD是一种价值观
保持边界明确是最重要的事
那么你就会发现,前面说的方法,是完全契合这个价值观的,我们首先明确出组成系统的一个个“原子单元”,识别出它们,然后再谨慎地进行合并,在没有把握的情况下,优先保持领域边界明确,避免它们之间的耦合。
而信奉这个价值观的依据则是我们对于复杂度的理解,这在前文也有详细讲解:
系统复杂度与元素的数量和元素的关系有关;
元素的关系对系统复杂度的影响远远大于元素的数量所产生的影响;
说到底,核心目的仍然是为了保持我们对系统复杂度的掌控,因此我们谨慎地为系统内的领域之间“建立耦合”。
完整操作方法
那么,如果你和我一样,认同DDD是价值观,保持边界是最重要的事,我们完整的操作方法就是:
当你有一个需求,叫创建xxx时,那么这个xxx就是一个聚合根;
我们可以视作一个聚合根就是一个领域;
当我们非常大把握可以掌控一个领域合并后的复杂度时,可以考虑合并这两个领域;
结尾
以上就是我们团队日常分析需求、设计方案和建模的实际操作方法,如果你赞同或者有共鸣,也很期望您将文章分享给更多的朋友。如果你持有不同的观点和视角,也欢迎与我讨论,我相信,至少持续提升开发者幸福感这个方向,咱们是有共识的。
解决DDD最大难题-如何划分领域的更多相关文章
- DCI架构是如何解决DDD战术建模缺点的?
摘要:将DCI架构总结成一句话就是:领域对象(Object)在不同的场景(Context)中扮演(Cast)不同的角色(Role),角色之间通过交互(Interactive)来完成具体的业务逻辑. 本 ...
- 十年磨一剑,王坚自研的MaxCompute如何解决世界级算力难题
摘要: 2009年这项关于大数据的技术长征开始.王坚带队,目标是自研大数据计算平台MaxCompute统一阿里巴巴内部的数据和大数据计算体系. 大数据时代,随着企业数据规模的急剧增长,传统软件已无法承 ...
- indexDB解决过的难题
我第一次使用indexDB是1年前(2018年10月),运用这个黑科技,解决过3个异常棘手的问题(如果不是indexDB 几乎找不到其他解决方案)所以我经常强调,前端一定要学indexDB! 难题一: ...
- [思维提升|干货All in]6种算法解决LeetCode困难题:滑动窗口最大值
为了更好的阅读体验,欢迎阅读原文: [思维提升|干货All in]6种算法解决LeetCode困难题:滑动窗口最大值 (eriktse.com) 最近在leetcode遇到一道非常经典的题目:239. ...
- DDD划分领域、子域,核心域,支撑域的目的
名词解释 在DDD兴起的原因以及与微服务的关系中曾举了一个研究桃树的例子,如果要研究桃树,将桃树根据器官分成根.茎.叶.花.果实.种子,这每一种器官都可以认为是一个研究领域,而领域又有更加具体的细分, ...
- 从壹开始微服务 [ DDD ] 之三 ║ 简单说说:领域、子域、限界上下文
前言 哈喽大家好,DDD领域驱动设计系列又开始了,前天周二的那篇入门文章中,也收到了一定的效果(写小说的除外),同时我也是倍感鸭梨,怎么说呢,DDD领域驱动设计已经有十年历史了,甚至更久,但是包括我在 ...
- 使用prolog逻辑语言解决爱因斯坦斑马难题
如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/06/28/sevenlang-prolog/. 目 ...
- 七周七语言之使用prolog解决爱因斯坦斑马难题
如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/06/28/sevenlang-prolog/. 目 ...
- 解决大数据难题 阿里云MaxCompute获科技大奖
摘要: 据介绍,MaxCompute(大规模分布式的数据计算平台)是国内最早自研的大数据计算平台之一,主要应用于大规模数据处理场景.目前,这项源自浙江.解决世界级难题的成果已拥有EB(百京)级别的数据 ...
- 深入super,看Python如何解决钻石继承难题 【转】
原文地址 http://www.cnblogs.com/testview/p/4651198.html 1. Python的继承以及调用父类成员 python子类调用父类成员有2种方法,分别是普通 ...
随机推荐
- 什么是淘宝API?
淘宝API是淘宝开放平台提供给开发者的一系列应用程序编程接口,它们允许开发者访问和使用淘宝的数据和服务.通过这些API,开发者可以构建应用程序,实现商品信息检索.订单管理.用户行为分析.物流跟踪等 ...
- CANopen学习笔记(二)通讯对象PDO和SDO等
通讯对象 PDO 我的观点:一个 CANopen 设备可以拥有最多 512 个 RPDO 和 512 个 TPDO,总共最多 1024 个 PDO.(得到GPT4o的肯定) CiA协议栈观点:一个只有 ...
- plotly dash
https://community.plotly.com/t/callback-on-graph-slider-change-which-property-to-use-as-input/33979/ ...
- 微信小程序--云开发支付闭环
云开发支付流程闭环 extends 微信小程序--使用云开发完成支付闭环 在上述文章中,我们对支付结果的处理更多依赖于小程序端的操作 订单号存储在小程序端 支付结果采用小程序端定时触发器轮询 现在我对 ...
- ASP.NET Core – Try Preview
前言 .NET 7 已经来到 RC 阶段了. 通常 RC 就是我们 (写库的人) 要入场的时候了. 有发现 Bug 要尽可能在这段期间提交. 不然后患无穷. 这篇主要就是来讲讲如果测试 RC 版本的 ...
- Let's Encrypt Free SSL – win-acme
前言 之前有介绍过用 Certify The Web 来做 Let's Encrypt SSL, 但是最近常看到它的 License 提示, 有种随时随地要收费的感觉 于是找了一个替代品 win-ac ...
- MySQL配置缓存查询和维护
配置文件设置缓存 query_cache_size = 20M #缓存大小 query_cache_type = ON #开启缓存 table_cache=256 #用于限制缓存表的最大数目,如果当前 ...
- 【赵渝强老师】搭建Hadoop环境
说明:这里我们以本地模式和伪分布模式伪列,为大家介绍如何搭建Hadoop环境.有了这个基础,大家可以自行搭建Hadoop的全分布模式. 需要使用的安装介质: hadoop-2.7.3.tar.gz j ...
- Flutter将视频或图文分享到抖音
如何在 Flutter 中分享视频到抖音 话不多说,先上效果: 原理 发布内容至抖音 H5 场景_移动/网站应用_抖音开放平台 (open-douyin.com) 本教程没有接入抖音原生 SDK 以及 ...
- Android Qcom USB Driver学习(十一)
基于TI的Firmware Update固件升级的流程分析usb appliction layers的数据 USB Protocol Package ①/② map to check password ...