Quanto deve essere granulare un comando in un modello CQ [R] S?


17

Sto prendendo in considerazione un progetto per migrare parte della nostra SOA basata su WCF su un modello di bus di servizio (probabilmente nServiceBus) e utilizzare alcuni pub-sub di base per ottenere la separazione tra query e comandi .

Non sono nuovo di SOA, o nemmeno di modelli di bus di servizio, ma confesso che fino a poco tempo fa il mio concetto di "separazione" era limitato al mirroring e alla replica del database "run-of-the-mill". Tuttavia, sono attratto dall'idea perché sembra fornire tutti i vantaggi di un sistema alla fine coerente , eludendo molti degli ovvi inconvenienti (in particolare la mancanza di un adeguato supporto transazionale).

Ho letto molto sull'argomento di Udi Dahan, che è fondamentalmente il guru delle architetture ESB (almeno nel mondo Microsoft), ma una cosa che dice mi ha davvero confuso:

Man mano che otteniamo entità più grandi con più campi su di esse, otteniamo anche più attori che lavorano con quelle stesse entità e maggiore è la probabilità che qualcosa tocchi un loro attributo in qualsiasi momento, aumentando il numero di conflitti di concorrenza.

[...]

Un elemento chiave di CQRS è ripensare il design dell'interfaccia utente per consentirci di catturare l'intenzione dei nostri utenti in modo tale che rendere preferito un cliente sia una diversa unità di lavoro per l'utente rispetto all'indicare che il cliente si è spostato o che ha ottenuto sposato. L'uso di un'interfaccia utente simile a Excel per le modifiche ai dati non cattura l'intento, come abbiamo visto sopra.

- Udi Dahan, chiarito CQRS

Dal punto di vista descritto nella citazione, è difficile discutere con quella logica. Ma sembra andare controcorrente rispetto alle SOA. Una SOA (e in realtà i servizi in generale) dovrebbero occuparsi di messaggi a grana grossa in modo da ridurre al minimo le chiacchiere di rete - tra molti altri vantaggi.

Mi rendo conto che le chiacchiere di rete sono meno un problema quando hai sistemi altamente distribuiti con una buona coda di messaggi e nessuno del bagaglio di RPC, ma non sembra saggio eliminare completamente il problema. Sembra quasi che Udi stia dicendo che ogni cambiamento di attributo (ad es. Aggiornamento di campo) dovrebbe essere il suo comando, che è difficile immaginare nel contesto di un utente che potenzialmente aggiorna centinaia o migliaia di entità e attributi combinati come spesso accade con un tradizionale servizio web.

Un aggiornamento batch in SQL Server può richiedere una frazione di secondo, data una buona query altamente parametrizzata, un parametro con valori di tabella o un inserimento di massa in una tabella di staging; l'elaborazione di tutti questi aggiornamenti uno alla volta è lenta, lenta, lenta e l'hardware del database OLTP è il più costoso di tutti da scalare / aumentare.

C'è un modo per conciliare queste preoccupazioni concorrenti? Ci sto pensando nel modo sbagliato? Questo problema ha una soluzione ben nota nel mondo CQS / ESB?

In caso contrario, come si può decidere quale dovrebbe essere il "giusto livello" di granularità in un comando? C'è qualche "standard" che si può usare come punto di partenza - una specie di 3NF nei database - e deviare solo quando un'attenta profilazione suggerisce un vantaggio potenzialmente significativo in termini di prestazioni?

O è forse una di quelle cose che, nonostante parecchie opinioni forti espresse da vari esperti, è davvero solo una questione di opinione?

Risposte:


7

Sull'argomento "modifica di ogni attributo"

Penso che tu abbia perso il punto. Il signor Udi Dahan sta dicendo che dovresti catturare l'intenzione dell'utente come comando. Un utente finale si preoccupa di poter indicare che un cliente si è trasferito. A seconda del contesto in cui il comando potrebbe contenere un'identificazione cliente, il nuovo indirizzo (suddiviso in via, numero civico, codice postale, ...), opzionalmente un nuovo numero di telefono (non insolito quando ci si sposta - forse meno con tutti questi telefoni cellulari) . Questo non è certo un attributo. Una domanda migliore è "come posso progettare i comandi?". Li progetti da una prospettiva comportamentale. Ogni caso d'uso, flusso, attività che un utente finale sta tentando di completare, verrà acquisito in uno o più comandi. I dati forniti con questi comandi vengono naturalmente, man mano che inizi a ragionare su di essi in modo più dettagliato. La cosa a cui prestare attenzione sono i dati che vengono interpretati come "potrebbe essere un'indicazione che è necessario suddividere il comando. Spero che non troverai mai quello standard per quanto riguarda la granularità di comando. Buona domanda però!


