虽然是经验丰富的程序员和架构师,但同样的旧基本问题反复出现。我有自己的宗教信仰,但我需要一些权威来源。
贫血数据模型((c)Martin Fowler?)本质上是不好的?蛋糕应该能够自己烘烤吗?发票应该知道如何(以及何时应该允许)向自己添加行,或者另一层应该这样做? rabbit.addToHole(洞)或hole.addRabbit(兔子)?是否已证明ADM更容易出错,或更容易维护,或其他什么?
你可以在网上找到很多声明,但如果可能的话,我真的想要一些权威的引用,参考或事实。
答案 0 :(得分:3)
请参阅此stackoverflow answer以获取启发。
这是我的观点:
贫血领域模型很糟糕,只有完整的oop。它被认为是糟糕的设计,主要是因为你无法在其中创建UML类和与嵌入行为的关系。例如,在包含Rich Domain Model(RDM)的Invoice类中:
该课程是自我记录的,并自我解释它可以做什么和不能做什么。
如果是贫血领域模型,它没有行为,我们需要搜索哪个类负责提交和保存草稿。由于UML类图仅显示了每个类之间的关系(一对多/多对多/聚合/复合),因此无法记录与服务类的关系,而且Martin Fowler的观点是正确的。
通常,您在服务中找到的行为越多,就越多 可能你要剥夺自己域名的好处 模型。如果你的所有逻辑都在服务中,你就会失明。
这是基于Lars Mathiassen
的OOAD书中的类图UML。我不知道更新的类图UML是否可以代表服务类。
在ADM的观点和对继承的压缩中,RDM(富域模型)违反了SRP。这可能是真的,但您可以参考此question进行讨论。
很简单,从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很容易被静态方法滥用 - 服务类。它也可以用RDM完成,但它需要另一层抽象而不值得。静态方法通常是糟糕设计的标志,它降低了可测试性并可能引入竞争条件,以及隐藏依赖性。
ADM可能有很多脏黑客,因为操作不受对象定义的约束(嘿,我可以为此创建另一个类!)。在糟糕的设计师手中,这可能会变成灾难性的。在RDM中更难,请阅读下一个信息。
通常RDM的实现不能被重用和嘲笑。以TDD方式,它降低了可测试性(如果有可以模拟和重用的RDM,请纠正我)。想象一下这个继承树的情况:
A
/ \
B C
如果B需要在C中实现逻辑,则无法完成。使用组合而不是继承,可以实现。在RDM中,可以使用如下设计完成:
A
|
D
/ \
B C
其中引入了更多的继承。但是,为了尽早实现整洁的设计,您需要直接了解系统流程。也就是说,RDM要求您在进行任何设计之前了解系统的行为,否则您将不会知道任何适用于您的系统的名为ISubmitable,IUpdateable,ICrushable,IRenderable,ISoluble等的接口。
这就是我对这种圣战的看法。两者都有利有弊。我通常选择ADM,因为它似乎具有更高的灵活性,甚至可靠性更低。无论是ADM还是RDM,如果您的系统设计不好,维护都很困难。任何类型的电锯只有在熟练的木匠手持时才能发光。
答案 1 :(得分:-2)
我认为this question的接受答案也是最能回答您问题的答案。
我认为必须记住的事情是: