Gestori di comandi e DDD


10

Ho un'applicazione ASP.NET MVC, che utilizza un servizio di query per ottenere dati e un servizio di comando per inviare comandi. La mia domanda riguarda la parte di comando.

Se arriva una richiesta, il servizio comandi utilizza un dispatcher di comandi che indirizzerà il comando al gestore dei comandi designato. Questo gestore di comandi convalida prima il comando e, se tutto è accettabile, esegue il comando.

Esempio concreto: AddCommentToArticleCommandHandler riceve AddCommentToArticleCommand, che contiene ArticleId, CommentText e EmailAddress.

Primo; deve avvenire la convalida, come: - controlla se l'articolo esiste - controlla se l'articolo non è chiuso - controlla se il testo del commento è compilato e tra 20 e 500 caratteri - controlla se l'indirizzo email è compilato e ha un formato valido.

Mi chiedo dove mettere questa convalida?

1 / nel gestore dei comandi stesso. Tuttavia, non può essere riutilizzato in altri gestori di comandi.

2 / nell'entità dominio. Ma poiché un'entità di dominio non è a conoscenza di repository o servizi, non può eseguire la convalida necessaria (non può verificare se esiste un articolo). D'altra parte, se l'entità non contiene la logica, diventa un semplice contenitore di dati, che non segue i principi DDD.

3 / il gestore comandi utilizza i validatori, in modo che la convalida possa essere riutilizzata in altri gestori comandi.

4 / Altri meccanismi?

Sto cercando la catena di responsabilità per questo esempio particolare e quali oggetti (entità, repository, ...) svolgono un ruolo in esso.

Hai idee su come implementarlo, a partire dal gestore dei comandi fino ai repository?


"Ma poiché un'entità di dominio non è a conoscenza di repository o servizi, non può eseguire la necessaria convalida"? Perchè no? Quale principio di DDD richiede questo?
S.Lott

Ho letto dappertutto che un'entità non dovrebbe conoscere i repository o altro.
L-Four,

Potete fornire un preventivo, un link o un esempio di ciò che - in particolare - avete letto? Non sappiamo quali descrizioni di DDD stai leggendo.
S.Lott


Jimmy Bogard ha condiviso alcune opinioni su questo argomento ... lostechies.com/jimmybogard/2009/02/15/validation-in-a-ddd-world
Mayo

Risposte:


4

Penso che in questo caso sia necessario separare due tipi di validazione; convalida del dominio e convalida dell'applicazione .

