2009-10-19 12 views
7

Chcę poprosić o poradę, jak unikać pisania obiektów, które są zwykłymi kontenerami danych.DDD - Korzenie agregatów i tworzenie obiektów behawioralnych

Rozważmy następujący Agregat root:

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

Biorąc pod uwagę pinciples które regulują sposób zagregowany korzenie pracy, jest to ważne, aby zadzwonić powyższy kod takiego?

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

Czy jest to właściwa droga?

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

i nazwał tak:

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

Czy to oznacza, co Eric Evan przez Zbiorczy Roots jest atomowy?

Jeśli tak jest, czy oznacza to, że jednostki nie mają żadnych publicznych ustawiaczy, ale zamiast tego mają metody wspomagające (AddThis, RemoveThat)? Czy w ten sposób tworzysz obiekty o bogatym zachowaniu?

+0

Oba są prawdopodobnie błędne, chyba że masz uzasadniony powód, aby zgrupować razem 'Post' i' Komentarze'. Jakie niezmienniki biznesowe próbujesz chronić za pomocą dużego agregatu klastrów? Jeśli tak nie jest, to 'Comment' powinien być własnym agregowanym rootem. – plalx

Odpowiedz

5

Masz koncepcję zagregowanych korzeni, ale twoje dwie opcje dotyczą implementacji - i oba są prawidłowe.

Wariant 1

  • Plusy: interfejs jednostka pozostaje dość czyste.

  • Wady: Metoda Add potrzebuje logiki drutu się relacji między Post i Comment (myślę NHibernate). Można utworzyć kolekcję silnie typograficzną i zastąpić metodę Dodaj, lub możesz podnieść zdarzenia z powrotem do obsługi .

Wariant 2

  • Plusy: Add/Remove metody zapewniają wygodne miejsce dla logiki okablowania.

  • Minusy: Ponieważ liczba właściwości kolekcji rośnie, możliwe jest wystąpienie eksplozji metod: Add/Remove. Ponadto eksponowane kolekcje muszą być w ReadOnly, aby zapewnić, że Comments są zawsze dodawane/usuwane przy użyciu specjalnych metod.

Moje preferencje to Opcja 1 - Używam generycznych kolekcji, które podnoszą zdarzenia. IMHO, to wydaje się bardziej naturalne i łatwiej jest innym programistom kodować. Chociaż inni na SO wyrazili inaczej.

Kiedy mówimy o zachowanie, mówimy o dołączenie logikę Podmiotowi. Na przykład.Jeśli chcesz zatrzymać dodawanie Comments po 5 dniach, możesz zapytać o numer Post, jeśli dodanie Comment jest prawidłowe, a Post zawiera logikę do sprawdzenia.

3

Wybrałbym drugą opcję.

Po pierwsze lubię pokazywać kolekcje jako IEnumerable. W ten sposób nie można tak łatwo manipulować tą listą i jest ona chroniona przed niechcianym zachowaniem. Regularnie sprawdzam metodę dodawania i usuwania, jeśli obiekt zawiera na liście, czy nie.

Po drugie jest hermetyzowany i mogę później dodać trochę logiki.

Wreszcie można dokonać metodą łańcuchowy z tej metody przez powrocie sama:

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

Jeśli metoda AddX jest znacznie wzdęcia swój podmiot, to można zrobić to z przeciążenia:

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