domain driven design - significado - Objetos de valor en DDD-¿Por qué inmutable?
domain driven design pdf (6)
¿Por qué es 6 inmutable?
Comprenda eso y comprenderá por qué Value Objects debe ser inmutable.
Editar: elevaré nuestro diálogo a esta respuesta ahora.
6
es inmutable porque la identidad de 6
está determinada por lo que representa, es decir, el estado de tener seis de algo. No puedes cambiar que 6
representa eso. Ahora, este es el concepto fundamental de los objetos de valor. Su valor está determinado por su estado. Una entidad, sin embargo, no está determinada por su estado. Un Customer
puede cambiar su apellido o su dirección y seguir siendo el mismo Customer
. Es por eso que Value Objects debe ser inmutable. Su estado determina su identidad; si sus estados cambian, su identidad debería cambiar.
No entiendo por qué los objetos de valor en DDD deben ser inmutables, ni veo cómo esto se hace fácilmente. (Me estoy enfocando en C # y Entity Framework, si eso importa).
Por ejemplo, consideremos el clásico objeto de valor de Dirección. Si necesita cambiar "123 Main St" a "123 Main Street ", ¿por qué debería tener que construir un objeto completamente nuevo en lugar de decir myCustomer.Address.AddressLine1 = "123 Main Street"? (Incluso si Entity Framework soporta estructuras, esto todavía sería un problema, ¿no?)
Entiendo (creo) la idea de que los objetos de valor no tienen una identidad y son parte de un objeto de dominio, pero ¿alguien puede explicar por qué la inmutabilidad es algo bueno?
EDITAR : Mi última pregunta aquí debería ser "¿Alguien puede explicar por qué la inmutabilidad es una buena cosa tal como se aplica a los objetos de valor ?" ¡Perdón por la confusion!
EDITAR : Clairfy, no estoy preguntando sobre los tipos de valores CLR (vs tipos de referencia). Pregunto sobre el concepto DDD de nivel superior de Value Objects.
Por ejemplo, aquí hay una forma de hack-ish para implementar tipos de valores inmutables para Entity Framework: http://rogeralsing.com/2009/05/21/entity-framework-4-immutable-value-objects . Básicamente, solo hace que todos los setters sean privados. ¿Por qué tomarse la molestia de hacer esto?
Esta podría no ser la respuesta completa. Solo estoy respondiendo tu pregunta sobre las ventajas de la Inmutabilidad.
- Porque los objetos inmutables son seguros para subprocesos. Como no pueden cambiar el estado, no pueden corromperse por la interferencia de hilo o observarse en un estado incoherente.
- Las referencias a los objetos inmutables pueden compartirse fácilmente o almacenarse en caché sin tener que copiarlos o clonarlos, ya que su estado no se puede cambiar después de la construcción.
- Para obtener más ventajas de inmutabilidad, mira aquí (respuesta de LBushkin). ¿Cuál es la ventaja de que una cadena sea inmutable?
c2.com/cgi/wiki?ValueObjectsShouldBeImmutable de Martin Fowler sobre por qué los objetos de valor deben ser Inmutables.
De acuerdo, aunque no es obligatorio hacer VO como inmutable (incluso el libro DDD no dice que tienen que ser inmutables), la idea principal, en DDD, hacer que sea un VO parece ser no tratar con complejidades del ciclo de vida como el de una Entidad. Mire aquí para más detalles .
Esto se ha preguntado hace mucho tiempo, pero he decidido dar una respuesta con un ejemplo que encuentro sencillo y muy simple de recordar. Además, SO funciona como referencia para muchos desarrolladores y creo que cualquiera que se encuentre con esta pregunta podría beneficiarse.
Debido a que están definidos por sus atributos, los objetos de valor se tratan como inmutables .
Un buen ejemplo de un objeto de valor es dinero. No importa que no pueda distinguir entre los mismos cinco billetes de un dólar en su bolsillo. No le importa la identidad de la moneda, solo sobre su valor y lo que representa. Si alguien intercambiara un billete de cinco dólares por uno que tenga en su billetera, no cambiaría el hecho de que todavía tiene cinco dólares.
Entonces, por ejemplo, en C #, defines dinero como un objeto de valor inmutable:
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;
}
}
Ignora todas las respuestas alocadas sobre seguridad de subprocesos, etc., que no tienen nada que ver con DDD. (Aún no he visto un mapeador O / R seguro para subprocesos u otro dal compatible con DDD)
Imagine un objeto de valor para pesos. digamos que tenemos un objeto de valor KG.
muestra (editada para mayor claridad):
var kg75 = new Weight(75);
joe.Weight = kg75;
jimmy.Weight = kg75;
Ahora, ¿qué pasaría si lo hacemos?
jimmy.Weight.Value = 82;
Eso cambiaría el peso de Joe también, si todavía estamos usando las mismas referencias de objeto que es. Tenga en cuenta que asignamos un objeto que representa 75kg tanto a joe como a jimmy. Cuando Jimmy aumenta de peso, no es el objeto kg75 el que ha cambiado, es el peso de Jim el que ha cambiado, por lo tanto, deberíamos crear un nuevo objeto que represente 82 kg.
Pero, ¿y si tenemos una sesión nueva y cargamos tanto a Joe como a Jimmy en una UoW limpia?
var joe = context.People.Where(p => p.Name = "joe").First();
var jimmy = context.People.Where(p => p.Name = "jimmy").First();
jimmy.Weight.Value = 82;
¿Qué pasaría entonces? bueno, como EF4 en tu caso cargaría joe y jimmy y sus pesos sin ninguna identidad, obtendríamos dos objetos de peso diferentes y cuando cambiemos el peso de jimmys, joe pesaría igual que antes.
Entonces tendríamos dos comportamientos diferentes para el mismo código. si las referencias de obejct siguen siendo las mismas, entonces tanto joe como jimmy tendrían un nuevo peso. si Joe y Jimmy están cargados en un árbol limpio, solo uno de ellos se vería afectado por el cambio.
Y eso sería bastante incoherente.
Al usar VO inmutables, obtendría el mismo comportamiento en ambos casos y aún podría reutilizar referencias de objetos para una huella de memoria menor al construir gráficos de objetos.
Llego muy tarde a la fiesta, pero me he estado preguntando sobre esto yo mismo. (Agradecería cualquier comentario)
No creo que se haya citado explícitamente aquí, pero creo que las referencias de Evans a la inmutabilidad se daban principalmente en el contexto del intercambio:
para que un objeto se comparta de manera segura , debe ser inmutable: no se puede cambiar excepto por reemplazo completo. (Evans p100)
También hay una barra lateral en el libro de Evan titulada "¿Es la dirección un objeto de valor? ¿Quién pregunta?".
Si cada uno de los compañeros de habitación llamara para solicitar el servicio eléctrico [es decir, si dos clientes tuvieran la misma dirección], la empresa tendría que darse cuenta. [Entonces] La dirección es una entidad. (Evans p98)
En el ejemplo que proporcionó, suponga que la dirección de la casa y el negocio del cliente eran ambos 123 Main Street. Cuando realiza la corrección que describe, ¿cambiarían ambas direcciones? Si es así, y si leo correctamente a Evans, parece que realmente tienes una Entidad.
Tomando un ejemplo diferente, supongamos que tenemos un objeto para representar el nombre completo de un cliente:
public class FullName
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Customer
{
public FullName Name { get; set; }
}
Sin un objeto de valor, el siguiente error:
[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);
}
En términos de ventajas en general, algunos se recogen en In DDD, ¿cuáles son las ventajas reales de los objetos de valor? . Notablemente, solo tiene que validar un VO en la creación. Si haces eso, entonces sabes que siempre es válido.
Los objetos de valor deben ser inmutables.
Los objetos inmutables de hecho simplifican la vida en muchos casos. ... Y pueden hacer que la programación simultánea sea más segura y más limpia para obtener más información
Consideremos que el objeto de valor es mutable.
class Name{
string firstName,middleName,lastName
....
setters/getters
}
Digamos que su nombre original era Richard Thomas Cook
Ahora digamos que solo cambia el primer Nombre (por Martin) y el Apellido (por el Enlace). Si no es un objeto inmutable, usará los métodos para mutar el estado uno por uno. Las posibilidades de tener un nombre como Martin Thomas Cook en ese estado Agregado antes del nombre final de Martin Thomas Bond nunca son aceptables (también da una idea equivocada a quien mira el código más tarde, lo que lleva a un efecto de dominó indeseable en el diseño posterior).
Los objetos de valor mutable explícitamente tienen que imponer restricciones de integridad para los cambios dados en 1 transacción, que se da gratuitamente en objetos inmutables. Por lo tanto, tiene sentido hacer que los objetos de valor sean inmutables.