请参阅此stackoverflow 答案以获得启发。
这是我的看法:
ADM(贫血领域模型)不能用类图 UML 表示
贫血域模型不好,仅在完整的 oop 方面。它被认为是糟糕的设计,主要是因为您无法创建 UML 类和在其中嵌入行为的关系。例如,在具有富域模型 (RDM) 的 Invoice 类中:
- 班级名称:订单
- 已实现:ICommittable、IDraftable、...
- 属性:否,UserId,TotalAmount,...
- 行为:提交(),SaveDraft(),...
该课程是自我记录的,并自我解释它可以做什么和不能做什么。
如果是贫血的领域模型,它是没有行为的,我们需要搜索哪个类负责提交和保存草稿。而且由于 UML 类图只显示了每个类之间的关系(一对多/多对多/聚合/复合),因此无法记录与服务类的关系,Martin Fowler 的观点是正确的。
通常,您在服务中发现的行为越多,您就越有可能剥夺自己从领域模型中获得的好处。如果您的所有逻辑都在服务中,那么您已经蒙蔽了自己。
这是基于 OOAD 书中的类图 UML Lars Mathiassen
。我不知道更新的类图 UML 是否可以表示服务类。
建议零售价
从 ADM 的观点和继承的角度来看,RDM(富域模型)违反了 SRP。这可能是真的,但你可以参考这个问题进行讨论。
简而言之,在 ADM 的观点中,SRP 等于一个班级做一件事且只做一件事。Any change into the class has one and only one reason.
在 RDM 的观点中,SRP 等同于所有与接口本身相关的责任。一旦操作涉及到其他类,则需要将操作放到其他接口中。实现本身可能会有所不同,例如,如果一个类可以实现 2 个或更多接口。简称为if an operation in interface need to be changed, it is for and only for one reason
。
ADM 往往被静态方法滥用,并且可能适用肮脏的黑客攻击
ADM 很容易被静态方法——服务类滥用。它也可以用 RDM 完成,但它需要另一层抽象,不值得。静态方法通常是糟糕设计的标志,它降低了可测试性,并可能引入竞争条件,以及隐藏依赖关系。
ADM 可能有许多肮脏的技巧,因为操作不受对象定义的限制(嘿,我可以为此创建另一个类!)。在糟糕的设计师手中,这可能会成为灾难性的。在 RDM 中更难,请阅读下一点以获取信息。
RDM 的实现通常不能重用,也不能模拟。RDM 需要事先了解系统的行为
通常 RDM 的实现不能被重用和模拟。在 TDD 方式中,它降低了可测试性(如果有可以模拟和重用的 RDM,请纠正我)。想象一下这个继承树的情况:
A
/ \
B C
如果 B 需要在 C 中实现逻辑,则无法完成。使用组合而不是继承,可以实现。在 RDM 中,可以通过这样的设计来完成:
A
|
D
/ \
B C
其中引入了更多的继承。但是,为了尽早实现整洁的设计,您需要直接了解系统流程。也就是说,RDM 要求您在进行任何设计之前了解系统的行为,否则您将不知道任何适合您系统的名为 ISubmitable、IUpdateable、ICrushable、IRenderable、ISoluble 等的接口。
结论
这就是我对这种圣战的全部看法。两者都有优点和缺点。我通常选择 ADM,因为它似乎更高的灵活性甚至更低的可靠性。不管是 ADM 还是 RDM,如果你的系统设计不好,维护就会很困难。任何类型的电锯只有在熟练的木匠手握时才会发光。