对于领域专家、程序员和测试工程师来说,领域建模所构建的概念模型是撑起软件开发系统的骨架。领域建模的方法有很多种,ThoughtWorks的同事们经常使用经过徐昊改编的“四色建模法”[1]来进行建模。而本文所描述的“限界纸笔建模法”,在“四色建模法”的“时标对象”的基础上确定"限界上下文”[2]与“聚集”[3]的概念,再使用“纸和笔来管理”的方法,力图在建模过程中实现“分而治之”,增强数据的完整性,并避免过度设计。

为了便于说明,下文将以“小画笔”绘画课外班的业务为例,首先描述同事亢江妹用四色建模法对其所建的模型,然后再描述如何在其“时标对象”的基础上,运用限界纸笔建模法进行建模。

“小画笔”绘画课外班

“小画笔”是一家面向2-10岁小朋友的绘画培训机构。乐乐老师是这个培训机构的主管。她毕业于北京师范学院,有一些认识的同学和老师愿意在业余时间授课来获得一定收入。

“小画笔”目前有三个班:

  • 美术预科:适合2-3岁孩子,从看、摸、闻、听、尝培养艺术感;每期课程8次,每周一次,周末上;每班最少6个孩子开课,最多10个孩子。

  • 书法:适合3-6岁孩子,学习字体结构、笔画线条;每期课程8次,每周一次,周末或晚上上; 每班最少6个孩子开课,最多12个孩子。

  • 儿童绘本:适合年龄5-10岁,用文字和图画表达;每期课程8次,每周一次,周末或晚上上; 每班最少6个孩子开课,最多12个孩子。

“小画笔”有三个教室:达芬奇,毕加索和梵高。

每两个月开始新期课程,8次课结束后重新开始。

乐乐老师的主要工作是:

  • 根据现有老师能够讲授的课程及时间,做好课程表安排,提前两个月把下期课程介绍做好,印成宣传彩页;

  • 在附近社区里给家长宣传,招募生源;

  • 接受家长报名(电话或面对面),记录和追踪报名情况;

  • 收取学费,学费支付采用现金付款,或银联卡刷卡支付;

  • 争取在每一期课程开始前都有足够学员报名,可以准时开班;

  • 保证课程质量和安全,保证营收,维持培训机构正常运转。

乐乐老师需要处理的三个核心问题有:

  • 下一期的课程如何安排? - 排课

  • 如何招生和管理报名?     - 管理报名

  • 如何保证课程质量?         - 管理课堂

挑战:

请为乐乐老师设计一个软件工具的概念模型,能让乐乐老师方便地管理排课、报名和学员考勤,维护“小画笔”的正常运营。

在日常运营中,乐乐老师经常碰到下列问题:

  • 课程开始后发现有孩子没来上课,也没有请假,需要查找家长联系电话来询问。

  • 有时孩子请假会造成缺课,家长会要求在后期课程中补上。乐乐老师需要记录孩子的上课次数,在可以补上课程的时候通知孩子来参加。

  • 需要查看还有哪个家长没有缴费,通知他们缴费。

  • 需要查看某个孩子的缴费记录,以确认家长是否缴费。

  • 经常有家长要求先试一次课,再确定报名交钱。但每班只能在报名不满额的情况下才能试听,且最多只能允许3个孩子试听。所以乐乐需要追踪每班报名多少孩子、试学多少孩子、还有没有试学名额。

  • 需要经常查看每班是否报满,可否开课;如果不满,需要再去小区做宣传。

  • 需要提前跟上课老师确认,确保他们能按时授课。

  • 有些课程可能会有一位主任老师和另一位见习老师来共同授课,所以这些课程每门课需要管理多位老师的信息。

  • 需要跟踪教学质量,确保老师按时按质授课,及正常教学安全和秩序;

请检查你所设计的概念模型能否帮乐乐老师解决上述问题。

用“四色建模法”进行建模

第一步:寻找要追溯的事件

1. 谁,在什么时候,为谁,报名了什么课程

2. 谁,在什么时候,为谁,支付了多少学费

3. 谁,在什么时候,上了什么课程

第二步:识别“时标对象”[4]

按时间发展的先后顺序,用红色所表示的起到“追溯单据”作用的“时标”概念,如下图所示:

从“四色建模法”到“限界纸笔建模法” | TW洞见_java

第三步:寻找时标对象周围的“人、地、物”[5]

在“时标”对象周围的用绿色所表示的“人、地、物”概念,如下图所示:

从“四色建模法”到“限界纸笔建模法” | TW洞见_java_02
第四步:抽象“角色”[6]

在上图中插入用黄色所表示的“角色”概念,如下图所示:


从“四色建模法”到“限界纸笔建模法” | TW洞见_java_03

第五步:补充“描述”信息[7]

在上图中插入用蓝色所表示的“描述”概念,如下图所示:

从“四色建模法”到“限界纸笔建模法” | TW洞见_java_04

用“限界纸笔建模法”进行建模

上面用四色建模法对“小画笔”绘画课外班的软件系统所做的建模过程,最大的亮点是按时间发展的先后顺序,识别出起到“追溯单据”作用的“时标”概念。这种识别方法直达业务核心数据,简便有效。

此外,限界纸笔建模法可以继续进行以下三项建模工作:

1. 划分限界上下文,避免模型发展成“大泥球架构”。

2. 强调“聚集根”[8]的概念,更好地保证数据的完整性。

3. 寻找“恰好够用”的概念,避免过度设计,降低所建模型的复杂性。

一个“聚集根”好比一个经理,这个“聚集”所汇聚的所有彼此相关的概念好比这个经理手下管理的所有员工。当另一个“聚集”的经理,要访问该“聚集”中的某个员工时,必须要通过该“聚集”的“聚集根”这个经理的同意和安排才行,不能直接去找。这样设计能够将管理数据的访问职责缩小到一些“经理”那里,既方便定位职责,也有助于增强数据的完整性。

下面尝试用限界纸笔建模法来对“小画笔”绘画课外班的软件系统建模。

第一步:根据“追溯单据”的价值识别核心领域[9]

首先以“小画笔”绘画课外班的业务“追溯单据”为线索,列出这些追溯单据为乐乐老师所提供价值,并合并其中一些价值相同的单据。比如对于一个只有三间教室的小课外培训机构,只有交费成功的“报名”才视作有效报名。所以“报名登记表”和“交费纪录”可以合并。然后确定这些价值所对应的核心领域。如下表所示:


第二步:确定核心领域之间的依赖关系

排课、报名与签到三个核心领域的依赖关系如下所示:

  排课 <—— 报名 <—— 签到

上面的箭头表示:“报名”需要依赖“排课”所提供的信息,而“签到”需要依赖“报名”所提供的信息。

第三步:用纸和笔画表格并写实例

先选择一个核心领域,然后开始在其所对应的“限界上下文”中,开始对其建模。假设时光回退100年,那时没有电脑,只有纸和笔。用纸和笔画表格并写实例的方法,来管理该核心领域的“恰好够用”的数据,来达成乐乐老师在此核心领域所期望的价值。

首先选择“排课”。下图是用纸和笔画出的表格,并有一条实例数据:


第四步:确定“聚集根”

给表中所有的列找一个“经理”来作为“聚集根”。这里选择“课程”作为“聚集根”,它是一种具有唯一标识(即有唯一的课程编号)的Entity[10]概念,然后把表中所有的列名都抄写到表下“聚集根”的右侧,并用括号括起来,如下图所示:

第五步:以“人以群分”的原则抽取新的“聚集”

观察所抄写的“聚集根”右侧所有聚集在一起的各个概念,提取出总是“一起玩儿”的多个概念,形成一个新的聚集,并确定这个新聚集的名字。比如,“上课时间”、“起始日期”、“次数”这三个概念总是一起出现,它们决定了这门课程的学时,所以就提取“学时”这个新聚集,并把这三个概念从“课程”右侧划掉。“学时”这个概念不需要有唯一标识,所以是Value Object[11]概念。它和“课程”是一对一的关系。用相同的方法可以提取“老师”这个新聚集,它是Entity概念,“课程”与它是一对多的关系。如下图所示:从“四色建模法”到“限界纸笔建模法” | TW洞见_java_05对于那些只“自己单独玩儿”的概念,如“学费”、“教室”等,就先暂时放到“课程”这个聚集根下面,等随着将来业务演进出现了新的“能一起玩儿的伙伴”后,再提取新的聚集不迟。

至此,使用限界纸笔建模法对“排课”这个核心领域所进行的建模告一段落。下图是使用这种方法对“报名”这个核心领域所建的模型,“签到”核心领域的建模略去不讨论。从“四色建模法”到“限界纸笔建模法” | TW洞见_java_06这里有一个问题,“排课”这个限界上下文中有“课程”这个聚集根,而“报名”这个限界上下文中也有“课程”这个聚集根,这两者是同一个概念吗?

从DDD的观点来看,这两者是不同的概念,而且在数据库中也应该是两张不同的表。前者是“排课.课程”,后者是“报名.课程”。两者的属性也各不相同,前者是:排课.课程(名称、介绍、适合年龄、学费、教室),后者是:报名.课程(名称)。当然,这两个概念的“课程名称”和课程编号都是一致的。当“报名”限界上下文需要访问“排课”限界上下文中的“课程”概念来获取“课程介绍”等信息时,需要通过两者之间的“翻译器”来根据上述一致的课程编号来进行翻译和转换。

限界纸笔建模法的3点优势

1. 划分核心领域有助于“分而治之”:一旦确定了核心领域,限界上下文也就确定了,不同的限界上下文之间通过“翻译器”来彼此沟通并屏蔽干扰,这样就避免了“大泥球”的设计,并有助于演进到微服务架构。

2. “聚集根”有助于数据完整性:每个限界上下文都有一个“聚集根”的概念,外界对其下属概念的访问都必须通过它来进行,这样既方便定位职责,也有助于增强数据的完整性。

3. 用“纸和笔”画恰好够用的概念有助于避免过度设计:每个限界上下文中要管理的概念,都是通过“倒退到没有电脑而用纸和笔的时代如何管理”来引导出来的,用纸和笔来记录,能促使人避免写过多的信息,而只写限界上下文中恰好够用的概念。

总结

四色建模法最大的亮点是按时间发展的先后顺序,识别起“追溯单据”作用的“时标”概念,从而能把握业务核心数据,简便有效。

限界纸笔建模法,使用了DDD中的"限界上下文”与“聚集”的概念以及“纸和笔来管理”方法,来实现“分而治之”,增强数据的完整性,避免过度设计。