您可能会说:不对,我的系统九成的工作全是核心域的,没法分。首先想说明的是,一个优秀的系统不仅仅要包含系统本身,还需要有很多的周边设施做支撑,是一个完整的生态,系统越大越是如此,比如日志汇聚、链路追踪、业务监控等都是生态的一部分。子域的划分是一个需要投入精力和思考的工作,您不仅要看眼下还需要再多往前看一步。您也不应该只考虑功能性需求,涉及安全、可用性等问题都应该在规划之出定义出来,做不做单说,得考虑。“推动技术进步的往往是非功能性需求”。回归到本文,即使核心域比例很大,也不太可能会涵盖系统的全面。极端一点,如果真的有95%的核心业务,您还可以对核心域作进一步划分呢?对划分出的“核心子域”进行优先级设定并决策资源投入度,与我们前面的不矛盾。
注意!
1、建议您在项目建设时将“核心域”与“支撑域”等同看待。虽然概念上进行了划分,但实际落地的时候两者几乎是需要同时进行的。划分的目的其实是让您在投入资源的时候比如开发人员选择,支撑域让中级或一般高级工程师出马就差不多了,监控运维就可以搞定。
2、“账户管理”、“数据字典”这类典型的属于支撑域的东西,开发工作往往优先于核心域
3、虽然某些域在业务上定义为核心,但系统建设时需要以同核心域相同的资源投入对待。这是灵活的,千万别陷入教条主义。
2、子域划分方法
子域的划分是指:确定业务属于“核心”、“通用”和“支撑”三个域的哪一类;针对每个子域如“核心域”中的内容如何再做细化。
把一个大的领域分成三个固定子域后,每个子域中的内容就是与您的业务相关的了。需要说明的是业务子域可能会再分为多个部分。比如核心域中包含A、B、C三个业务子域,A的业务子域又可再分成A1、A2两个业务子子域。细分的标准是每个子域应该有一个明确的边界,这个边界不是以技术作为划分依据的。比如电商系统中,“销售中心”是核心子域中的一部分,其内部可再划分为“商品中心”和“订单中心”两个子域。
业务子域的划分一般来说可以从两个维度出发:功能与流程。通过功能划分其实是可以根据感觉走的,虽然很不严肃,但也不是什么很玄的东西。有些业务听起来看起来就可区分其重要性。比如做个论坛,监控非常重要,但您不会真的投入一半人马去开发个主机监控系统吧?比如您熟悉的“豆瓣网”,“读书频道”与“电影频道”肯定得作为核心域中的两个业务子域吧?这种下意识的分割有时候很准,人是有这个灵性的。根据功能来分域一般是划分子域的一个非常非常重要的参考,下面我们以个人微信为例尝试通过功能的维度进行子域划分。
注意!
在做子域划分时请使用业务语言而非技术术语,尤其不能说什么微服务、Spring Cloud、MySQL、Kafka等。域属于业务方面概念,此阶段尚未到达讨论技术的地步。
下图为个人微信子域的示意图,也许与您设想的有不一致的情况,此处有很强的主观性。试想一下,这样的一个图如果可以在设计之初定义下来,基本上您和您的团队以及客户就可以在宏观上大概知道了这个系统要做什么,有哪些主要的业务。此图除用于资源分配的决策,还能在后续设计限界上下文时给予指导。
根据流程来划分一般是在功能划分后的基础上所做的补充,假如某个业务的进行顺序为:A - B - C,三个任务节点亦可以视为三个子域而存在。以电商购物为例,您在按功能分域的时候分割出了一个订购子域,订购的一般流程是:下单、支付、送货,那么我们就可以把这个子域再分解为三个子子域:下单子域、支付子域、送货子域。团队建设时可能会以此为据组建三个小的项目组。
如果您是一个DDD初学者,可能会对子域划分的正确与否产生怀疑。其实没必要有这一层的顾虑。子域的划分主观性很大,经过仔细分析后的划分基本上也八九不离十,随着后续对业务的深入了解,还会引入新的子域或对现有子域做调整。即使规划之出有些偏差也并不影响项目的成功失败,随时进行调整即可。除非您在规划之初把很明显应该作为核心的东西没有投入足够的关注,在项目建设前完全没做过分析工作才可能会出现这类情况。
下一节,讲解限界上下文及其与子域的关系。