La convalida dell'applicazione è quella che hai quando verifichi che la proprietà del comando 'text' è compresa tra 20 e 200 caratteri; quindi lo convalidi con la GUI e con un validatore del modello di vista che viene eseguito anche sul server dopo un POST. Lo stesso vale per l'e-mail (a proposito, spero che tu realizzi che un'e-mail come `32.d +" Hello World .42 "@ mindomän.local" è valida secondo la RFC).

Quindi hai un'altra convalida; controlla che l'articolo esista: devi porti la domanda sul perché l'articolo non dovrebbe esistere se esiste effettivamente un comando inviato dalla GUI che riguarda il collegamento di un commento. La tua GUI è stata infine coerente e hai una radice aggregata, l'articolo, che può essere fisicamente cancellata dall'archivio dati? In tal caso, basta spostare il comando nella coda degli errori perché il gestore comandi non riesce a caricare la radice aggregata.

Nel caso sopra, avresti un'infrastruttura che gestisce i messaggi velenosi, ad esempio riproverebbero il messaggio 1-5 volte e poi lo sposterebbero in una coda di avvelenamento dove potresti ispezionare manualmente la raccolta di messaggi e rispedire quelli pertinenti. È una buona cosa da monitorare.

Quindi ora abbiamo discusso:

  • Convalida dell'applicazione

    • Con javascript nella GUI
    • Con convalida MVC sul server Web
  • Radice aggregata mancante + code di veleno

Che dire dei comandi non sincronizzati con il dominio? Forse hai una regola nella logica del tuo dominio che dice che dopo 5 commenti a un articolo, sono consentiti solo commenti inferiori a 400 caratteri, ma un ragazzo era troppo tardi con il 5 ° commento ed è diventato il 6 ° - La GUI non l'ha presa perché non era coerente con il dominio nel momento in cui inviava il suo comando - in questo caso si verifica un "errore di convalida" come parte della logica del dominio e si restituisce l'evento di errore corrispondente.

L'evento potrebbe essere sotto forma di un messaggio su un broker di messaggi o sul proprio spedizioniere personalizzato. Il server Web, se l'applicazione è monolitica, potrebbe ascoltare in modo sincrono sia un evento di successo che l'evento di errore menzionato e visualizzare la vista / parziale appropriata.

Spesso hai un evento personalizzato che significa fallimento per molti tipi di comandi, ed è questo evento a cui ti iscrivi dal punto di vista del web server.

Nel sistema su cui stiamo lavorando, stiamo facendo una richiesta-risposta con comandi / eventi su un bus di messaggi + broker MassTransit + RabbitMQ e abbiamo un evento in questo particolare dominio (che modella in parte un flusso di lavoro) che è chiamato InvalidStateTransitionError. La maggior parte dei comandi che tentano di spostarsi lungo un bordo nel grafico dello stato può causare questo evento. Nel nostro caso, stiamo modellando la GUI secondo un paradigma alla fine coerente, e quindi inviamo l'utente a una pagina di "comando accettato" e in seguito lasciamo che le visualizzazioni del server Web si aggiornino passivamente attraverso le sottoscrizioni di eventi. Va detto che stiamo anche facendo il sourcing degli eventi nelle radici aggregate (e lo faremo anche per le saghe).

Quindi, vedete, molte delle convalide di cui state parlando sono in realtà convalide del tipo di applicazione, non una vera logica di dominio. Non c'è nessun problema ad avere un modello di dominio semplice se il tuo dominio è semplice ma stai facendo DDD. Mentre continui a modellare il tuo dominio, tuttavia, scoprirai che il dominio potrebbe non essere così semplice come si è scoperto. In molti casi la radice / entità aggregata potrebbe semplicemente accettare un'invocazione di metodo causata da un comando e modificare parte del suo stato senza nemmeno eseguire alcuna convalida, specialmente se ti fidi dei tuoi comandi come faresti se li convalidassi nel server Web che tu controlli.

Posso consigliare di guardare le due presentazioni su DDD della Norwegian Developer Conference 2011 e anche la presentazione di Greg a Öredev 2010 .

Saluti, Henke


Grazie! Una cosa sulla convalida: al momento, questa convalida viene attivata dall'interfaccia utente (inviando una richiesta di convalida (comando) al servizio), che utilizza la convalida () dell'entità commento stessa. Quindi, se il comando è valido, il client emette un comando Execute, che eseguirà nuovamente Validate () per essere sicuro, e se valido viene eseguito il comando effettivo. Quindi la validazione principale viene fatta dall'entità Comment, perché in ogni contesto la validazione sarà la stessa (l'email deve essere sempre valida, il testo del commento non troppo lungo, ecc.) È un buon approccio?
L-Four,

La convalida che sembra stia descrivendo non mi sembra giustificata a modellarla con un protocollo di convalida in due fasi: convalidare i parametri di invocazione del metodo sull'entità come se si testasse in un test unitario, ma a parte questo; il livello applicazione / GUI potrebbe facilmente convalidare le regole che stai descrivendo senza inviare comandi al dominio. Imo. A meno che il client non sia dannoso, il comando dovrebbe funzionare. Se il client è dannoso, il comando ha esito negativo e il modello di lettura non riceve mai un evento corrispondente ed è possibile controllare il comando problematico nella coda degli errori.
Henrik,

Nell'interfaccia utente (ASP.NET MVC) sto usando gli attributi di validazione per fare tutta la validazione. Quindi, se questa convalida ha esito positivo, non devo convalidare nuovamente sul dominio, ma eseguire semplicemente il comando?
L-Four,

1
Sì, esegui il comando ma assicurati che il comando non sia non valido sia nel livello applicazione che nel dominio.
Henrik,

0

EDIT: WaybackMachine link: http://devlicio.us/blogs/billy_mccafferty/archive/2009/02/17/a-response-to-validation-in-a-ddd-world.aspx

Non c'è una risposta pat.

Ci sono due scenari di progetto chiari che mi vengono in mente quando provo a rispondere dove dovrebbe convivere la convalida. Il primo è in cui un livello DTO viene utilizzato per trasferire informazioni tra i livelli vista e dominio. Ad esempio, potresti avere un oggetto Cliente nel tuo livello di dominio e un DTO cliente associato in un altro livello su cui mappare le informazioni del Cliente, per poi dare alla vista la presentazione delle informazioni del Cliente all'utente.

Il secondo scenario è un progetto in cui le entità all'interno del livello di dominio sono condivise direttamente con la vista per presentare i dati all'utente. Ad esempio, invece di mantenere un livello DTO separato e mappare l'oggetto dominio sui DTO da assegnare alla vista, alla vista potrebbe essere assegnato direttamente l'oggetto Cliente. Quindi, invece di parlare tramite un DTO gestito separatamente per mostrare il nome di un cliente, la vista richiederebbe semplicemente al cliente stesso l'oggetto le informazioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.