Terminare con troppi servizi in DDD

2

Al momento sto lavorando a un progetto e sto utilizzando questo progetto per provare a applicare DDD. Tuttavia, ci sono parti della mia implementazione che non riesco a capirmi o non mi sento giusto. Proverò a descrivere come attualmente ho la mia configurazione dell'applicazione;

Nel mio livello di dominio, ho i miei aggregati, oggetti valore e una classe di servizio per ogni contesto limitato. Ad esempio, ho un contesto limitato 'Account' con il seguente;

Account: account aggregate root

Profilo - oggetto valore

Indirizzo Email - oggetto valore

AccountValidator - convalida lo stato di un account

ProfileValidator - convalida uno stato dei profili

AccountRepository - interfaccia che descrive i metodi disponibili sul repository

AccountService - al momento questo ha un singolo metodo createNewAccount (), accetta un numero di valori primitivi e crea l'account e lo restituisce. Prima di creare l'account, prima controlla che il nome utente selezionato non esista già. Se il nome utente esiste, genera un'eccezione. (Questa regola dovrebbe essere nel servizio dominio?)

Nel mio livello di applicazione ho;

AccountRepositoryImp: un'implementazione dell'accountRepository nella classe domain, questa è un'interfaccia Spring Data standard che implementa accountRepository.

AccountFacade - fondamentalmente, un altro servizio account che fornisce metodi come findById (), findByUsername (), createNewAccount (), sendVerificationEmail (), verifyAccount.

AccountController - controller Spring standard che gestisce tutte le azioni relative all'account

Ho un numero di domande / problemi con il mio approccio;

  1. Ho due classi di servizio per ogni contenuto limitato, uno per il dominio e uno per l'applicazione e, mentre capisco, la classe del servizio di dominio dovrebbe essere utilizzata solo per applicare comportamenti o regole aziendali che non possono essere eseguite sull'aggregato di per sé (cioè bisogno di accesso db), sto faticando a determinare qual è una regola di applicazione e qual è una regola aziendale. Ad esempio, non è possibile creare un account se il nome utente è già in uso, l'ho messo nel mio servizio di dominio, ma sto iniziando a chiedermi se dovrebbe appartenere al metodo createNewAccount () nel servizio dell'applicazione. Un'altra regola: "Un account può essere cancellato solo da un amministratore o l'account si mantiene", è questa applicazione o azienda?
  2. Mentre aggiungo sempre più metodi al mio servizio applicativo, diventerà piuttosto grande. Questo mi porta a pensare all'implementazione di CQRS e ad avere una classe / metodo per ogni comando / query. Questo rompe le cose e rende più facile la gestione, ma non posso fare a meno di sentire che questo porterà un sacco di duplicazioni ad esso. Ad esempio, nel AccountRepository posso recuperare un account tramite il suo nome utente, e se l'account non esiste restituisce null. Invece di restituire null, ho scritto un metodo getByUsername () nel servizio dell'applicazione in modo che lanci un'eccezione se l'account non esiste, piuttosto che un null. Ciò significa che posso utilizzare questo metodo con altri metodi e non è necessario duplicare l'eccezione. Mi sento come se io uso CQRS, ho ancora intenzione di mantenere il servizio dell'applicazione in modo che possa contenere metodi che vengono utilizzati da più comandi / query per ridurre i duplicati. Finirò con un altro controller di livello - > comando / query - > applicationervice - > domainservice mi sembra che sto rendendo l'applicazione più complicata di quanto non debba essere
  3. Se utilizzo CQRS, il comando / query o controller è responsabile della creazione di ViewModels? Sono incline a cosa il comando / query può costruirle, dato che saranno basate sul caso d'uso e possono essere riutilizzate se dovessi aggiungere endpoint REST al sistema in futuro. Se ho permesso al controller di eseguire più comandi / query e di creare ViewModel, quindi se implemento REST in un secondo momento, dovrò duplicarlo.
  4. Regole - come detto sopra, sto faticando ad assegnare regole all'applicazione o al dominio. Elencherò alcune regole qui sotto e se potessi avere qualche puntatore su dove potrebbero essere, sarebbe utile allenare il mio cervello;

    • Non è possibile creare un account senza un'email, nome utente, nome e cognome (l'ho inserito nel dominio)
    • Non è possibile creare un account se il nome utente è in uso (l'ho messo nel dominio)
    • Un utente non può commentare un progetto se non è un membro del progetto.
    • Un commento non può essere lasciato su un progetto chiuso
    • Solo il proprietario del progetto può modificare / gestire / amministrare il progetto

Mi scuso se questa domanda è poco strutturata e i miei pensieri sembrano un po 'casuali. Sono stato così abituato a usare un modello anemico che ho tanti pensieri nella testa che non riesco a strutturare (da qui la domanda).

    
posta SheppardDigital 09.11.2018 - 09:15
fonte

1 risposta

1

Off the top

1) Se hai problemi a modellare il tuo dominio, è improbabile che CQRS aiuti.

2) Il tuo "vincolo email unico" è un esempio comune di Set convalida . Cercare di garantire l'unicità di un elemento in un insieme distribuito con più scrittori è un problema difficile.

In alcuni domini, puoi usare l'indirizzo email come identificativo univoco per l'account stesso (sia l'indirizzo email stesso, sia un certo valore hash / uuid calcolato dall'indirizzo email). È più semplice della convalida dei set, ma ha implicazioni sui casi d'uso in cui un indirizzo email può cambiare.

Gli indirizzi email sono qualcosa di speciale. Il tuo dominio probabilmente non è l'autorità per un indirizzo email; l'indirizzo è stato assegnato da qualche altra parte e ne stai appena ricevendo una copia. Quindi potresti valutare attentamente cosa è realmente possibile con la convalida dell'email .

I servizi di dominio non hanno normalmente una logica di dominio: il calcolo dei cambiamenti di stato appartiene agli aggregati, non ai servizi. La maggior parte dei servizi di dominio sono query per fornire l'accesso in lettura aggregato a una copia memorizzata nella cache di dati che risiedono altrove, o per fornire l'accesso aggregato ad alcune funzionalità esterne al modello (come l'invio di un'email). Lo stesso servizio di dominio potrebbe essere poco più di un'interfaccia, con tutti i dettagli dell'implementazione definiti nei componenti dell'applicazione / infrastruttura che forniscono la capacità.

Infine, la maggior parte dei domini non ha bisogno di una soluzione su misura per la gestione degli account. Sei sicuro di non dover usare qualcosa da uno scaffale per risolvere questa parte del problema?

am I right in saying that you wouldn't inject the domain service into the aggregate? i.e., you'd call the domain service first?

No: passaggio del servizio di dominio all'aggregazione come argomento e la logica di business nel metodo di aggregazione determina se richiamare o meno le funzionalità del servizio di dominio.

    
risposta data 09.11.2018 - 11:24
fonte

Leggi altre domande sui tag