Domanda sull'architettura del servizio applicazioni DDD

3

Spesso mi imbatto in questo scenario decisionale su dove chiamare un dominio (o un servizio applicativo) quando si costruiscono i miei modelli di dominio. Forse la confusione sta nell'identificare se si tratta di un servizio di dominio o di un servizio di applicazione stesso. Mi piacerebbe vedere cosa pensano gli altri. Farò del mio meglio per spiegarlo con uno scenario semplice e porrò altri esempi in cui mi imbatto.

Immagina un modello di dominio degli indirizzi. Ha i seguenti elementi:

  1. AddressLine1
  2. AddressLine2
  3. Città
  4. StateProvince
  5. Paese
  6. ZipCode

Ora ho definito un costruttore in questo modo:

Address(string addressLine1, string addressLine2, string city, string stateProvinceCode, string countryCode, string zipCode)

Devo garantire che il codice della provincia di stato che viene passato corrisponda a una provincia statale del Paese. Se avessi un database di città, mi piacerebbe anche abbinare la città e il codice postale.

In scenari come questi, come posso risolvere al meglio questo? Ecco le mie opzioni:

  1. Mantengo il costruttore molto semplice, non ci dovrebbero essere motivi per cui qualcuno non possa archiviare tutti i dati che vogliono costruire l'oggetto indirizzo. Creo quindi un metodo chiamato Validate () nel modello di dominio che accetta un IAddressValidator che sa come convalidare i dati.

L'implementazione di IAddressValidator può essere specifica dell'implementazione.

  1. In alternativa, introduco IAddressValidator come parte del costruttore. Il problema con questo approccio è che ora tutti coloro che desiderano utilizzare il dominio Indirizzo (indipendentemente dalle ragioni rudimentali) devono ora preoccuparsi di creare l'implementazione di IAddressValidator.

  2. Non hai affatto IAddressValidator / Validate nel dominio. Supponiamo che il dominio venga popolato da un servizio applicativo, ad esempio AddressService che esegue il lavoro di convalida di tutti i dati e quindi inserisce il modello di indirizzo che può essere successivamente memorizzato nel database. Ciò significa anche che se qualcuno non chiama il servizio di indirizzi per effettuare le convalide, rischia di salvare dati non validi nell'indirizzo.

Allo stesso modo, ho molti scenari simili in cui mi sembra di non sapere dove sia il posto migliore per convalidare i dati in arrivo.

Esempi:

  1. Un esempio in cui un utente risponde alle domande del sondaggio. Ogni domanda ha potenziali opzioni di risposta che devono essere convalidate prima che la risposta venga aggiunta a un sondaggio. Questa convalida appartiene al livello di dominio, ad esempio dovrei fare SaveAnswer (risposta risposta, validatore IAnswerValidator) ? Oppure a livello di servizio usando IAnswerValidator per prima convalidare la risposta e poi semplicemente chiama SaveAnswer (Answer answer) nel dominio assumendo che tutta la convalida verrà eseguita dal livello di servizio?

  2. Scenario di commercio elettronico, quando un articolo viene aggiunto al carrello e dobbiamo anche convalidare se l'inventario esiste. Dovremmo passare l'interfaccia di controllo inventario al dominio in questo modo: AddItem (elemento CartItem, checker IInventoryChecker) ? O dovremmo farlo a livello di servizio e lasciare il dominio con un semplice metodo AddItem (elemento CartItem) .

posta Anup Marwadi 19.08.2018 - 04:58
fonte

1 risposta

1

Sembra esserci una confusione tra diversi concetti nella tua domanda, che si occupa da un lato con DDD, dall'altro su DI e infine su livelli di architettura.

Servizi DDD

Diamo prima un'occhiata alla definizione di un servizio nella terminologia DDD, secondo Eric Ewans nel suo libro di riferimento Domain Driven Design :

SERVICE: An operation offered as an interface that stands alone in the model, with no encapsulated state.

Applicazione di questa definizione:

  • L'opzione 1 implica che il tuo validatore è un metodo di una classe di dominio. In effetti, potresti anche considerare di avere una proprietà isValid impostata dal costruttore e aggiornata ogni volta che viene richiamato un setter. Questo mi sembra un approccio molto logico e flessibile: dopo tutto, un indirizzo può essere temporaneamente errato o incompleto; deve essere valido solo nel momento in cui si desidera geolocalizzarlo o spedire un pacco.
  • L'opzione 2 suppone che il validatore sia indipendente dall'indirizzo, come verrebbe invocato dal costruttore. Quindi, per definizione, sarebbe un servizio di dominio. Tuttavia, il validatore è completamente dipendente dall'indirizzo (deve accedere a tutti i suoi componenti) e se cambi la struttura dell'indirizzo (ad esempio, introduci un numero di strada separato), dovresti cambiare tutto il potenziale validatore Servizi.
  • L'opzione 3 è un equivoco. Il fatto che un indirizzo sia valido o meno è in definitiva un problema di dominio. E più precisamente, è un problema di dominio dipendente dal Paese (ad esempio, non convalidi gli indirizzi del Regno Unito come convalidare gli indirizzi degli Stati Uniti, e la Francia richiede numeri all'inizio della strada, mentre Germania e Belgio alla fine). Supponiamo di condividere gli indirizzi tra diverse applicazioni: non avrebbe senso avere un tipo di convalida in una sola applicazione e una validazione totalmente diversa in un'altra applicazione!

Iniezione di dipendenza

Nell'opzione 2, si considera di iniettare il validatore. Questo avrebbe senso se potessi immaginare più validatori nel tuo dominio. Ma perché dovresti avere più validatori?

Potresti immaginare di avere diversi validatori per diversi paesi. Ma il codice del paese è parte degli argomenti del costruttore. Quindi, se sceglieresti nel livello applicazione il validatore in base al paese, in effetti eseguirai alcune scelte di dominio nella tua applicazione. Cosa significa questo ? Si crea accidentalmente un accoppiamento stretto tra il dominio e l'applicazione: gli oggetti del dominio sono coerenti solo se l'applicazione ha scelto il servizio di dominio corretto.

Livello applicazione vs livello dominio

La terminologia del servizio che usi, sembra riflettere l' architettura della cipolla , che fa anche un uso pesante di DI.

Ma attenzione alla potenziale confusione: ciò che diversi modelli di architettura chiamano il servizio di dominio non è necessariamente un servizio di dominio DDD. Spesso è un livello che isola la logica di dominio dal mondo esterno.

Ad ogni modo, indipendentemente dal modello di architettura, secondo i miei argomenti sopra, la validazione dovrebbe essere parte della logica del dominio.

    
risposta data 19.08.2018 - 21:00
fonte

Leggi altre domande sui tag