DDD e oggetti valore. Sono oggetti valore mutabili un buon candidato per Non Aggr. Entità radice?


9

Ecco un piccolo problema

Avere un'entità, con un oggetto valore. Non è un problema. Sostituisco un oggetto valore con uno nuovo, quindi nhibernate inserisce il nuovo valore e orfano quello vecchio, quindi lo elimino. Ok, questo è un problema.

L'assicurato è la mia entità nel mio dominio. Ha una raccolta di indirizzi (oggetti valore). Uno degli indirizzi è MailingAddress. Quando vogliamo aggiornare l'indirizzo postale, supponiamo che il codice postale sia errato, seguendo la dottrina di Mr. Evans, dobbiamo sostituire il vecchio oggetto con uno nuovo poiché è immutabile (un oggetto valore giusto?).

Ma non vogliamo cancellare la riga, perché il PK di quell'indirizzo è un FK in una tabella MailingHistory. Quindi, seguendo la dottrina del signor Evans, siamo praticamente fregati qui. A meno che non crei i miei indirizzi Entities, quindi non devo "sostituirli" e semplicemente aggiornare il suo codice postale, come ai vecchi tempi.

Cosa mi suggeriresti in questo caso? Per come la vedo io, ValueObjects sono utili solo quando si desidera incapsulare un gruppo di colonne della tabella del database (componente in nibernazione). Tutto ciò che ha un ID di persistenza nel database, è meglio renderlo un'entità (non necessariamente una radice aggregata) in modo da poter aggiornare i suoi membri senza ricreare l'intero grafico dell'oggetto, specialmente se si tratta di un oggetto annidato in profondità.

Sei d'accordo? Il signor Evans ha permesso di avere un oggetto a valore mutabile? O un oggetto a valore mutabile è un candidato per un'entità?

Grazie


2
Esiste un "oggetto valore mutabile"? Ho sempre avuto l'impressione che gli oggetti siano immutabili.
erbaceo

@herby Immagino che potresti avere un oggetto mutabile che rappresenta un oggetto valore DDD nel codice, ma dovresti considerare che una volta mutato l'oggetto, non fa più riferimento allo stesso oggetto logico valore DDD ma a uno nuovo. Questo potrebbe essere desiderabile, ma è una ricetta per imitare la confusione: rendere oggetti di valore immutabili nel codice è una convenzione intelligente.
MattDavey,

Risposte:


8

Tutto ciò che ha un'identità dovrebbe essere un'entità, e tutto ciò che non ha un'identità è un valore semplice, quindi un oggetto valore.

Per citare Martin Fowler (che a sua volta dice Eric Evans)

  • Entità: oggetti che hanno un'identità distinta che attraversa il tempo e diverse rappresentazioni. Si sentono anche questi chiamati "oggetti di riferimento".
  • Valore oggetto: gli oggetti che contano hanno solo la combinazione dei loro attributi.

Motivo per rendere il tuo indirizzo un oggetto valore:

Se il tuo indirizzo è mutevole, probabilmente alla fine rovinerai la tua cronologia postale. Ad esempio, se spedisci articoli a un cliente, non puoi essere sicuro a quale indirizzo hai effettivamente spedito qualcosa in passato se l'indirizzo a cui fa riferimento la tua tabella MailingHistory è stato modificato.

La voce MailingHistory Abbiamo spedito A764 all'indirizzo 657 potrebbe significare che abbiamo spedito l'articolo A764 a Boston ieri e che abbiamo spedito l'articolo A764 a New York domani.

Se l'indirizzo postale deve essere modificato, non è necessario eliminare quello precedente. Conservalo e contrassegnalo come inattivo e quello nuovo come attivo .


Ovviamente potresti trattare il tuo indirizzo come un'entità, ma solo quando lo aggiorni non cambierebbe il luogo effettivo a cui si riferisce l'indirizzo, consentendo quindi solo la correzione di errori di battitura.

Se sei sicuro che potresti assicurarti che, utilizzando un'entità sarebbe possibile.


