2009-10-19 14 views
7

Quiero pedir algunos consejos sobre cómo evitar la escritura de objetos que son meros contenedores de datos.DDD - Agregar raíces y crear objetos de comportamiento

Considere lo siguiente Raíz Agregada:

public class Post : IAggregateRoot 
{ 
    List<Comment> Comments {get; set;} 
} 

Dadas las pinciples que rigen el trabajo raíces forma agregada, que es válida para llamar al código como este?

new Post().Comments.Add(New Comment("stuff")); 

¿O es esta la manera correcta?

public class Post : IAggregateRoot 
{ 
     List<Comment> Comments {get; private set;} 
     public void AddComment(string message) 
     { 
     Comments.Add(new Comment(message)); 
     } 
} 

Y se llama así:

new Post().AddComment("stuff"); 

Es esto lo Eric Evan significa Roots agregados siendo atómica?

Si este es el caso, ¿significa que las entidades no tienen entidades públicas, pero en su lugar tienen métodos de apoyo (AddThis, RemoveThat)? ¿Es así como creas objetos con un comportamiento rico?

+0

Ambos probablemente sean incorrectos a menos que tengas una razón válida para agrupar 'Post' y' Comments' juntos. ¿Qué invariantes comerciales está tratando de proteger con su gran agregado de clúster? Si no hay, entonces 'Comment' debe ser su propia raíz agregada. – plalx

Respuesta

5

Tiene el concepto de raíces agregadas correctas, pero sus dos opciones son realmente acerca de la implementación, y ambas son válidas.

Opción 1

  • Pros: Su interfaz entidad permanece bastante limpio.

  • Contras: El método Add necesita lógica para cable hasta la relación entre el Post y la Comment (pensar NHibernate). Puede crear una colección fuertemente tipada y anular el método Agregar o puede resucitar eventos al manejador Post a .

Opción 2

  • Pros: Los Add/Remove métodos proporcionan un lugar conveniente para la lógica de cableado.

  • Contras: A medida que crece el número de propiedades de recopilación, es posible que tenga una explosión de métodos Add/Remove. Además, las colecciones expuestas deben ser ReadOnly, para garantizar que Comments siempre se agreguen o eliminen utilizando los métodos especiales.

Mi preferencia es la Opción 1: utilizo colecciones genéricas que generan eventos. En mi humilde opinión, se siente más natural, y es más fácil para otros desarrolladores codificar en contra. Aunque otros en SO han expresado lo contrario.

Cuando hablamos de comportamiento, estamos hablando acerca de cómo adjuntar lógica a la Entidad. P.ej.si desea detener el agregado de Comments después de 5 días, le preguntará Post si es válido agregar Comment, y Post contendrá la lógica para realizar el control.

3

Iría con la segunda opción.

Primero me gusta mostrar colecciones como IEnumerable. De esta forma, no es posible manipular esa lista tan fácilmente y está protegida contra el comportamiento no deseado. Regularmente controlo añadiendo y eliminando el método que si el objeto contiene en la lista o no.

En segundo lugar encapsulado y puedo agregar un poco de lógica después.

Finalmente, puede hacer que el método de encadenamiento con ese método volviendo hacia atrás en sí:

var post = new Post() 
    .AddComment("My First comment") 
    .AddComment("My Second comment") 
    .Publish(); 

Si el método ADDX es mucho hinchazón de su entidad, entonces es posible hacerlo con sobrecarga:

var post = new Post() 
    .Add(new Comment("My First comment")) 
    .Add(new Comment("My Second comment")) 
    .Publish();