Che cos'è un oggetto valore nella progettazione orientata al dominio?

6

Ho un'entità e ho capito che esiste un gruppo di proprietà che funzionano insieme. Quindi li ho spostati su un oggetto valore (insieme al loro comportamento) e ora ho un riferimento dalla mia entità a questo oggetto valore.

Ho letto " Domain Driven Design " (PDF) e I ha trovato la seguente dichiarazione quando ha spiegato gli oggetti Valore:

If Customer is an entity object, then one instance of this object, representing a specific bank client, cannot be reused for account operations corresponding to other clients. The outcome is that such an instance has to be created for every client. This can result in system performance degradation when dealing with thousands of instances.

Ma non sono ancora chiaro cosa significhi esattamente. Il mio nuovo oggetto è un oggetto valore o dovrebbe essere un'entità? Sto avendo problemi a ragionare sul fatto che dovrebbe essere un'entità. In altre parole, quali domande dovrei chiedere al mio dominio per assicurarmi che dovrebbe essere un oggetto valore?

    
posta JD01 18.12.2011 - 13:21
fonte

3 risposte

4

Per espandere la risposta in base alle domande, un oggetto valore non ha un'identità surrogata come un numero cliente, ma l'oggetto stesso è la sua identità naturale.

Prendi un indirizzo per esempio. Tutti gli indirizzi sono unici e i vari componenti di un indirizzo (numero, nome della via, ecc.) Costituiscono l'identità degli indirizzi. Quando ti trasferisci a casa, non raccogli il tuo indirizzo, cambia il numero sulla porta e portalo con te, ottieni un nuovo indirizzo. Poiché tali oggetti valore non cambiano, sono immutabili. Tuttavia potresti avere 2 o più clienti che vivono allo stesso indirizzo, nel qual caso il valore dell'indirizzo è riutilizzabile - non è legato a una singola entità cliente.

    
risposta data 19.12.2011 - 10:54
fonte
3

La proprietà chiave di un oggetto valore è che non ha identità. È definito solo dai suoi attributi, e qualsiasi altra istanza con valori di attributo identici può essere sostituita.

Los Techies ha avuto una buona spiegazione sul loro blog qualche tempo fa , ed è stato chiesto su StackOverflow .

    
risposta data 18.12.2011 - 23:05
fonte
1

Ecco la migliore analogia che ho potuto "insegnare" ai miei colleghi quando volevo lavorare su DDD con Value Objects.

Ogni volta che pensi a un oggetto valore, pensa all'oggetto DateTime in .Net.

Ad esempio, quando si dispone di un DateTime nell'oggetto e si mantiene quell'oggetto, si salva solo una rappresentazione in formato stringa della data e dell'ora in questione. Può anche essere formattato per soddisfare determinati locali (mese-giorno o giorno-mese per esempio).

Tuttavia, l'oggetto DateTime è così sofisticato internamente. Hanno più membri per memorizzare valori diversi (giorno, mese, anno, ora, minuto, secondi, millisecondi) in modo che possano eseguire operazioni come .AddDay (2) che fondamentalmente prende il campo giorno, ne aggiunge un 2 e restituisce un nuovissimo oggetto DateTime con la nuova aggiunta. Quindi, non modifichi mai veramente l'oggetto DateTime. Ne crei uno ogni volta che usi uno dei loro metodi.

Lo stesso vale per gli oggetti valore personalizzati ... Dì, CreditCard ... diamo un esempio.

Vogliamo memorizzare le informazioni della carta di credito per un utente. Nel nostro dominio, non è necessario tenere traccia della carta di credito. Quindi, la prima cosa che potremmo essere tentati di fare è creare 4 campi.

string CreditCardNumber {get;set;}
string CreditCardExpiration {get;set;}
string CreditCardType {get;set;}
string CreditCardSecurityCode {get;set;}

Ora dì che abbiamo questo campo nella nostra AggregareRoot / Entity. Se vogliamo "analizzare" il nostro ExpirationDate su un oggetto DateTime miningful (dal 07/18 al 07/01/2018) per scopi di validazione, ora dobbiamo aggiungere quella logica alla nostra AR / Entity. Potresti pensare ... "va bene" ma non lo è, perché le nostre AR / Entità dovrebbero essere focalizzate sul problema che risolvono, non convalidando le date di scadenza della carta di credito. Questo è più lavoro ausiliario.

Immagina se DateTime non avesse tutte quelle funzionalità di manipolazione di Date e Time e hai bisogno di implementare tutto ciò nella tua classe, suona bene? Certo che no.

Quindi, nel nostro esempio creiamo una classe CreditCard

public class CreditCard: ValueObject

quindi trasferiamo tutti questi campi in questa classe (puoi rimuovere il prefisso CreditCard). Ora hai molto potere nelle tue mani. È possibile creare tutti i metodi di convalida desiderati: convalida del checksum, convalida della data di scadenza e analisi, in realtà convalidare che il tipo di carta di credito corrisponda alla sequenza numerica (Mastercard inizia con 54 se non vado errato) ... Voglio dire, puoi aggiungi MOLTA funzionalità alla tua classe CreditCard senza inquinare il tuo AR / Entità. Puoi creare il tuo "formato" personale per mantenere queste informazioni se vuoi. Supponete di sovrascrivere il metodo .ToString () e formattarlo come "MC 5474 3434 8383 4848 07/18". Oppure puoi configurare il tuo ORM per mappare le singole proprietà di sola lettura per quei valori.

Come si usa in modo efficace? Semplice. Supponi di avere una classe PaymentMethod che è una radice aggregata. Vuoi tenere traccia di quel metodo di pagamento perché verrà utilizzato per effettuare i pagamenti, quindi forse vuoi avere una cronologia dei pagamenti collegata a questa classe.

All'interno tutto ciò che devi fare è aggiungere un oggetto valore CreditCard ...

public CreditCard BusinessCard {get;}

Ora in uno dei metodi della tua AR ... dì,

private void Enable()
{
    this.IsEnabled = BusinessCard.IsValid();
}

Vedi? Ho spostato la logica della convalida della carta nell'oggetto valore. E indovina cosa? Può essere riutilizzato !!! Puoi effettivamente condividere oggetti valore.

Spero che questo aiuti!

    
risposta data 19.07.2016 - 18:55
fonte

Leggi altre domande sui tag