21

刚才我输入这个问题时,出现了一个有趣的线程。我不认为它回答了我的问题。

我一直在使用 .NET MVC3 进行大量工作,希望有一个贫血模型。视图模型和编辑模型最好作为愚蠢的数据容器,您可以将它们从控制器传递到视图。任何类型的应用程序流都应该来自控制器,视图处理 UI 问题。在 MVC 中,我们不希望模型中有任何行为。

但是,我们也不希望控制器中有任何业务逻辑。对于较大的应用程序,最好将域代码与模型、视图和控制器(以及通常的 HTTP)分开并独立于模型、视图和控制器。因此,有一个单独的项目首先提供域模型(具有实体和值对象,根据 DDD 组合成聚合)。

我已经做了一些尝试,从一个贫乏的模型转向更丰富的域代码模型,我正在考虑放弃。在我看来,拥有既包含数据又包含行为的实体类违反了 SRP。

以网络上一个非常常见的场景为例,撰写电子邮件。给定一些事件,域有责任在给定 EmailTemplate、EmailAddress 和自定义值的情况下编写一个 EmailMessage 对象。模板作为具有属性的实体存在,并且自定义值作为用户输入提供。为了论证,我们还假设 EmailMessage 的 FROM 地址可以由外部服务 (IConfigurationManager.DefaultFromMailAddress) 提供。鉴于这些要求,富域模型似乎可以让 EmailTemplate 负责编写 EmailMessage:

public class EmailTemplate
{
    public EmailMessage ComposeMessageTo(EmailAddress to, 
        IDictionary<string, string> customValues, IConfigurationManager config)
    {
        var emailMessage = new EmailMessage(); // internal constructor
                                            // extension method
        emailMessage.Body = this.BodyFormat.ApplyCustomValues(customValues);
        emailMessage.From = this.From ?? config.DefaultFromMailAddress;
        // bla bla bla
        return emailMessage;
    }
}

这是我对富域模型的尝试之一。但是,在添加此方法后,EmailTemplate 负责包含实体数据属性和撰写消息。它大约有 15 行长,似乎分散了全班学生对成为 EmailTemplate 的真正含义的注意力——IMO 只是存储数据(主题格式、正文格式、附件和可选的发件人/回复地址)。

我最终将此方法重构为一个专门的类,该类的唯一责任是根据前面的参数编写一个 EmailMessage,我对此更满意。事实上,我开始更喜欢贫血领域,因为它帮助我保持职责分离,使类和单元测试更短、更简洁、更专注。似乎使实体和其他数据对象“没有行为”可以很好地分离责任。还是我在这里偏离轨道?

4

2 回答 2

20

支持丰富领域模型而不是贫乏模型的论点取决于 OOP 的价值主张之一,即保持行为和数据彼此相邻。核心好处是封装和凝聚力,有助于推理代码。富领域模型也可以看作是信息专家的一个实例图案。然而,所有这些模式的价值在很大程度上是主观的。如果将数据和行为分开对您更有帮助,那么就这样吧,尽管您可能还会考虑其他将查看代码的人。我更喜欢尽可能多地封装。在这种情况下,更丰富的域模型的另一个好处是可以将某些属性设为私有。如果一个属性只被类中的一种方法使用,为什么要公开它?

富域模型是否违反 SRP 取决于您对责任的定义。根据 SRP,责任是改变的理由,这本身就需要一个定义。该定义通常取决于手头的用例。您可以声明模板类的职责是成为一个模板,包含所有出现的含义,其中之一是从模板生成消息。模板属性之一的更改可能会影响ComposeMessageTo方法,这表明这些可能是单一职责。此外,ComposeMessageTo方法是模板中最有趣的部分。模板的客户不关心方法是如何实现的,也不关心模板类的属性是什么。他们只想根据模板生成消息。这也投票赞成将数据保留在方法旁边。

于 2012-05-07T22:17:16.433 回答
0

好吧,这取决于您要如何看待它。

另一种方式是:“单一职责原则会违反富域模型吗?”

两者都是指导方针。软件设计中没有任何“原则”。然而,有好的设计和坏的设计。这两个概念都可以以不同的方式使用,以实现良好的设计。

于 2016-07-26T08:14:46.590 回答