Come convalidare il comando prima dell'esecuzione su aggregato quando la convalida deve interrogare i dati?

1

In un'applicazione progettata da DDD con principio CQRS come gestiamo il caso quando un comando deve essere convalidato prima di essere eseguito su un aggregato e la convalida deve interrogare i dati esistenti?

Ad esempio, nel mio sistema ho Customer , Project e Ticket aggregati. Un Project appartiene a uno specifico Customer e un Ticket è aperto per uno specifico Project .

Un comando CreateTicket viene emesso dal cliente corrente. Il sistema popola il carico utile del comando con customer_id e project_id .

Prima che i comandi vengano eseguiti su Ticket aggregato, devo verificare che il progetto del comando appartenga effettivamente al cliente del comando.

Un altro caso è questo. Viene emesso un comando per creare un nuovo Department nel sistema. Un dipartimento ha una proprietà title . Prima che venga creato il dipartimento, devo verificare che non ci siano altri reparti con lo stesso titolo nel sistema. Il repository aggregato non esegue query sui dati. Si recupera solo per ID e memorizza gli aggregati.

Come gestiamo tali casi?

    
posta Thanasis Ioannidis 30.10.2018 - 11:35
fonte

3 risposte

1

In a DDD designed application with CQRS principle how do we handle the case when a command needs to be validated before it is executed on an aggregate and the validation needs to query the existing data?

Se hai bisogno di interrogare i dati esistenti che fanno già parte dell'aggregato, non farlo. Basta passare il comando all'aggregato e inserire la logica per la valutazione dei dati correnti nel codice del dominio.

Se hai bisogno di interrogare i dati che esistono da qualche altra parte , normalmente passerai al modello di dominio qualcosa come un servizio di dominio, che dà al modello la possibilità di accedere a una copia dei dati che ha bisogno.

A command to create a new Department in the system is issued. A Department has a title property. Before the department is created I need to verify that there is no other department with the same title in the system.

Il termine generico per questo problema è Imposta convalida . La priorità è assicurarsi di comprendere l'impatto sul business (quanto costa all'azienda avere un titolo di dipartimento duplicato nel database per un minuto?)

I modelli di dominio applicano gli invarianti di set includendo l'intero set in un singolo "aggregato", in modo che le modifiche all'appartenenza abbiano sempre i dati di cui hanno bisogno per controllarli. Nei sistemi in cui i membri dell'insieme vengono archiviati in un database relazionale, può avere senso far sì che il database, anziché il modello di dominio, imponga l'invarianza.

Quando c'è solo un singolo campo di cui devi preoccuparti di essere unico, e se per quell'entità il valore del campo non cambierà mai, una possibilità è quella di usare quel campo per calcolare l'identificatore (assicurandoti che tutte le richieste di una chiave univoca specifica viene mappata sulla stessa istanza dell'aggregato).

(Probabilmente non è una buona opzione per qualcosa come il nome di un dipartimento, perché i re-org sono così prevedibili).

    
risposta data 30.10.2018 - 13:31
fonte
1

Gli aggregati dovrebbero essere progettati in modo da avere sempre tutti i dati necessari per eseguire la logica di business che incapsulano. Pertanto, se si scopre che è necessario interrogare i dati da altre aree (specialmente da altri contesti limitati), potrebbe indicare che i propri confini aggregati sono errati o, almeno, che non si stanno memorizzando abbastanza dati nel proprio aggregato.

Nel tuo scenario particolare, perché non immagazzini CustomerId e ProjectId quando crei il Biglietto? se l'operazione di creazione è sicura (non consentire ai clienti di creare ticket per progetti che non possiedono), da quel momento in poi è possibile eseguire comandi sui ticket sapendo che CustomerId può effettivamente accedere a ProjectId.

Per quanto riguarda la convalida del nome del Dipartimento, l'opzione più semplice e sicura per me è avere un vincolo univoco nel database (se la tecnologia db lo consente), perché non importa quanti controlli aggiungi prima di salvare, c'è sempre un possibilità di inserire o aggiornare contemporaneamente e finire con un nome di reparto duplicato.

Per migliorare l'esperienza utente, è possibile esporre ed endpoint per convalidare il nome di un dipartimento, in modo che l'interfaccia utente possa eseguire una convalida iniziale ed evitare la maggior parte dei casi dall'interfaccia utente direttamente. Quindi il vincolo univoco è lì per salvarti dai problemi di concorrenza.

    
risposta data 30.10.2018 - 20:34
fonte
0

Se è necessario interrogare qualcosa da qualche altra parte fuori dai confini aggregati, convalidare i dati prima di inviare il comando. Nella maggior parte dei casi, il meccanismo del bus di comando è 'Fire and forget' e se è necessario restituire qualche errore all'emittente del comando, è necessario controllare tale vincolo prima di inviare i comandi.

    
risposta data 16.12.2018 - 07:24
fonte

Leggi altre domande sui tag