Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.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
C# 域模型中的setter_C#_Domain Driven Design_Domain Model - Fatal编程技术网

C# 域模型中的setter

C# 域模型中的setter,c#,domain-driven-design,domain-model,C#,Domain Driven Design,Domain Model,在DDD的上下文中,域模型上的setter是一种代码气味。 应该避免使用它们,原因很简单,它们不是域的一部分。其中没有领域专家可以理解的名词,数据的更改应该通过特定的方法进行 例如: customer.StreetName = ... customer.City = ... 正确的方法是使用customer.ChangeAddress方法,然后发布事件等。。至少从我的理解来看,这都是合理的理论,我完全可以理解为什么域模型中的setter不是真正需要的 但是: 如果域模型上没有setter,那么

在DDD的上下文中,域模型上的setter是一种代码气味。 应该避免使用它们,原因很简单,它们不是域的一部分。其中没有领域专家可以理解的名词,数据的更改应该通过特定的方法进行

例如:

customer.StreetName = ...
customer.City = ...
正确的方法是使用
customer.ChangeAddress
方法,然后发布事件等。。至少从我的理解来看,这都是合理的理论,我完全可以理解为什么域模型中的setter不是真正需要的

但是: 如果域模型上没有setter,那么这些方法将很难测试

如果我不能构造一个客户实例,而没有一个大的构造函数来接受所有参数,或者做一些反射魔法,那么我如何让客户实例运行我的测试呢?我在后端使用NHibernate,因此NHibernate首先已经做了一些反射魔法来填充这些字段

但是有一个有10个参数的ctor感觉真的很糟糕。。(对于工厂方法也是如此)

有什么建议吗

你好,丹尼尔

你可能想试试

再加上一点反射,爱和领域变得非常可测试:

namespace Unit{
  using System;
  using System.Linq.Expressions;
  public static class ObjectExtensions{
    public static T Set<T,TProp>(this T o,
      Expression<Func<T,TProp>> field,TProp value){

      var fn=((MemberExpression)field.Body).Member.Name;
      o.GetType().GetProperty(fn).SetValue(o,value,null);
      return o;
    }
  }
}
你至少应该试着把那些“大屁股”的物体分成更小的。尝试建立一个层次结构(只需确保它符合普遍存在的语言)。

在经典(非CQRS)DDD中,将所有数据分解为值对象是一个很好的做法,这样您的实体就可以简化为其主要功能:维护身份

在您的示例中,客户应引用一个Address ValueObject,并具有一个ChengeAddress方法,该方法应简单到:

public void ChangeAddress(Address address)
{
   //Consistency rules are here
   _address = address;
}
尝试将尽可能多的逻辑从实体移动到值对象。它们本质上更易于测试,因为好值对象较小且不可变。您可以使用构造函数在给定状态下实例化VO并执行它(通常通过调用返回另一个已转换VO实例的方法)


最后但并非最不重要的一点是,根据我的经验,我可以说,如果测试域模型需要额外的基础设施(如反射或任何其他工具),那么您就错了(引入了不必要的耦合)。

我确实尝试将对象变小。现在测试中的工厂方法帮助很大。但是客户仍然需要有大量的信息,比如:姓名(名字、姓氏、头衔……)、地址(4个字段)、生日。。还有很多其他特定于应用程序的东西。。但感谢您将AutoFixtureExtract address指定为CustomerAddress。将减少3个字段。:)如果您需要传递数据,那么您需要传递数据o深嵌套值对象的替代方案是什么?你怎么能替换它们?我得到了18张excel表格,其中几乎所有的数据都是不可变的。关于不可变性的好观点:)为什么这在CQRS系统中有所不同?据我所知,即使是在普通的域模型中,我也可以通过记录所有调用域模型的命令来使用事件源
public void ChangeAddress(Address address)
{
   //Consistency rules are here
   _address = address;
}