Domain driven design DDD中的值对象-为什么不可变?
我不明白为什么DDD中的值对象应该是不可变的,也不明白这是如何容易做到的。(我的重点是C#和实体框架,如果这很重要的话。)Domain driven design DDD中的值对象-为什么不可变?,domain-driven-design,value-objects,Domain Driven Design,Value Objects,我不明白为什么DDD中的值对象应该是不可变的,也不明白这是如何容易做到的。(我的重点是C#和实体框架,如果这很重要的话。) 例如,让我们考虑经典地址值对象。如果您需要将“123 Main St”更改为“123 MainStreet”,为什么我需要构建一个全新的对象,而不是说myCustomer.Address.AddressLine1=“123 Main Street”?(即使实体框架支持结构,这仍然是一个问题,不是吗?) 我理解(我认为)值对象没有标识并且是域对象的一部分,但是有人能解释为什么
例如,让我们考虑经典地址值对象。如果您需要将“123 Main St”更改为“123 MainStreet”,为什么我需要构建一个全新的对象,而不是说myCustomer.Address.AddressLine1=“123 Main Street”?(即使实体框架支持结构,这仍然是一个问题,不是吗?)
我理解(我认为)值对象没有标识并且是域对象的一部分,但是有人能解释为什么不变性是一件好事吗编辑:我在这里的最后一个问题应该是“有人能解释为什么不变性是应用于值对象的一件好事吗”?“很抱歉造成混淆
编辑:对Clarify来说,我不是在问CLR值类型(相对于引用类型)。我问的是价值对象的更高层次的DDD概念
例如,以下是一种为实体框架实现不可变值类型的黑客方法:。基本上,他只是让所有二传球员都成为私人球员。为什么要费心这么做呢?这可能不是完整的答案。我只是回答你关于不变性的好处的问题
6
是不可变的,因为6
的身份是由它所代表的东西决定的,即某事物的六个状态。您无法更改6
表示的内容。这是价值对象的基本概念。它们的价值由它们的状态决定。然而,一个实体不是由其国家决定的。客户
可以更改他们的姓氏或地址,但仍然是相同的客户
。这就是为什么值对象应该是不可变的。他们的国家决定了他们的身份;如果他们的状态改变,他们的身份也应该改变。忽略所有关于线程安全等的疯狂答案,这与DDD无关。
(我还没有看到线程安全的O/R映射器或其他DDD友好的dal)
想象一个权重值对象。
假设我们有一个KG值的对象
样本(为清晰起见编辑):
现在,如果我们这样做会发生什么:
jimmy.Weight.Value = 82;
如果我们仍然使用相同的对象引用,这也会改变joe的权重。
请注意,我们为joe和jimmy分配了一个代表75kg的对象。
当jimmy增加体重时,改变的不是kg75对象,而是jimmy的体重,因此,我们应该创建一个代表82公斤的新对象
但是,如果我们有一个新的会议,并加载乔和吉米在一个干净的UoW
var joe = context.People.Where(p => p.Name = "joe").First();
var jimmy = context.People.Where(p => p.Name = "jimmy").First();
jimmy.Weight.Value = 82;
那么会发生什么?好吧,因为在你的例子中EF4会加载joe和jimmy以及他们的重量,而没有任何标识,所以我们会得到两个不同的重量对象,当我们改变jimmy的重量时,joe的重量仍然和以前一样
因此,对于同一代码,我们将有两种不同的行为。
如果对象引用仍然相同,那么joe和jimmy都将获得新的权重。
如果joe和jimmy装载在一个干净的uow中,则只有一个会受到更改的影响
这在国际海事组织是不一致的
通过使用不可变VO,在这两种情况下,您将获得相同的行为,并且在构建对象图时,您仍然可以重用对象引用以获得更小的内存占用。我参加聚会已经很晚了,但我自己一直在想这个问题。(如有任何意见,我们将不胜感激。) 我认为这里没有明确引用,但我认为埃文斯提到的不变性主要是在分享的背景下: 为了安全地共享对象,它必须是不可变的:它是 除非完全替换,否则无法更改。(埃文斯p100) 埃文的书中还有一个边栏,叫做“地址是一个价值对象吗?谁在问?” 如果室友们都打电话订购电气服务(如果两个顾客的地址相同),公司会这样做 我们需要认识到这一点。[所以]地址是一个实体。(埃文斯第98页) 在您给出的示例中,假设客户的家庭和公司地址都是Main Street 123。当你做出你描述的更正时,两个地址都会改变吗?如果是这样,如果我读对了埃文斯,听起来你真的有一个实体 举一个不同的例子,假设我们有一个对象来表示客户的全名:
public class FullName
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Customer
{
public FullName Name { get; set; }
}
如果没有值对象,以下操作将失败:
[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);
}
就优势而言,一般而言,有些优势是在。值得注意的是,您只需在创建时验证VO。如果您这样做,那么您知道它总是有效的。值对象需要是不可变的 在许多情况下,不变的对象确实使生活更简单。。。它们可以使并发编程方式更加安全和干净
让我们考虑值对象是可变的。< /P>
class Name{
string firstName,middleName,lastName
....
setters/getters
}
假设你的原名是理查德·托马斯·库克
现在让我们假设你只改变了
class Name{
string firstName,middleName,lastName
....
setters/getters
}
public class Money
{
protected readonly decimal Value;
public Money(decimal value)
{
Value = value;
}
public Money Add(Money money)
{
return new Money(Value + money.Value);
}
// ...
// Equality (operators, Equals etc) overrides (here or in a Value Object Base class).
// For example:
public override bool Equals(object obj)
{
return Equals(obj as Money);
}
public bool Equals(Money money)
{
if (money == null) return false;
return money.Value == Value;
}
}