贫血数据模型,dao's,...权威参考? [英] anemic data model, dao's, ... authoritative reference?

查看:21
本文介绍了贫血数据模型,dao's,...权威参考?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然是一位经验丰富的程序员和架构师,但同样的旧基本问题反复出现.我对此有自己的信仰,但我需要一些权威来源.

贫血的数据模型((c)Martin Fowler?)本质上是坏的吗?蛋糕应该可以自己烤吗?发票是否应该知道如何(以及何时应该允许)向其自身添加行,还是应该由另一层执行此操作?rabbit.addToHole(hole) 还是hole.addRabbit(rabbit)?有没有证明 ADM 更容易出错,或者更容易维护,或者其他什么?

您可以在网络上找到很多声明,但如果可能的话,我真的想要一些权威的引述、参考或事实.

解决方案

请参阅此 stackoverflow 答案以获得启发.>

这是我的看法:

ADM(贫血领域模型)不能用类图 UML 表示

贫血域模型很糟糕,仅在完整 oop 方面.它被认为是糟糕的设计,主要是因为您无法在其中创建带有嵌入行为的 UML 类和关系.例如,在具有丰富域模型 (RDM) 的 Invoice 类中:

  • 班级名称:订单
  • 已实施:ICommittable、IDraftable、...
  • 属性:否、UserId、TotalAmount、...
  • 行为:Commit()、SaveDraft()、...

该课程是自我记录的,并自我解释了它可以做什么和不能做什么.

如果是贫血领域模型,则没有行为,我们需要搜索哪个类负责提交和保存草稿.而且由于 UML 类图只显示了每个类之间的关系(一对多/多对多/聚合/复合),无法记录与服务类的关系,Martin Fowler 的观点是正确的.

<块引用>

一般来说,您在服务中发现的行为越多,你很可能会剥夺自己域名的好处模型.如果你所有的逻辑都在服务中,那你就失明了.

这是基于 Lars Mathiassen 的 OOAD 书中的类图 UML.不知道新的类图UML能不能代表服务类.

建议零售价

在 ADM 的观点和对继承的组合中,RDM(富域模型)违反了 SRP.这可能是真的,但你可以参考这个问题 讨论.

简而言之,在 ADM 的观点中,SRP 等于一个班级做一件事并且只做一件事.对课程进行任何更改都有一个且只有一个原因.

在 RDM 的观点中,SRP 等于所有与接口本身相关且仅与接口本身相关的责任.只要操作涉及到其他类,就需要将操作放到其他接口中.实现本身可能会有所不同,例如,如果一个类可以实现 2 个或更多接口.简单来说就是如果界面中的某个操作需要改变,只有一个原因.

ADM 往往会被静态方法滥用,并且可能适用脏黑客

ADM 很容易被静态方法滥用——服务类.它也可以用 RDM 来完成,但它需要另一个抽象层,不值得.静态方法通常是糟糕设计的标志,它降低了可测试性并可能引入竞争条件以及隐藏依赖关系.

ADM 可以有很多肮脏的黑客,因为操作不受对象定义的约束(嘿,我可以为此创建另一个类!).在糟糕的设计师手中,这可能是灾难性的.在 RDM 中更难,请阅读下一点以获取信息.

RDM 的实现通常不能被重用,也不能被模拟.RDM 需要事先了解系统的行为

通常 RDM 的实现不能被重用和模拟.在 TDD 方式中,它降低了可测试性(如果有可以模拟和重用的 RDM,请纠正我).想象一下这种继承树的情况:

 A/\乙丙

如果 B 需要在 C 中实现逻辑,则无法完成.使用组合而不是继承,可以实现.在 RDM 中,可以通过这样的设计来完成:

 A|D/\乙丙

在其中引入更多的继承.但是,为了尽早实现整洁的设计,您需要直接了解系统流程.也就是说,RDM 要求您在进行任何设计之前了解系统的行为,否则您将不知道任何适合您系统的名为 ISubmitable、IUpdateable、ICrushable、IRenderable、ISoluble 等的接口.

结论

