用“数据与算法”解释DDD“上下文和聚合”


数据 vs 算法 = 上下文 vs. 聚合
从对应位置来看:

  • “数据”=“上下文”
  • “算法”= “聚合”

数据=上下文
首先,数据本身是上下文的一种体现,如果你熟悉写作文,那么作文要求你说明来龙去脉,上下文背景需要交待清楚,那么这些文字本身就是一种数据,一个领域中大量相关数据堆积在一起就能说明某种场景的上下文背景。
当然,这里上下文是有限制的、有边界的,也就是说:数据不是无限多,数据也是有限的,有一定意义的,比如围绕购物车发生的数据是发生在购物的上下文中;而下订单上下文中发生的数据则是围绕即将生成的订单进行的,比如需要填入收货地址,选择优惠码或凑单等等。

理解以上概念以后,事件建模或事件溯源EventSourcing概念就容易理解:
在上下文中发生的数据是一种“事件”。

也就是说:事件也是一种数据,只不过是发生的动作或活动的数据,把动词“事件”映射成名词“数据”,事件建模就是追踪一个需求流程中这些动作或活动,然后定义起止范围,也就是作用域,这段作用域就类似有界上下文BC,例如购物车上下文的起止作用域;下单上下文的起止作用域范围,这样我们就得到两个上下文:购物车上下文和下单上下文。

那么,关键就是界定上下文的开始与最后的作用域范围,也就是起点和终点,如果把事件数据看成是“点”,那么“点”串起来的就是“线”或“流stream”或“流程”,这就是上下文的作用域范围,就是有界的上下文BC。
一段线总是有两个端点,正如染色体两端有两个端粒影响人的寿命一样,上下文界限对整体DDD设计也非常重要。

如果你一开始无法界定上下文这段范围,或者可能随着时间边界会动态变化,那么采取事件溯源先把一段或可能包含几段线的数据“点”保存起来,以后再从中发现算法或聚合。

算法=聚合
算法本身代表一种聚合的意思,例如:X+Y 是加法,是将两个元素相加在一起的算法,那么,这里算法本身体现了高凝聚的特点,如果说有界上下文BC是一种截断耦合实现松耦合的方法,那么算法或聚合是实现高凝聚的方式。

罗伯-派克的5条编程规则:数据高于算法
数据占主导地位。如果你选择了正确的数据结构并很好地组织了事情,算法几乎总是不言而喻的。数据结构(而不是算法)才是编程的核心。

也就是说,当你界定好上下文数据以后,算法会自然涌现emerge,算法取决于你希望从这段上下文数据获得什么样的洞察力和预见性,比如你想按照某个字段合并或排序,那么使用简单SQL语句就可以实现,一条SQL语句本身就是一个聚合,否则怎么会成为“语句呢”?这里我们又碰到编程中的“作用域 vs. 语句”,
作用域=上下文;语句=聚合。

总结
看来处处都存在“上下文 vs. 聚合”,只要你多一个心眼,从这个新视角再重新看世界,你会发现世界果然是由这两种元素组成,正所谓“阴与阳”一样,上下文是藏在暗处的“阴”,而聚合是聚光灯下的“阳”。

原来二分法不只是“物质 vs. 意识”这样的二分方式,还有“上下文 vs. 聚合”、“数据 vs. 算法”、“作用域 vs . 语句”、“阴 vs. 阳”、“隐性 vs. 显性”、“有效期 vs. 产品”、“剂量 vs. 药品”等二分方式,这些方式是不是更实用?更具有可操作性?而且会纠正我们的认知偏见呢?