2011-02-02 20 views
32

Supponiamo di avere un'architettura ispirata a CQRS, con componenti come comandi, modello di dominio, eventi di dominio, DTO modello di lettura.
Ovviamente, possiamo usare Value Objects nel nostro modello di dominio. La mia domanda è, dovrebbero essere utilizzati anche in:Oggetti valore in CQRS - dove usare

  1. Comandi
  2. Eventi
  3. DTOs

non ho visto alcun esempio in cui si utilizzano oggetti di valore (VO) nei componenti menzionato sopra. Invece, vengono usati i tipi primitivi. Forse sono solo gli esempi semplicistici. Dopotutto, la mia comprensione dell'uso di VO in DDD è che agiscono da collante per l'intera applicazione.

La mia motivazione:

Comandi.
Diciamo che l'utente invia un modulo che contiene campi di indirizzi. Abbiamo Object Address Value per rappresentare questo concetto. Quando costruisci il comando nel client, dovremmo comunque validare l'input dell'utente, e quando è ben formato, possiamo creare l'oggetto Address proprio lì e inizializzare Command con esso. Non vedo la necessità di delegare la creazione dell'oggetto Address al gestore comandi.

Eventi di dominio.
Il modello di dominio opera già in termini di oggetti valore, quindi pubblicando eventi con VO anziché convertendoli in tipi primitivi, è possibile evitare alcuni codici di mapping. Sono abbastanza sicuro che sia giusto usare gli OV in questo caso.

DTO.
Se i DTO lato query possono contenere oggetti valore, ciò consente una maggiore flessibilità. Ad esempio, se disponiamo di un oggetto Money, possiamo scegliere se visualizzarlo in EUR o USD, non è necessario modificare il modello di lettura.

+3

Dopo aver riflettuto su questo per un po ', la mia conclusione: avere oggetti ricchi di comportamenti in Eventi è semplicemente impossibile, in quanto devono rappresentare dati storici, e non abbiamo modo di serializzare il comportamento oggi. Per quanto riguarda i comandi e la lettura dei DTO del modello, questo potrebbe funzionare, e non è ancora chiaro se l'accoppiamento che introduce sia accettabile o meno (in ogni caso, si tratta di "se i livelli di dominio e presentazione fanno riferimento alla stessa implementazione di Money VO" piuttosto che "dovrebbe TransferMoneyCommand contenere Money VO o MoneyDTO"). – driushkin

risposta

22

Ok ho cambiato idea. Ultimamente ho cercato di trattare con i VO e dopo aver visto questo http://www.infoq.com/presentations/Value-Objects-Dan-Bergh-Johnsson ho chiarito un paio di cose per me.

I comandi e l'evento sono messaggi (e non oggetti, oggetti sono dati + comportamento), per certi aspetti come DTO, comunicano dati su un evento e non incapsulano essi stessi alcun comportamento.

Valore Gli oggetti non sono affatto come DTO. Sono una rappresentazione di dominio e sono, in generale, ricchi di comportamento come tutte le altre rappresentazioni di dominio.

I comandi e gli eventi comunicano le informazioni all'interno e all'esterno del dominio rispettivamente, ma esse non incapsulano alcun comportamento. Da quella prospettiva sembra sbagliato e probabilmente un limite di contesti di violazione per passare i VO all'interno di essi.

Per parafrasare Oren (anche se si riferiva a nHibernate e WCF) "Non inviare il tuo dominio attraverso il filo". http://ayende.com/Blog/archive/2009/05/14/the-stripper-pattern.aspx

Se si desidera comunicare un oggetto valore, quindi suggerisco di passare gli attributi necessari necessari per ricostruire il VO al loro interno.

testo originale (per i posteri):

Se ti stai chiedendo se il valore di oggetti possono essere passati per il modello di dominio a eventi o trasmesso dal comando, non ho davvero vedere un problema enorme con l'ex, sebbene quest'ultimo possa violare alcune delle regole della radice aggregata che è il "proprietario" dei valori.

Detto questo un oggetto valore rappresenta concetti come ad esempio un colore. Non hai verde, tu sono verde o no. Non sembra esserci nulla di intrinsecamente sbagliato in un comando che ti dice che sei verde passando questo.

Leggere il capitolo da DDD sul modello di radice aggregata spiega Entità e oggetti valore piuttosto bene e vale la pena leggerlo più volte.

+0

Penso che sia ok dal punto di vista DDD puro per avere i VO condivisi, ma dal punto di vista di cqrs, questo può introdurre alcuni problemi tecnici, come il controllo delle versioni degli eventi se viene applicato Event Sourcing. E poi sorge la domanda naturale, è davvero solo un problema tecnico, o è qualcosa di intrinsecamente sbagliato con l'intera idea. – driushkin

+0