Ma la soluzione migliore IMHO è non fare riferimento a un'entità indirizzo nella cronologia postale, ma piuttosto salvare l'indirizzo specifico direttamente nella tabella della cronologia postale (fondamentalmente copiando i dati dell'indirizzo).

In questo modo, sai sempre dove hai spedito le tue cose (o qualunque cosa tu stia inviando per posta) e dal momento che useresti un'entità mutabile, la tua tabella degli indirizzi non sarà ingombra.

Ho lavorato con / su diversi sistemi ERP e quasi tutti hanno usato questo approccio.

Avrai un po 'di ridondanza nel tuo database, ma è il modo più pragmatico di IMHO.


Questa è probabilmente la soluzione più priva di mal di testa. Solo se ti aspetti che i futuri canali di comunicazione richiederanno colonne aggiuntive e il tuo database sia troppo grande per ALTER, potrebbe essere necessario utilizzare entità in tabelle separate. Ciò, a sua volta, richiede strategie come "unisciti sempre al più recente indirizzo / telefono / e-mail" nelle tue SELECTquery, che sono difficili da mantenere sostenibili ed efficienti. Mantenerlo semplice, se possibile.
Timo

@Timo "Unisciti sempre al più recente indirizzo / telefono / e-mail" non è difficile se denormalizzi un po 'i tuoi dati semplicemente aggiungendo una activebandiera. Ovviamente devi assicurarti di utilizzare sempre i and active = truetuoi Join, mantenere aggiornato il flag e aggiungere una contraffazione al tuo tavolo in modo che, ad esempio, solo un messaggio di posta elettronica per ciascun cliente possa impostare questo flag su true.
bradipo

Questo introduce il problema di disattivare quello precedente. Se hai sostituito l'oggetto indirizzo "attuale" della tua istanza nel codice e vai al tuo codice di accesso ai dati, allora non saprà (1) se ne esiste uno nuovo o (2) quale sia il potenziale vecchio uno era. Quindi ogni operazione di salvataggio dovrà fare qualcosa di contorto come "prima vai e disattiva tutti gli indirizzi correlati nel database", e quindi salva quello corrente con active=true. Questo non è ciò che definirei semplice, motivo per cui mi piace la tua soluzione.
Timo

2

Vedo 2 cose:

  1. Va bene che la modifica del codice postale influisca su una cronologia? Penso che sarebbe logico che la cronologia indichi il vecchio indirizzo invariato, quindi sai che lo invii a un indirizzo sbagliato.

  2. Nel momento in cui MailingHistory ha FK sull'indirizzo l'indirizzo ha smesso di essere un oggetto valore ed è diventato entità. Gli oggetti valore non hanno identità, che consente ad altre entità di fare riferimento a questa identità. Puoi avere indirizzi in una singola tabella con altre tabelle che puntano ad esso, ma l'unico effetto è il risparmio di spazio. Dal punto di vista del dominio, se due entità hanno lo stesso tipo di oggetto valore di riferimento, non condividono alcun tipo di informazione.


2

IMO l'oggetto indirizzo è un'entità nel tuo dominio. È condiviso da più entità, ha una propria identità ed è unico in tutto il sistema.

Evans dice:

Un oggetto definito principalmente dalla sua identità è chiamato entità.


Le identità di dominio, a mio avviso, non hanno nulla a che fare con l'identità di persistenza. Secondo il libro del signor Evan.
Pepito Fernandez,

Hai ragione. Modifica la mia risposta. Ciò che intendo è che l'oggetto Indirizzo è importante in questo specifico dominio, è unico. La chiave esterna e la chiave primaria IMO indicano che in realtà è un oggetto unico nell'intero dominio, quindi ha un'identità.
margabit,

1
"l'oggetto indirizzo ... ha la sua identità" - quale attributo di un indirizzo lo identifica in modo univoco? Nessun singolo attributo di un indirizzo è unico, ma la combinazione di attributi funge da identità. Questa è la definizione stessa di un oggetto valore
MattDavey il

@MattDavey: è una buona conclusione, ma mi confondo quando Tony dice "non vogliamo cancellare la riga, perché il PK di quell'indirizzo è un FK in una tabella MailingHistory". Questo significa per me che l'oggetto Indirizzo ha anche un significato al di fuori dell'Assicurato "Assicurato". Il che mi indica che l'oggetto "Indirizzo" non dovrebbe essere un oggetto ValueObject. Cosa ne pensi?
margabit,

Potremmo dire che Value Objects invariabilmente sarebbe una composizione interamente di proprietà (UML) da parte del genitore? Inoltre un oggetto valore non avrebbe senso senza il suo genitore e non può essere condiviso tra i genitori?
Sudarshan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.