“富领域模型”是否会违反单一职责原则?

22

一个有趣的讨论在我刚刚输入这个问题时出现了。但我不认为它回答了我的问题。

我一直在使用 .NET MVC3,其中最好拥有贫血模型。视图模型和编辑模型最好是愚蠢的数据容器,你只需将其从控制器传递到视图即可。任何类型的应用程序流程都应该来自控制器,而视图则处理 UI 相关问题。在 MVC 中,我们不希望模型中出现任何行为。

然而,我们也不希望控制器中出现任何业务逻辑。对于大型应用程序,最好将域代码与模型、视图和控制器(以及 HTTP)分离并独立。因此,有一个单独的项目,在任何其他东西之前提供一个域模型(包含根据 DDD 组合的实体和值对象)。

我尝试过几次离开贫血模型,转向领域代码更丰富的模型,但我考虑放弃了。对我来说,似乎同时包含数据和行为的实体类违反了 SRP 原则。

例如,假设有一个非常常见的场景,即组成电子邮件。给定某个事件,根据 EmailTemplate、EmailAddress 和自定义值,域的责任是组成 EmailMessage 对象。模板作为一个具有属性的实体存在,并且用户提供自定义值作为输入。出于论证的目的,假设 EmailMessage 的 FROM 地址可以由外部服务提供(IConfigurationManager.DefaultFromMailAddress)。在这种要求下,似乎富领域模型可以将组成 EmailMessage 的责任交给 EmailTemplate:

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的本意--在我看来,EmailTemplate只是用于存储数据(主题格式、正文格式、附件以及可选的发件人/回复地址)。
最终,我将这个方法重构为专门的类,该类的唯一职责是在给定先前参数的情况下组合EmailMessage,并且我对此非常满意。实际上,我开始更喜欢贫血领域,因为它可以帮助我保持责任的分离,从而使类和单元测试更短、更简洁、更集中。似乎让实体和其他数据对象“不具备行为”对于分离责任是有好处的。或者我偏离了正确的方向?

2
一个丰富的领域模型只需要在相关的上下文中足够丰富。 - user1342582
2个回答

20
优先选择富领域模型而非贫血模型的论点取决于OOP的价值主张之一,即将行为和数据放在一起。核心好处是封装和内聚性,有助于理解代码。富领域模型也可以看作是信息专家模式的实例。然而,所有这些模式的价值在很大程度上是主观的。如果将数据和行为分开更有帮助,那么就这样做,但您也可能考虑其他人会查看代码。我喜欢尽可能地封装。在这种情况下,富领域模型的另一个好处是可能将某些属性设为私有。如果一个属性只由类上的一个方法使用,为什么要公开它呢?
无论一个丰富的领域模型是否违反SRP取决于你对责任的定义。根据SRP,责任是导致变化的原因,这本身需要定义。这个定义通常取决于手头的用例。你可以声明模板类的责任是作为模板,带有所有相关的含义,其中之一是从模板生成消息。模板属性的更改可能会影响ComposeMessageTo方法,这表明也许这些是单一责任。此外,ComposeMessageTo方法是模板中最有趣的部分。模板的客户端不关心该方法的实现方式或模板类中存在哪些属性。他们只想根据模板生成消息。这也支持将数据保留在方法旁边。

0

嗯,这取决于你想如何看待它。

另一种方式是:“单一职责原则是否可以违反丰富的领域模型?”

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接