Questa definizione mi sembra ancora molto arbitraria; il modello concettuale di un CSR può raggruppare insieme lo stato preferito e lo stato marziale nello stesso modo in cui si raggruppano indirizzo e codice postale insieme. Non intendo dividere i peli, mi sembra solo che per capire davvero se sono comportamenti diversi, devi essere in grado di prevedere gli effetti a valle e OTOH l'intera idea di ESB e CQS e pub / sub è che non dovresti sapere o preoccuparti di ciò che accade a valle. Grazie per la tua risposta, lo apprezzo molto, anche se non posso dire di sentirmi più illuminato finora ...
Aaronaught

@Aaronaught: la definizione è arbitraria. La granularità di un comando dovrebbe essere qualunque cosa abbia senso per il tuo particolare scenario . Non esiste una taglia unica. Esistono diverse linee guida, come la corrispondenza dei comandi per utilizzare casi o attività o azioni disponibili nell'interfaccia utente - un'altra è quella di preferire comandi più granulari rispetto a comandi meno granulari (particolarmente come Yves ha detto di diffidare dei dati interpretati come flusso di controllo logico) - ma nessuna regola dura e veloce. Esiste uno scenario reale in cui "un utente potenzialmente aggiorna centinaia o migliaia di entità e attributi combinati"?
Quentin-starin

Questo è il punto! Non raggruppare insieme. Dividi in base al comportamento! Non inserire dati nel comando che non si allineano con l'intento del comando / utente finale. E non si tratta di sistemi a valle.
Yves Reynhout,

@qes: Nei nostri sistemi ci sono diversi scenari simili, molto reali e molto necessari. Per dirlo nel modo più semplice possibile, devono modificare intere sequenze di dati e queste sequenze hanno senso solo come sequenze. Naturalmente di solito non apportano queste modifiche record per record, applicano alcuni algoritmi alla maggior parte di esso e quindi correggono alcune eccezioni. Forse questo non è uno scenario appropriato per CQS, ma quella decisione è solo un sottoinsieme della mia domanda più ampia.
Aaronaught l'

1
@qes: Abbastanza giusto, e questa è una risposta in sé e per sé. Comprendo certamente il concetto di un'operazione logica (è così che vengono modellati i servizi esistenti), immagino che mi sia appena preoccupato che CQS sembri cambiare alcune delle regole su come dovresti definire un'operazione. La SOA "tradizionale" sembra iniziare dalla definizione più grossolana possibile e, se necessario, scendere dalla scala di astrazione; la mia comprensione del CQS finora sembra indicare il contrario, partire dalla definizione più granulare possibile e astratta se assomiglia troppo a RPC o flusso di controllo.
Aaronaught l'

2

Il messaggio che Udi sta cercando di comunicare è che CQRS è più di un semplice CRUD. Perché ho creato questo record? Perché sto cambiando questo record? Perché viene eliminato / contrassegnato come eliminato?

I comandi dovrebbero corrispondere ad azioni / casi d'uso che l'utente fa con il sistema ed esprimere l'intenzione dell'azione piuttosto che dire semplicemente cambiarlo. Inoltre, può sembrare a grana più fine, ma potrebbe essere molto più grossolano di quanto sembri. Ad esempio, l'aggiornamento allo status gold potrebbe comportare una modifica a più attributi e un certo numero di altri aggregati potrebbe persino rispondere e cambiare in risposta all'evento corrispondente.

CQRS riguarda l'acquisizione della lingua dell'azienda nel livello di servizio, quindi l'interfaccia utente non deve preoccuparsi di ciò che accade quando eseguo l'aggiornamento dello stato oro o la spedizione è stata contrassegnata come non consegnabile dal corriere o il dipendente è stato promosso al manager del gruppo tecnologico. Beh, tecnicamente sto parlando di Event Sourcing ora, ma hai la mia direzione. Esistono messaggi più distinti ma non sono necessariamente più precisi rispetto al CUD standard.

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.