2009-10-19 6 views
7

Je souhaite demander conseil sur la manière d'éviter d'écrire des objets qui sont de simples conteneurs de données.DDD - Agrégation de racines et création d'objets comportementaux

Tenir compte de la racine globale suivante:

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

Compte tenu des pinciples qui régissent le fonctionnement des racines ensemble, est-il valide pour appeler le code ci-dessus comme ça?

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

Ou est-ce la bonne façon?

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

Et appelé comme ceci:

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

Est-ce que Eric Evan signifie par Aggregate Roots étant atomique?

Si tel est le cas, cela signifie-t-il que les Entités n'ont pas de setters publics, mais ont des méthodes de support (AddThis, RemoveThat)? Est-ce ainsi que vous créez des objets avec un comportement riche?

+0

Les deux sont probablement faux, sauf si vous avez une raison valable de regrouper 'Post' et' Comments' ensemble. Quels sont les invariants professionnels que vous essayez de protéger avec votre agrégat de cluster volumineux? S'il n'y a pas alors 'Comment' devrait être sa propre racine agrégée. – plalx

Répondre

5

Vous avez le concept des racines agrégées correctes, mais vos deux options concernent vraiment l'implémentation - et les deux sont valides.

Option 1

  • Avantages: Votre interface entité reste tout à fait propre.

  • Cons: La logique doit Add procédé à fil jusqu'à la relation entre la Post et la Comment (penser NHibernate). Vous pouvez créer une collection fortement typée et remplacer la méthode Add, ou vous pouvez lever des événements vers la poignée Post vers .

Option 2

  • Avantages: Les méthodes Add/Remove offrent un endroit pratique pour la logique de câblage. Inconvénients: À mesure que le nombre de propriétés de collection augmente, vous pouvez avoir une explosion de Add/Remove méthodes. En outre, les collections exposées doivent être ReadOnly, pour garantir que Comments sont toujours ajoutées/supprimées à l'aide des méthodes spéciales.

Ma préférence est Option 1 - J'utilise des collections génériques qui déclenchent des événements. À mon humble avis, il se sent plus naturel, et il est plus facile pour les autres développeurs de code contre. Bien que d'autres sur SO ont exprimé autrement.

Quand on parle de comportement, nous parlons de fixation logique à l'entité. Par exemple.Si vous souhaitez arrêter l'ajout de Comments après 5 jours, vous devez demander Post si l'ajout d'un Comment est valide et si le Post contient la logique pour effectuer la vérification.

3

J'irais avec la deuxième option.

Tout d'abord j'aime montrer des collections comme IEnumerable. De cette façon, il n'est pas possible de manipuler cette liste si facilement et elle est protégée contre les comportements indésirables. Régulièrement je vérifie en ajoutant et en supprimant la méthode que si l'objet contient dans la liste ou pas.

Deuxièmement, il encapsulé et je peux ajouter une logique après.

Enfin, vous pouvez faire méthode enchaînant avec cette méthode en revenant lui-même:

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

Si la méthode ADDX est beaucoup ballonnements votre entité, alors il possible de le faire avec la surcharge:

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