2012-03-27 3 views
1

Ich habe ein Aggregat, das die Entitäten A, AbstractElement, X, Y und Z enthält. Die Root-Entität ist A, die auch eine Liste von AbstractElement enthält. Die Entitäten X, Y und Z erben von AbstractElement. Ich brauche die Möglichkeit Instanzen von X, Y und Z zu einer Instanz von A hinzuzufügen. Ein Ansatz besteht darin, ein Verfahren für jeden Typ zu verwenden, d. H. addX, addY und addZ. Diese Methoden würden als Argumente die Werte annehmen, die erforderlich sind, um Instanzen von X, Y und Z zu erstellen. Aber jedes Mal, wenn ich einen neuen Typ hinzufüge, der von AbstractElement erbt, muss ich die Entität A ändern, also denke ich, dass es nicht die beste Lösung ist.Aggregieren Stamm und Instanzen erstellen von untergeordneten Entitäten

Ein anderer Ansatz besteht darin, eine abstrakte Add-Methode addAbstractElement für das Hinzufügen von AbstractElement Instanzen zu verwenden. Aber in diesem Fall würde das Verfahren als Argument eine Instanz von AbstractElement nehmen. Da diese Methode von Entitäten aufgerufen wird, die sich außerhalb des Aggregats nach den DDD-Regeln/-Empfehlungen befinden, sind diese externen Entitäten berechtigt, Instanzen von AbstractElement zu erstellen? Ich habe im Buch von Eric Evans gelesen, dass externe Entitäten nicht berechtigt sind, Referenzen auf Entitäten eines Aggregats außer der Wurzel zu halten.

Was ist die beste Vorgehensweise für diese Art von Problem?

Dank

Antwort

5

Von Evan Buch, Seite 139:

Bedeutung „wenn Sie Elemente innerhalb eines bereits existierenden AGGREGATE hinzuzufügen benötigen, können Sie eine Factory-Methode auf der Wurzel des Aggregates schaffen“ , sollten Sie eine Factory-Methode auf dem Stamm (A) erstellen, die die Details des AbstractElement erhalten wird. Diese Methode erstellt das AbstractElement (X/Y/Z) gemäß einem Entscheidungsparameter und fügt es zu seiner internen Sammlung von AbstractElements hinzu. Am Ende gibt diese Methode die ID des neuen Elements zurück.

Mit besten Grüßen,

Itzik Saban

+0

In meinem Fall unterscheiden sich die Details von einer Entität zur anderen. Um eine Instanz von X zu erstellen, brauche ich eine Zeichenfolge. Um eine Instanz von Y zu erstellen, brauche ich zwei Strings ... Wie funktioniert es in diesem Fall? Wie kann ich nur eine Methode verwenden? –

+0

Sie sind nicht auf DDD beschränkt, um nur eine Methode zu erstellen - Sie können 3 verschiedene Methoden erstellen, solange sie als FABRIKMETHODEN fungieren. – ItzikSaban

+0

Aber in diesem Fall existiert das Problem, das ich in meiner Frage aufgeworfen habe, immer noch. Ich müsste jedes Mal, wenn ein neuer Typ hinzugefügt wird, eine neue Factory-Methode hinzufügen. –

2

Ein paar Anmerkungen. Wie der vorherige Beantworter sagte, ist es eine gute Methode, eine Factory-Methode zu verwenden. Wenn Sie es vermeiden können, erstellen Sie niemals Objekte aus heiterem Himmel. Normalerweise ist es ein ziemlich großer Geruch und eine verpasste Chance, mehr aus Ihrer Domain zu machen.

Ich schrieb ein kleines Beispiel, um dies zu veranschaulichen. Video ist in diesem Fall die aggregierte Wurzel. Innerhalb der Grenzen des Aggregats befinden sich das Videoobjekt und die zugehörigen Kommentare. Kommentare können anonym sein oder von einem bekannten Benutzer geschrieben worden sein (um das Beispiel zu vereinfachen, habe ich den Benutzer mit einem Benutzernamen dargestellt, aber offensichtlich haben Sie in einer echten Anwendung so etwas wie eine UserId). Hier

ist der Code:

public class Video { 
    private List<Comment> comments; 

    void addComment(final Comment.Builder builder) { 
     this.comments.add(builder.forVideo(this).build()); 
     // ... 
    } 
} 


abstract public class Comment { 
    private String username; 
    private Video video; 

    public static public class Builder { 
     pubic Builder anonymous() { 
      this.username = null; 
      return this; 
     } 

     pubic Builder fromUser(final String username) { 
      this.username = username; 
      return this; 
     } 

     pubic Builder withMessage(final String message) { 
      this.message = message; 
      return this; 
     } 

     public Builder forVideo(final Video video) { 
      this.video = video; 
      return this; 
     } 

     pubic Comment build() { 
      if (username == null) { 
       return new AnonymousComment(message); 
      } else { 
       return new UserComment(username, message); 
      } 
     } 
    } 
} 

public class AnonymousComment extends Comment { 
    // ... 
} 

static public class UserComment extends Comment { 
    // ...  
} 

Eine Sache auch zu bedenken, ist, dass aggregierten Grenzen Objekte enthalten und keine Klassen. Daher ist es sehr gut möglich, dass bestimmte Klassen (meist Wertobjekte, aber auch Entitäten) in vielen Aggregaten dargestellt werden können.