值vs实体对象(域驱动devise)
我刚开始阅读DDD。 我无法完全理解实体与价值对象的概念。有人可以解释当一个价值对象被devise为一个实体对象时,系统可能面临的问题(可维护性,性能等)? 例子会很棒
归属于实体的本质区别在于本质上的差别,但对于价值对象来说并不重要。 例如,某人的名字是一个值对象。 客户实体可以由客户名称(值对象),列表<Order> OrderHistory(实体列表)和可能的默认地址(通常是值对象)组成。 客户实体将有一个ID,每个订单将有一个ID,但一个名称不应该; 一般来说,无论如何,在对象模型中,地址的标识可能并不重要。
价值对象通常可以表示为不可变对象; 改变一个值对象的一个属性本质上会破坏旧对象并创build一个新对象,因为你不像内容那样关心身份。 正确地说,只要对象的属性与另一个实例的属性相同,Name上的Equals实例方法就会返回“true”。
但是,改变客户这样一个实体的某个属性并不会破坏客户, 客户实体通常是可变的。 身份保持不变(至less一次持久对象)。
您可能会创build价值对象而不意识到它; 无论何时你通过创build一个细粒度的类来表示一个实体的某个方面,你都有一个值对象。 例如,对有效值有一些限制但由较简单的数据types组成的IPAddress类将是一个值对象。 一个EmailAddress可以是一个string,也可以是一个拥有自己行为的值对象。
甚至在数据库中具有身份的项目在对象模型中都不具有身份。 但最简单的情况是一些有意义的组合。 你可能不想拥有Customer.FirstName,Customer.LastName,Customer.MiddleInitial和Customer.Title,当你可以把它们合并为Customer.Name; 在您考虑持久性时,他们可能会在数据库中有多个字段,但您的对象模型并不在意。
任何由所有属性共同定义的对象都是一个值对象。 如果任何属性发生更改,则您有一个值对象的新实例。 这就是值对象被定义为不可变的原因。
如果对象没有被其所有属性完全定义,那么就有属性的一个子集组成对象的身份。 剩下的属性可以改变而不用重新定义对象。 这种对象不能被定义为不可变的。
作出区分的一个更简单的方法是将值对象视为永远不会改变的静态数据,将实体视为在您的应用程序中演变的数据。
我不知道以下是否正确,但我想说的是,在Address对象的情况下,我们希望将它用作Value Object而不是实体,因为对实体的更改将反映在所有链接的对象上一个人)。
以这种情况为例:你和别人一起住在你的房子里。 如果我们将使用实体的地址,我会争辩说,将有一个唯一的地址,所有的个人对象链接到。 如果一个人搬出去,你想更新他的地址。 如果您要更新地址实体的属性,则所有人都将拥有不同的地址。 在Value对象的情况下,我们将无法编辑Address(因为它是不可变的),我们将被迫为该Person提供一个新的地址。
这听起来正确吗? 我必须说,在阅读DDD书后,我仍然对这种差异感到困惑。
更进一步,这将如何在数据库中build模? 您是否将Address对象的所有属性作为Person表中的列,或者是否要创build一个单独的Address表还将具有唯一的标识符? 在后一种情况下,住在同一个房子里的人每个都有一个Address对象的不同实例,但除了它们的ID属性外,这些对象将是相同的。
地址可以是取决于业务stream程的实体或值对象。 地址对象可以是快递服务应用程序中的实体,但地址可以是其他应用程序中的值对象。 在快递申请身份事宜中作为地址对象
我在另一个线索问了这个问题,我想我还是很困惑。 我可能会将性能考虑与数据build模混为一谈。 在我们的编目应用程序中,客户不会更改,直到需要。 这听起来很愚蠢 – 但是客户数据的“读取”远远超过了“写入”,而且由于许多Web请求都在对象的“活动集合”上,我不想一次又一次地加载客户。 因此,我正在为Customer对象做出一个不可改变的道路 – 加载它,caching它,并且为想看到Customer的99%(multithreading)请求提供相同的服务。 然后,当一个顾客改变了一些东西,得到一个“编辑”来创build一个新顾客,并使旧顾客无效。
我担心的是,如果许multithreading看到相同的客户对象,并且它是可变的,那么当一个线程开始改变时,其他线程就会发生混乱。
我现在的问题是,1)这是合理的,2)如何最好的做到这一点,而不需要复制大量关于属性的代码。