危险的DDD聚合根

  DDD的核心是聚合。这没有问题,大家都认同。但关于DDD中的聚合方式,可能就有些问题了。下面谈一下我的观点,希望大家参与讨论。
  其实当初第一次看到DDD中关于聚合根部分论述的时候,就感觉有些僵化。同时,看到jivejdon关于聚合根实现代码时,有感觉有些沉重而不自然。
DDD中的聚合根的分析设计思路大致是这样:1、业务本质逻辑分析;2、确认聚合对象间的组成关系;3、所有的读写必须沿着这些固有的路径进行。这是一种静态聚合的设计思路。理论上讲,似乎没有什么问题。但实际上,人对第一步中的业务逻辑分析就是一个渐进的过程,不是稳定不变的。不是谁都可以成为业务领域专家,就算是业务领域专家也不一定都是对的。在我看来,从时间维度和多用户场景下看,这种静态的聚合分析设计方法是根本无法保证领域模型的稳定性。
  也许有人不理解,那可以打个比喻:过去几个孩子可以和爸爸妈妈高高兴兴地一家人生活在一起,但是孩子们长大后是必然要分家的。其实我只是在强调,人们对业务过程的认识是有局限性的,谁也无法避免。
  DDD本来就是处理复杂业务逻辑设计问题。在论坛里经常也能看到大家用DDD去分析一些小项目的时候,大家往往为谁是聚合根而无法达成共识。这说明每个人对业务认识的角度、深度和广度都不同,自然得出的聚合根也不同。也因为这种认识的局限性,可能造成不同领域模型的聚合根是相同的(比如人)。试想,这样的情况下,领域模型怎么保持稳定。
  更现实的解决方式是怎么在动态过程中尽可能地保证业务领域模型的稳定性。在我看来:对象之间是平等的,没有谁高人一等(也就是没有聚合根);场景(业务)是聚合对象行为的唯一理由;复杂的场景是由简单场景聚合而成。不管业务如何变化,总有子场景是不变的,这样就能获得最大的“维护利润”(业务不变性)。

我也认同聚合根的提炼是一个过程,分析设计过程是一个不断切分领域,划定领域边界,找出bounded context 再提炼出上下文中的领域模型,聚合根实体也将呼之欲出。

这是实施ddd的步骤,可以结合BDD等敏捷,也可以使用瀑布不断强攻,最终目标都是找出聚合根。

其实,我个人实践和交流思考体会是,聚合根很好找,它实际是一个集合概念,比如cms的栏目是一个集合,很可能是根,论坛中thread是集合,car也是集合概念,由发动机 车轮组成的。这个集合可以认为是逻辑中那个集合,反正是有节点元素的树枝。

不找出聚合根,基本就不叫用过ddd,可能很武断,这是我个人体会。

  作为企业软件开发而言,最大的挑战就是业务变化。这一方面来源于业务本身的变化(应用系统应用不断深入和推广),另一方面是我们对业务认识不断深入的过程。不能适应变化的系统只有死路一条。
  复杂的业务要求软件架构必须具备很强的适应能力。如前面所说,这是一个渐进的过程。DDD本身就是为了解决复杂业务的软件开发问题的。“如何避免颠覆式修改”是最大的挑战。
  如果发现找的聚合根是错误的,那领域模型还可重用的价值还有多大,这种代价和成本是否 能够承受?

很赞同你的观点,业务是变化的,但是这个变化不是什么都变,其中有不变和变的。而不变的一般认为是领域模型们和他们的结构,这被dci称为不变的数据模型,变化的是各种行为,在不同场景下的行为,比如我在家这个场景是父亲,在单位这个场景是程序员,其中贯穿不变的是我这个数据模型,也就是领域模型,一个实体模型,聚合根,聚合着各种关于我的各种数据,身高 体重等等,这些属性数据和具体业务场景无关,属于不变的,聚合根实际代表这个不变的总称。

聚合根实体经过各种业务场景后,其状态是不同的,比如在家消耗爱心数据,在单位增长财富数据,账户余额状态变化了。

过去不重视事件情况下,聚合根状态总是当前最新状态,无法追溯不同业务场景造成当时状态,我们使用event sourcing实现这个目的。


我们总是探索方法应付变化,当然方法带来缺陷是,这个方法使用不到位,应付变化也就不能实现,而方法使用不到位带来的重构成本只能默默承担,学习成本嘛。

以上我在业务统一描述中也有阐述,只是个人观点。

  当业务还不算复杂时(比如单系统),对象之间的聚合关系还是比较好找的。但是在企业的复杂业务里,就很难说了。
  banq,我不知道你是否听过“企业操作系统”这样的东西。“企业操作系统”已经不是单个类似ERP的系统了,而是企业不同业务系统的总称。在这样的场景下,对象之间的关系十分复杂,也就意味的对象之间的聚合关系很难说的清楚,因为可能会从各个不同的业务层面去描述整个业务(比如计划、研发、质量、成本、风险等等)。
  如果想做一款通用产品,你可能要考虑同一业务在民企和国企有什么不同,在不同行业又会有什么不同。在这样的复杂场景下,寻找到正确的聚合根是十分困难的。在我的经验看来,聚合根的维护代价太高了。
  如果围绕聚合根的设计很容易搞,为什么上次那个“关于借书”的设计,大家的思路五花八门呢。又比如jivejdon中的不变性设计是否能让每个人一看就能轻松弄明白呢。我想这根本不现实,因为那是banq多年经验的浓缩。

[该贴被flyzb于2012-09-08 18:43修改过]
[该贴被flyzb于2012-09-08 18:53修改过]

其实我想说的是在聚合根设计的演进中,如何保证“合理”的业务能够被顺利的复用,如何避免“因为一个小的业务要求而造成伤筋动骨式的更改”才是架构设计的关键