Hob*_*bes 33 domain-driven-design value-objects
我不明白为什么DDD中的值对象应该是不可变的,我也不知道如何轻松完成.(如果重要的话,我专注于C#和实体框架.)
例如,让我们考虑经典的Address值对象.如果你需要改变"解放路123号"到"123主街 ",我为什么要需要构建一个全新的对象,而不是说myCustomer.Address.AddressLine1 ="123大街"的?(即使实体框架支持结构,这仍然是一个问题,不是吗?)
我理解(我认为)价值对象没有身份并且是域对象的一部分的想法,但有人可以解释为什么不变性是一件好事吗?
编辑:我在这里的最后一个问题应该是"有人可以解释为什么不变性是适用于价值对象的好东西吗?" 对困惑感到抱歉!
编辑:为了clairfy,我不是在询问CLR值类型(与引用类型相比).我问的是价值对象的更高级DDD概念.
例如,这里是实现不可变的值类型实体框架劈上下的方式: http://rogeralsing.com/2009/05/21/entity-framework-4-immutable-value-objects.基本上,他只是让所有的安装者都私密.为什么要经历这样做的麻烦?
Rog*_*son 43
忽略关于线程安全等的所有疯狂的答案,这与DDD无关.(我还没有看到线程安全的O/R映射器或其他DDD友好dal)
想象一下权重的价值对象.假设我们有一个KG值对象.
样本(为清晰起见编辑):
var kg75 = new Weight(75);
joe.Weight = kg75;
jimmy.Weight = kg75;
Run Code Online (Sandbox Code Playgroud)
现在如果我们这样做会发生什么:
jimmy.Weight.Value = 82;
Run Code Online (Sandbox Code Playgroud)
如果我们仍然使用相同的对象引用,那也会改变joe的权重.请注意,我们为joe和jimmy分配了一个代表75千克的对象.当jimmy增加重量时,不是kg75对象已经改变,它是jimmys重量已经改变,因此,我们应该创建一个代表82 kg的新对象.
但是如果我们有一个新的会话并在一个干净的UoW中加载joe和jimmy呢?
var joe = context.People.Where(p => p.Name = "joe").First();
var jimmy = context.People.Where(p => p.Name = "jimmy").First();
jimmy.Weight.Value = 82;
Run Code Online (Sandbox Code Playgroud)
那会发生什么?好吧,因为在你的情况下EF4会加载joe和jimmy以及它们的重量而没有任何标识,我们会得到两个不同的重量对象,当我们改变jimmys重量时,joe仍然会像以前一样重量.
因此,对于相同的代码,我们会有两种不同的行为.如果对象引用仍然相同,则joe和jimmy都会获得新的权重.如果joe和jimmy被加载到一个干净的哇,只有其中一个会受到更改的影响.
那将是非常无情的imo.
通过使用不可变的VO,您可以在两种情况下获得相同的行为,并且在构造对象图时,您仍然可以在较小的内存占用空间中重用对象引用.
jas*_*son 33
为什么6不可变?
理解这一点,你就会理解为什么Value Objects应该是不可变的.
编辑:我现在将对话框提到这个答案.
6是不可改变的,因为它6的身份是由它所代表的东西决定的,即有六种东西的状态.你不能改变它6代表那个.现在,这是Value Objects的基本概念.他们的价值取决于他们的国家.但是,实体不是由其州决定的.A Customer可以更改姓氏或地址,但仍然相同Customer.这就是Value Objects应该是不可变的原因.他们的国家决定他们的身份 如果他们的州改变,他们的身份应该改变.
Dav*_*vid 10
我参加派对的时间已经很晚了,但我自己一直在想这个问题.(感谢任何评论.)
我认为这里没有明确引用,但我认为埃文斯对不变性的提及主要是在分享的背景下:
为了安全地共享对象,它必须是不可变的:除非完全替换,否则不能更改它.(埃文斯p100)
在Evan的书中还有一个侧栏,名为"Is Is a value a Value Object?谁在问?".
如果每个室友都要求订购电气服务[即如果两个客户拥有相同的地址],公司就需要实现它.[所以]地址是一个实体.(埃文斯p98)
在您给出的示例中,假设客户的家庭和公司地址均为123 Main Street.当您进行描述校正时,两个地址都会发生变化吗?如果是这样,如果我正确地阅读埃文斯,听起来你真的有一个实体.
举一个不同的例子,假设我们有一个对象来表示客户的全名:
public class FullName
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Customer
{
public FullName Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果没有值对象,以下内容将失败:
[Test]
public void SomeTest() {
var fullname = new FullName { FirstName = "Alice", LastName = "Jones" };
var customer1 = new Customer { Name = fullname };
var customer2 = new Customer { Name = fullname };
// Customer 1 gets married.
customer1.Name.LastName = "Smith";
// Presumably Customer 2 shouldn't get their name changed.
// However the following will fail.
Assert.AreEqual("Jones", customer2.Name.LastName);
}
Run Code Online (Sandbox Code Playgroud)
在优势方面,有些是在In DDD中获得的,有价值对象的实际优势是什么?.值得注意的是,您只需要在创建时验证VO.如果你这样做,那么你知道它总是有效的.
这可能不是完整的答案.我只回答你关于不变性的优点的问题.
这是 Martin Fowler关于为什么值对象应该是不可变的一个例子.
好吧,虽然没有强制要求VO成为不可变的(即使DDD书并没有说它们必须是不可变的),DDD中使其成为VO的主要想法似乎不是要处理生命周期的复杂性,如实体的那个.在这里查看更多详情.