2010-01-28 16 views
6

Mi chiedevo quale delle seguenti affermazioni sia considerata una best practice quando si tratta di relazioni parent parent.Progetto basato su domini - Modello di relazione figlio genitore - Modello di specifica

1) Il seguente esempio sembra essere una pratica comune, ma quando si crea un'istanza di un bambino, esso si troverà in uno stato non valido purché non venga aggiunto al genitore. Non potrebbe questo portare a problemi per quanto riguarda la convalida ecc

public class Parent 
{ 
    private ICollection<Child> children; 

    public ReadOnlyCollection Children { get; } 

    public void AddChild(Child child) 
    { 
     child.Parent = this; 
     children.Add(child); 
    } 
} 


public class Child 
{ 
    internal Parent Parent 
    { 
     get; 
     set; 
    } 

    public Child() 
    { 
    } 
} 

2) Il campione successivo sarebbe fare in modo che un bambino deve sempre essere legata al suo genitore.

public class Parent 
{ 
    private ICollection<Child> children; 

    public ReadOnlyCollection Children { get; } 

    public Child CreateChild() 
    { 
     var child = new Child(); 
     child.Parent = this; 
     children.Add(child); 
     return child; 
    } 
} 


public class Child 
{ 
    internal Parent Parent 
    { 
     get; 
     set; 
    } 

    internal Child() 
    { 
    } 
} 

3) Nell'ultimo esempio quel bambino si occupa della relazione alla sua madre stessa.

public class Parent 
{ 
    private ICollection<Child> children; 

    public ReadOnlyCollection Children { get; } 

    public void AddChild(Child child) 
    { 
     child.Parent = this; 
     children.Add(child); 
    } 
} 


public class Child 
{ 
    public Parent Parent 
    { 
     get; 
     set; 
    } 

    public Child(Parent parent) 
    { 
     this.Parent = parent; 
    } 
} 

Quale modello è considerato il migliore? Credo che il modello 2 potrebbe essere il migliore da allora un bambino non può mai esistere senza una relazione con il suo genitore. Ciò renderebbe più semplice, ad es. in sede di attuazione di un modello specifica che potrebbe fare cose come:

public class ChildSpecification 
{ 
    bool IsSatisfiedBy(Child child) 
    { 
     return child.Parent.Children.Where(someCondition).Count > 0; 
    } 
} 

La specifica di cui sopra può funzionare solo se un bambino ha un genitore.

Cosa ne pensi? Conosci modi migliori? Grazie in anticipo

risposta

0

Tendo ad usare l'opzione (1) - ha sempre funzionato bene per me. L'importante è non esporre la collezione di bambini al mondo esterno - il genitore dovrebbe essere in grado di mediare tutti gli accessi. Ma sono perfettamente felice che un bambino venga creato altrove, a me interessa solo quando viene aggiunto al genitore, e a questo punto può essere controllato per la validità ecc. Ecc.

Non capisco il tuo esempio di specifica: sembra che il tuo ChildSpecification restituisca true se qualsiasi dei figli del genitore ha qualche condizione come vera. Sicuramente IsSatisfiedBy (Figlio secondario) deve restituire true solo se il figlio specifico passato come parametro ha soddisfatto la condizione.

+0

Il modello di specifica riguarda un caso speciale che sto attualmente svolgendo in uno dei miei progetti. Un bambino ha un intervallo di date di validità, che non dovrebbe intersecarsi con altri intervalli di date di validità di qualsiasi altro bambino all'interno della raccolta secondaria. Lo considereresti una specifica per il genitore? – Chris

+0

Probabilmente lo implementerei come condizione di guardia nel metodo addChild() del Parent. Il genitore quindi non consentirebbe l'aggiunta per es. lanciando un'eccezione. Probabilmente non userò una specifica in questo caso. – alasdairg

+0

Ma ho bisogno di controllare anche quello sull'interfaccia utente. Quindi, quando viene lanciata un'eccezione, dovrei prenderlo. Anche questo non è molto elegante. Inoltre, il bello delle specifiche è che potrei usarlo in molti scenari diversi come 1.) all'interno del mio dominio oe 2.) all'interno di un'applicazione client per pre-validare la logica di business. O mi sbaglio? – Chris

5

Io sicuramente come il numero 2 suggerimento, ma credo che manca qualcosa di importante che si trova in 3, vale a dire che se un oggetto Child non può esistere senza un Parent si dovrebbe prendere un oggetto Parent nel suo costruttore. Inoltre, la proprietà Parent nella classe Child deve essere di sola lettura. Così si potrebbe finire con qualcosa di simile:

public class Parent 
{ 
    private ICollection<Child> children; 

    public ReadOnlyCollection Children { get; } 

    public Child CreateChild() 
    { 
     var child = new Child(this); 
     children.Add(child); 
     return child; 
    } 
} 


public class Child 
{ 
    internal Parent Parent 
    { 
     get; 
     private set; 
    } 

    internal Child(Parent parent) 
    { 
     this.Parent = parent; 
    } 
} 
+0

Lo farei anche io, se la specifica è che un bambino dovrebbe sempre avere un genitore e non può essere creato senza conoscerne il genitore. Quindi, solo una combinazione di 2 e 3. +1 –

1

Dal momento che ho appena incontrato lo stesso desissions design e domanda ancora non contrassegnati come risposta vi posterò la mia visione sulla soluzione di questo problema - forse ti aiutare chiunque. Questa soluzione è in realtà perfettamente utilizzabile con NHibernate.

public class Parent 
{ 
    private readonly ISet<Child> _children = new HashedSet<Child>(); 
    public virtual IEnumerable<Child> Children { get { return new ImmutableSet<Child> (this._children); } } 


    protected internal virtual void AddChild (Child child) 
    { 
     this._children.Add(child); 
    } 
} 


public class Child 
{ 
    public virtual Parent Parent { get; protected set; } 


    protected Child() 
    { 
    } 


    public static Create (Parent parent) 
    { 
     if (parent == null) 
      throw new ArgumentNullException ("parent"); 

     var child = new Child 
     { 
      Parent = parent 
     }; 

     child.Parent.AddChild (child); 

     return child; 
    } 
} 

Questo è differisce dalla vostra opzione # 2 in modo che la creazione dell'oggetto bambino (e invalidante suoi valori iniziali) sono raccolti withing oggetto figlio stesso e non in oggetto padre come lei ha suggerito nella # 2.

Una cosa non sono sicuro se è considerato un cattivo progetto o no se creiamo oggetti figlio con il metodo di produzione personale (Child.Create).

Spero che qualcuno con più esperienza nell'utilizzo di DDD possa commentare in merito.

Problemi correlati