La comprensione che ho tratto dal libro DDD è che mentre le radici aggregate sono i proprietari delle rispettive entità e oggetti valore, possono passare transitoriamente un riferimento a tali oggetti. L'unico scopo della radice aggregata è definire i limiti transazionali del sistema. Ancora una volta, potrei interpretare erroneamente questo e come sempre YMMV. Anche se sarebbe davvero un errore serializzare un'entità come parte di un evento, non vedo alcun problema per gli OV poiché dovrebbero rappresentare un vero valore immutabile. –

+5

"Gli oggetti valore non sono affatto DTO, sono una rappresentazione di dominio e sono [...] ricchi di comportamento come tutte le altre rappresentazioni di dominio." Sarei fortemente in disaccordo con la seconda parte. Sebbene facciano parte del dominio (ad esempio definendo cosa sia un * indirizzo *), sono pensati per essere usa e getta e non hanno alcun comportamento collegato ad essi. Ecco perché sono solitamente immutabili, per impedirti di voler fare casino con il tuo VO. – Dav

4

Dico che è una cattiva idea.

C'è un motivo per cui non facciamo lo stesso con le entità - per evitare di collegare altre parti del sistema al dominio (nei posti sbagliati). Lo stesso vale per Value Objects, l'unica differenza tra oggetti value ed entità è lifetime e ownership - queste differenze non influenzano il modo in cui dovremmo e non dovremmo accoppiarci.

Immagina di creare un evento contenente un VO. Un cambiamento nel tuo dominio richiede di cambiare quel VO. Ora sei entrato in un angolo in cui il tuo evento è anche forzato da modificare, idem per qualsiasi Comando o DTO di cui fa parte.

Questo deve essere evitato.

Utilizzare DTO e/o primitive. Mappale (AutoMapper lo rende un affare di 1 riga).

+1

Bene, questi VO non dovrebbero appartenere al solo modello di dominio. Sarebbero una conoscenza condivisa su tutti i componenti del sistema (come l'assembly MyApp.Core a cui può fare riferimento chiunque). Finché i concetti sono stabili, o addirittura, non hanno cambiamenti di rottura, immagino che questo dovrebbe andare bene. Ofc, se usiamo Event Sourcing, questo ingombrerebbe il nostro codice con concetti legacy che non sono più in uso ma fanno parte di vecchi eventi. Quindi questo è uno svantaggio a cui riesco a pensare. Tuttavia, l'idea di avere un modulo di concetti condivisi (come Valuta, Soldi, Velocità) attraverso i suoni delle applicazioni è così allettante per me. – driushkin

+0

Se sono concetti condivisi tra le applicazioni, direi che non fanno parte del dominio (in quanto il dominio, praticamente per definizione, è specifico dell'applicazione) in quanto infrastruttura o codice comune. Pensavo a quello in particolare quando ho risposto. –

+0

Ritengo inoltre che VO in CQRS sia una cattiva idea, ma come possiamo incapsulare la logica del dominio quando l'aggregazione diventa complessa? –

3

Analogamente ad altre risposte, in SOA ciò interromperà l'incapsulamento del servizio mentre il dominio sta uscendo.

0

In base a Clean Code i DTO sono strutture di dati (solo per aggiungere un altro termine), mentre gli oggetti valore sono oggetti. La differenza che gli oggetti possono avere un comportamento. Mescolare strutture dati con oggetti è generalmente una pessima idea, perché sarà difficile mantenere l'ibrido che si ottiene.

Non mi sento corretto mettere gli oggetti valore in DTO anche da una prospettiva di architettura. Gli oggetti valore sono all'interno del modello di dominio mentre i DTO che hai menzionato stanno definendo l'interfaccia del modello. Di solito costruiamo un'interfaccia per disaccoppiare il mondo esterno dall'interno di qualcosa. Quindi nel caso attuale abbiamo aggiunto DTO per disaccoppiare il mondo esterno dagli oggetti valore (e altre cose relative ai modelli). Dopo questo l'aggiunta di oggetti valore all'interfaccia è pazzesca.

Quindi non hai ancora trovato questa soluzione perché è un anti-pattern.

+0

Quindi non dovremmo aggiungere alcun tipo di stringa o intero a DTO, dal momento che è anche oggetto valore? – bojanv55

+0

@ bojanv55 Le stringhe e gli interi sono primitivi, non oggetti valore. Un oggetto Date o DateTime sarebbe stato un esempio migliore. Intendevo che i DTO non dovessero trasferire i VO definiti nel dominio. Ad esempio abbiamo un VO nel nostro dominio relativo alla nascita di qualcuno, ad es. 1985/12/20. Se chiediamo il compleanno, dovremmo restituire 12-20 nel DTO. Se chiediamo la data di nascita, dovremmo restituire il 1985-12-20 al DTO. Se chiediamo l'età, dovremmo restituire 31 anni nel DTO. Quindi il DTO non conterrà l'intero VO con la sua logica, solo la rappresentazione di cui avevamo veramente bisogno. – inf3rno

+0

@ bojanv55 Almeno questo è il modo in cui utilizzo DTO e VO. Questo approccio ha funzionato finora, ma ofc. Non sono infallibile. :-) – inf3rno