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?