Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Domain driven design 能不能“a”;“富域模型”;违反单一责任原则?_Domain Driven Design_Single Responsibility Principle_Anemic Domain Model - Fatal编程技术网

Domain driven design 能不能“a”;“富域模型”;违反单一责任原则?

Domain driven design 能不能“a”;“富域模型”;违反单一责任原则?,domain-driven-design,single-responsibility-principle,anemic-domain-model,Domain Driven Design,Single Responsibility Principle,Anemic Domain Model,我刚才打这个问题的时候就想到了。但我认为这并不能回答我的问题 我一直在与.NETMVC3合作,希望有一个贫血模型。视图模型和编辑模型最好作为哑数据容器,您可以将其从控制器传递到视图。任何类型的应用程序流都应该来自控制器,视图处理UI问题。在MVC中,我们不希望模型中出现任何行为 但是,我们也不希望控制器中有任何业务逻辑。对于较大的应用程序,最好将域代码与模型、视图和控制器(以及HTTP)分开并独立于它们。因此,有一个单独的项目,它首先提供一个域模型(带有实体和值对象,根据DDD组合成聚合) 我已

我刚才打这个问题的时候就想到了。但我认为这并不能回答我的问题

我一直在与.NETMVC3合作,希望有一个贫血模型。视图模型和编辑模型最好作为哑数据容器,您可以将其从控制器传递到视图。任何类型的应用程序流都应该来自控制器,视图处理UI问题。在MVC中,我们不希望模型中出现任何行为

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

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

举个例子,网络上一个非常常见的场景,撰写电子邮件。给定某个事件,域负责在给定EmailTemplate、EmailAddress和自定义值的情况下组合EmailMessage对象。模板作为具有属性的实体存在,自定义值作为用户的输入提供。为了便于讨论,我们还假设EmailMessage的发件人地址可以由外部服务(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;
    }
}
公共类电子邮件模板
{
公共EmailMessage ComposeMessageTo(电子邮件地址至,
IDictionary自定义值,IConfigurationManager配置)
{
var emailMessage=new emailMessage();//内部构造函数
//扩展方法
emailMessage.Body=this.BodyFormat.ApplyCustomValues(customValues);
emailMessage.From=此.From??config.DefaultFromMailAddress;
//呜呜呜呜
回复电子邮件;
}
}
这是我对富域模型的一次尝试。但是,添加此方法后,EmailTemplate负责包含实体数据属性和撰写消息。它大约有15行长,似乎分散了全班同学对电子邮件模板的注意力——在我看来,电子邮件模板就是存储数据(主题格式、正文格式、附件以及可选的发件人/回复地址)


我最终将这个方法重构成一个专门的类,根据前面的参数,这个类的唯一责任就是编写一封EmailMessage,我对此感到非常高兴。事实上,我开始更喜欢贫血领域,因为它帮助我保持职责分离,使类和单元测试更短、更简洁、更集中。看起来,让实体和其他数据对象“没有行为”有助于分离责任。还是我偏离了正轨?

支持富域模型而不是贫乏模型的论点取决于OOP的一个价值主张,即保持行为和数据彼此相邻。核心好处是封装和内聚,这有助于对代码进行推理。丰富域模型也可以被视为模式的一个实例。然而,所有这些模式的价值在很大程度上都是主观的。如果对数据和行为保持独立性有帮助,那么,尽管如此,你也可以考虑其他人来查看代码。我宁愿尽可能多地封装。在这种情况下,更丰富的域模型的另一个好处是可以将某些属性私有化。如果一个属性仅由类上的一个方法使用,为什么要将其公开


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

好吧,这取决于你想如何看待它

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


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

一个丰富的领域模型只需要足够丰富,以满足相关的上下文。