领域驱动设计(DDD)基础:理解核心域、支撑域、通用域
好,咱们接着聊。上一章我们讲了微服务拆分的底层逻辑,很多同学听完就问我:“老师,到底怎么判断一个业务该不该拆成一个独立的服务?”
这个问题问得好。我当年刚带团队做重构时,也踩过这个坑。那时候我们一股脑把订单、库存、支付全拆了,结果发现服务之间互相调来调去,比原来还乱。后来我才明白——拆分的依据,不在技术层面,而在业务层面。而领域驱动设计(DDD),就是帮我们看清业务边界的那盏灯。
什么是领域?说白了就是你的业务地盘
先别急着背概念。你想想看,一个ERP系统里都有什么?有财务、有采购、有生产、有销售……每个模块都有自己的规则和逻辑。这些模块,就是一个个“领域”。
DDD把领域分成了三类:核心域、支撑域、通用域。这个分类,直接决定了你的资源应该往哪投,代码应该怎么写。
核心观点: 不是所有代码都值得你花同样的精力。把最好的资源留给核心域,把通用能力交给现成的工具。
核心域:你的命根子,别人抄不走的东西
核心域是什么?就是你的企业赖以生存的核心竞争力。没有它,你的公司就没了灵魂。
举个例子。我服务过一家做高端装备制造的企业,他们的ERP系统里,最核心的是什么?不是财务,不是HR,而是生产排程算法。这个算法决定了他们能不能在最短时间内、用最低成本把订单排出来。同行想学,学不会;想买,买不到。这就是核心域。
我的经验: 判断一个模块是不是核心域,就问自己一个问题:“如果这个模块挂了,公司还能正常运转吗?”如果答案是“不能”,那它就是核心域。
核心域的特点很明显:
- 业务逻辑复杂,充满了各种规则和例外
- 变化频繁,因为市场在变,策略在变
- 需要深度定制,市面上买不到现成的
- 投入产出比最高,值得你投入最好的团队
在微服务架构里,核心域应该被拆成最细粒度的服务。每个服务只负责一件事,但要把这件事做到极致。我曾经见过一个团队,把核心域里的“定价引擎”单独拆成一个服务,结果这个服务只有几百行代码,但支撑了全公司每年几十亿的营收。
支撑域:没有它不行,但它不是主角
支撑域,说白了就是“没有它你活不了,但有了它你也不会飞”。
还是那个装备制造企业的例子。他们的生产排程是核心域,那什么算支撑域?物料管理算一个。没有物料管理,生产排程就是空中楼阁——你排得再好,没料也白搭。但物料管理本身,并不会给企业带来直接的竞争优势。你想想看,哪家制造企业不做物料管理?大家都做,只是做得好坏的区别。
注意: 支撑域虽然不核心,但也不能外包。因为支撑域和核心域之间往往有紧密的业务耦合。我曾经见过一家公司,把物料管理外包给第三方系统,结果每次生产排程调整,都要等物料系统同步数据,延迟高达半小时。最后不得不自己重写。
支撑域的特点:
- 业务逻辑中等复杂,有一定定制需求
- 变化频率中等,不会天天改
- 可以部分复用,但需要适配核心域
- 值得投入一定资源,但不必追求极致
在微服务架构里,支撑域可以拆成中等粒度的服务。比如物料管理,可以拆成“物料主数据”、“库存管理”、“采购申请”几个服务。每个服务内部可以有一定的复杂度,但不要像核心域那样拆得太细。
通用域:能买就别造,能租就别买
通用域,就是那些所有企业都差不多的功能。比如:
- 用户认证和权限管理
- 邮件通知
- 日志记录
- 文件存储
- 支付接口(如果你们不是做支付的话)
这些功能,说白了就是“别人怎么做,你就怎么做”。你花三个月自己写一个权限系统,和用现成的Spring Security或者Keycloak,效果差不多。但你自己写的,bug可能更多,文档可能更少。
我记得有一次,一个团队花了大半年自己开发了一套工作流引擎。我问他们为什么不用现成的?他们说“想完全掌控”。结果呢?那个引擎上线后bug不断,最后不得不换回Activiti。白白浪费了半年时间。
我的建议: 对于通用域,优先考虑SaaS服务,其次考虑开源方案,最后才考虑自研。把精力省下来,投入到核心域里去。
通用域的特点:
- 业务逻辑简单,标准化程度高
- 几乎不变,行业里已经形成了最佳实践
- 可以直接复用,不需要太多定制
- 投入产出比低,不值得花太多精力
在微服务架构里,通用域通常不需要拆得太细。一个“通知服务”就够了,没必要拆成“短信通知”、“邮件通知”、“站内信通知”三个服务。除非你的业务量特别大,需要独立扩展。
如何区分这三类领域?一个实用的判断框架
很多同学问我:“老师,我分不清某个模块到底算核心域还是支撑域,怎么办?”
我一般会让他们用这个框架来判断:
| 判断维度 | 核心域 | 支撑域 | 通用域 |
|---|---|---|---|
| 是否构成核心竞争力? | 是 | 否 | 否 |
| 市面上是否有成熟方案? | 通常没有 | 可能有,但需要适配 | 有,且成熟 |
| 业务逻辑是否独特? | 非常独特 | 有一定独特性 | 标准化 |
| 变化频率如何? | 高 | 中 | 低 |
| 建议投入的资源 | 最多 | 中等 | 最少 |
举个例子。假设你在做一个电商ERP系统:
- 核心域: 商品推荐算法、定价策略、库存分配策略
- 支撑域: 订单管理、支付对接、物流跟踪
- 通用域: 用户注册登录、权限管理、日志记录
你看,这样一分,你就知道该把最好的架构师派到哪里去了。
一个真实的案例:我是怎么用这个分类救了一个项目的
几年前,我接手过一个ERP重构项目。团队已经干了半年,但进度严重滞后。我一看代码,发现问题出在哪了——他们把所有模块都当核心域来对待。
权限管理,他们自己写了一套复杂的RBAC模型,花了两个月。邮件通知,他们自己实现了邮件服务器集群,又花了一个月。而真正的核心——生产排程算法,反而只分到了两个人,代码写得一塌糊涂。
我当时就做了一个决定:把通用域全部砍掉,换成现成的方案。权限管理用Keycloak,邮件通知用SendGrid,日志用ELK。省下来的资源,全部投入到核心域里。
结果呢?三个月后,核心域的重构顺利完成,系统性能提升了5倍。而通用域那边,因为用的是成熟方案,几乎没出过问题。
总结一下: 核心域要“重”,支撑域要“稳”,通用域要“轻”。把有限的资源,投到最能产生价值的地方去。
最后说两句
DDD的领域分类,说白了就是帮你回答一个问题:你的钱和时间,到底该花在哪里?
很多团队做微服务重构,一上来就想着怎么拆分、怎么部署、怎么用Kubernetes。这些当然重要,但如果你连核心域和通用域都分不清,那你的微服务架构,大概率会变成一个“微服务乱架构”。
下一章,我们会深入聊聊限界上下文——也就是怎么用DDD的方法,把核心域、支撑域、通用域真正地“画”出来,变成一个个独立的微服务。到时候,你会看到这些概念是怎么落地的。
嗯,今天就到这里。有什么问题,欢迎在评论区留言,我会挑一些典型的问题在下一章开头回答。