这就是我对这种圣战的全部看法.两者都有优点和缺点.我通常选择 ADM,因为它看起来更高的灵活性甚至更低的可靠性.不管是ADM还是RDM,如果你的系统设计不好,维护起来就很困难.任何类型的电锯只有在熟练的木匠手中才会发光.

Although an experimented programmer and architect, the same old basic problem comes back recurrently. I have my own religion about it, but I need some authoritative source.

Are anemic data models ( (c) Martin Fowler?) inherently bad? Should a cake be able to bake itself? Should an invoice know how (and when it should allow) to add lines to itself, or should another layer do that? rabbit.addToHole(hole) or hole.addRabbit(rabbit)? Has it been proved that an ADM is more bug-prone, or easier to maintain, or anything?

You can find a lot of claims on the web, but I'd really want some authoritative quotes, references or facts, if possible from both sides.

解决方案

See this stackoverflow answer for enlightment.

And this is my opinion:

ADM (Anemic Domain Model) cannot be represented with class diagram UML

Anemic domain model is bad, only in terms of full oop. It is considered as bad design, mainly because you cannot create UML classes and relations with embedded behavior inside it. For example, in your Invoice class with Rich Domain Model (RDM):

  • Class Name: Order
  • Implemented: ICommittable, IDraftable, ...
  • Attributes: No, UserId, TotalAmount, ...
  • Behavior: Commit(), SaveDraft(), ...

The class is self-documented and self explaining about what it can do and what can't.

If it is anemic domain model, it does not has the behavior, and we need to search which class is responsible for Committing and Saving Draft. And since the UML class diagram only shows the relation between each classes (one to many / many to many / aggregate / composite), the relation with service class cannot be documented, and Martin Fowler has his point right.

In general, the more behavior you find in the services, the more likely you are to be robbing yourself of the benefits of a domain model. If all your logic is in services, you've robbed yourself blind.

This is based on class diagram UML in OOAD book by Lars Mathiassen. I don't know if newer class diagram UML can represent service class.

SRP

In ADM's point of view and compisition over inheritance, RDM (rich domain model) violates SRP. It may be true, but you can refer to this question for discussion.

Shortly, in ADM's point of view, SRP equals one class doing one thing and one thing only. Any change into the class has one and only one reason.

In RDM's point of view, SRP equals all responsibility related to and only to the interface itself. As soon as the operation involve other class, then the operation need to be put into other interface. The implementation itself may vary, as such if a class can implement 2 or more interfaces. It is simply said as if an operation in interface need to be changed, it is for and only for one reason.

ADM tend to be abused with static methods and dirty hacks may apply

ADM is very easy to be abused with static methods - service class. It can be done with RDM too, but it need another layer of abstraction and not worth it. Static methods are usually a sign of bad design, it reduced testability and may introduce race conditions, as well as hiding the dependency.

ADM can has many dirty hacks because the operations are not being constrained by the object definition (hey, I can create another class for this!). In hand of bad designer, this can become catastrophic. In RDM it is harder, please read next point for information.

RDM's implementation usually cannot be reused and cannot be mocked. RDM require to know the system's behavior beforehand

Usually RDM's implementation cannot be reused and mocked. In TDD manner, it reduced testability (please correct me if there is RDM which can be mocked and reused). Imagine a situation with this inheritance tree:

    A
   / \
  B   C

If B need logic implemented in C, it cannot be done. Using composition over inheritance, it can be achieved. In RDM, it can be done with a design like this:

    A
    |
    D
   / \
  B   C

In which introduce more inheritance. However, in order to achieve neat design early, you will need to know the system flow firsthand. That said, RDM require you to know the system's behavior before doing any design, or you won't know any of the interfaces named ISubmitable, IUpdateable, ICrushable, IRenderable, ISoluble, etc, suitable for your system.

Conclusion

That's all my opinion about this kind of holy war. Both has pros and cons. I usually go for ADM because it seems like higher flexibility even has less reliability. Regardless of ADM or RDM, if you design your system bad, the maintenance is hard. Any type of chainsaw will only shines when held by skillful carpenter.

这篇关于贫血数据模型,dao's,...权威参考?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