2010-11-01 17 views
5

Capisco che non dovremmo cambiare i figli di una radice aggregata direttamente, ma invece dovrebbero essere eseguiti tramite metodi sulla radice aggregata. E.g. order.SetOrderLineQty(product, qty);Accesso ai membri aggregati in sottoclasse

Ma cosa succede se i figli della radice aggregata sono qualcosa di astratto? Immagina di avere radice radice auto, che contiene un elenco di IWheel come parte dell'aggregato. Come aggiungeresti/modificheresti le proprietà della ruota tramite la sua radice aggregata (chi non sa nulla di quale sia il tipo di ruota in calcestruzzo che potrebbero essere)?

Un esempio più realistico è questo: Un medico può creare un MedicalRerport (radice aggregata), che contiene un elenco di IMedicalNote (come parte dell'aggregato di MedicalReport). IMedicalNote è un'interfaccia/classe di base, che è sottoclasa in alcune sottoclassi concrete, ad es. BloodCheck Nota, TemperatureNote, MineralConcentrationNote, ecc. Ecc.

Ogni sottoclasse ha proprietà diverse e sono tutte modificabili. Un aggregato di MedicalReport può contenere una o più delle seguenti note. (Ogni sottoclasse di note ha un controllo utente specifico per l'utente per inserire/aggiornare i dettagli, visualizzati come pannelli/schede sotto la grande schermata MedicalReport)

La mia domanda è, come posso aggiungere/modificare le proprietà di questi note rigorosamente tramite il suo aggregato-root (MedicalReport)? Dal momento che non mi è permesso di modificare direttamente queste proprietà note, una brutta opzione è esponendo tutte le possibili proprietà della nota sulla radice aggregata (MedicalReport), vale a dire:

report.SetWhiteBloodCellCount(cellCount); 
report.SetBloodCheckComment(comment); 
report.SetTemperature(bodyPart, temperature); 
report.AddMineral(mineral, concentration); 

Ciascuno di questi metodi aggiornare (o creare nuovo) nota gli articoli nella sua collezione di bambini interni. Ci sono 2 ovvi problemi con questo:

  1. Dobbiamo definire in anticipo tutte le proprietà disponibili di tutte le sottoclassi di IMedicalNote possibili sulla radice aggregata. Questo non è accettabile poiché il numero di sottoclassi è garantito per crescere, dipende dal tipo di dati medici che vogliamo acquisire, che è il punto centrale dell'ereditarietà in primo luogo.
  2. Ci possono essere più istanze dello stesso tipo di nota all'interno dell'elenco. Questa API fallirà, dal momento che non possiamo semplicemente dire report.SetBloodCheckComment(comment) e aspettarci che aggiorni un elemento BloodCheckNote nell'elenco, perché consentiamo più di una voce di BloodCheckNote nell'elenco.

ho ancora voglia di mantenere tutte le interazioni di queste note attraverso il suo aggregato-radice, in quanto ha per controllare se l'intero MedicalReport aggregata è valida per essere salvati, se l'aggregato non è modificabile, optimistic- a grana grossa controllo della concorrenza, ecc. Ma come posso farlo?

risposta

4

Mi chiedo se stai interpretando male la guida sulle radici aggregate (o forse l'ho fatto ...).

Non ho mai letto la guida dicendo: "l'aggregato deve fornire metodi proxy per ogni proprietà concepibile di tutti i suoi oggetti aggregati". Piuttosto, penso che dice: "l'aggregato controlla il ciclo di vita, l'identità e le relazioni dei suoi oggetti aggregati".

Quindi è perfettamente valido per un cliente chiedere all'aggregato un riferimento (transitorio) a uno dei suoi oggetti e fare qualcosa con esso.Non ho la mia copia di DDD qui per confermare la formulazione, ma che sembrerebbe coerente con la DDD summary ebook (p53) che dice:

E 'possibile che la radice di passare riferimenti transitori di oggetti interni a quelli esterni, a condizione che gli oggetti esterni non contengano il riferimento al termine dell'operazione.

Quindi, nel tuo caso i clienti avrebbe chiesto MedicalReport per esempio (s) di IMedicalNote, tornare i sottotipi, operare su di essi a seconda dei casi e passare di nuovo alla radice, se applicabile.

Come dico: non posso dire con certezza che sia in linea con DDD, ma il buon senso dice che è una soluzione più scalabile e flessibile rispetto al tentativo di riflettere ogni proprietà/metodo di ogni sottotipo nella radice aggregata.

hth.

+0

La mia comprensione è che è possibile recuperare l'oggetto interno (IMedicalNote) ma solo per uno scopo di sola lettura. Non dovresti apportare alcuna modifica ad esso. Tutte le modifiche devono essere fatte tramite la root in modo che possa controllare l'integrità. Inoltre, cosa intendi riportando alla radice? Una volta che esterniamo la proprietà del bambino esternamente, allora è tutto, è cambiato (per riferimento), ignorando la radice, vero? Che cosa fa esattamente "il ritorno alla radice"? – Sheepy

+0

Mi scuso, rispondo in qualche modo ambiguo. Root restituisce le copie degli oggetti che il client quindi aggiorna e restituisce alla root. Root quindi responsabile del controllo delle invarianti e dell'impostazione delle relazioni. Fornisce una scissione sensata di responsabilità: root conosce le relazioni e i vincoli tra gli oggetti aggregati ma non ha bisogno di conoscere i dettagli di tutti i sottotipi. I clienti possono operare su sottotipi specifici come richiesto. Nota Root potrebbe aver bisogno di conoscere alcuni dettagli di sottotipo (ad es. Se deve contenere esattamente un 'BloodCheckNote' ma potrebbe avere molti' TemperatureNote's). – sfinnie

+0

Si intende creare un meccanismo di clonazione in modo che la radice restituisca sempre un clone di ogni nota figlio quando si accede tramite il getter pubblico di root? E poi un modo per copiare questi valori di nuovo sul suo oggetto reale una volta che il client restituisce questi figli alla radice. Volevo solo chiarire se questo è ciò che intendevi, perché sembra un bel po 'di lavoro. Cheers – Sheepy

Problemi correlati