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

16

Sto prendendo in considerazione un progetto per migrare parte del nostro SOA basato su WCF su un modello di bus di servizio (probabilmente nServiceBus) e usando alcuni pub-sub di base per ottenere Comando-Query Separation .

Non sono nuovo per SOA, o anche per i modelli di bus di servizio, ma confesso che fino a poco tempo 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 mentre elimini molti degli ovvi inconvenienti (in particolare la mancanza di un adeguato supporto transazionale).

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

As we get larger entities with more fields on them, we also get more actors working with those same entities, and the higher the likelihood that something will touch some attribute of them at any given time, increasing the number of concurrency conflicts.

[...]

A core element of CQRS is rethinking the design of the user interface to enable us to capture our users’ intent such that making a customer preferred is a different unit of work for the user than indicating that the customer has moved or that they’ve gotten married. Using an Excel-like UI for data changes doesn’t capture intent, as we saw above.

-- Udi Dahan, Clarified CQRS

Dalla prospettiva descritta nella citazione, è difficile discutere con quella logica. Ma sembra andare controcorrente rispetto alle SOA. Un SOA (e in generale i servizi in generale) dovrebbe occuparsi di messaggi a grana grossa in modo da ridurre al minimo le chatter di rete - tra molti altri vantaggi.

Mi rendo conto che le chatter di rete sono un problema minore quando si dispone di sistemi altamente distribuiti con un buon accodamento dei messaggi e nessuno dei bagagli di RPC, ma non sembra saggio smentire completamente il problema. Udi sembra quasi dire che ogni modifica di attributo (cioè l'aggiornamento del 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 servizio web tradizionale.

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 è lento, lento, lento e l'hardware del database OLTP è il più costoso di tutti su scala / fuori.

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

Se no, allora come si può decidere quale dovrebbe essere il "giusto livello" di granularità in un comando? C'è un punto "standard" che può essere utilizzato come punto di partenza - una specie di 3NF nei database - e deviare solo quando un'accurata profilazione suggerisce un beneficio prestazionale potenzialmente significativo?

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

    
posta Aaronaught 08.04.2011 - 17:24
fonte

2 risposte

6

Sull'argomento "modifica di ogni attributo"

Penso che tu abbia perso il punto. Mr. Udi Dahan sta dicendo che dovresti catturare l'intento dell'utente come un comando. Un utente finale è interessato a essere in grado di indicare che un cliente si è trasferito. A seconda del contesto in cui il comando può contenere un'identificazione del cliente, il nuovo indirizzo (diviso in street, streetnumber, zipcode, ...), facoltativamente un nuovo numero di telefono (non raro quando ti muovi, forse meno con tutti questi cellulari) . Questo è difficilmente un attributo. Una domanda migliore è "come posso progettare i comandi?". Li disegni da una prospettiva comportamentale. Ogni caso d'uso, flusso, compito che un utente finale sta tentando di completare, verrà catturato in uno o più comandi. I dati forniti con questi comandi vengono in modo naturale, quando inizi a ragionare su di loro in modo più dettagliato. La cosa a cui prestare attenzione sono i dati che vengono interpretati come "controllo del flusso logico" sul lato server. Che potrebbe essere un'indicazione che è necessario dividere il comando. Spero che tu non abbia mai trovato standard riguardo alla granularità del comando. Buona domanda però!

    
risposta data 08.04.2011 - 18:13
fonte
2

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

I comandi devono corrispondere a azioni / casi d'uso che l'utente fa con il sistema ed esprimere l'intento dell'azione piuttosto che dire semplicemente cambiare questo. Inoltre, potrebbe sembrare che sia più fine ma potrebbe essere molto più grossolano di quanto non appaia prima. Ad esempio, l'aggiornamento allo stato dell'oro potrebbe comportare la modifica di diversi attributi e un numero di altri aggregati potrebbe persino rispondere e cambiare in risposta all'evento corrispondente.

CQRS tratta di acquisire la lingua dell'azienda nel livello di servizio in modo che l'interfaccia utente non debba preoccuparsi di ciò che accade quando eseguo l'aggiornamento dello stato dell'oro o la spedizione è stata contrassegnata come non recapitabile dal corriere o dal dipendente è stato promosso direttore del gruppo tecnologico. Beh, tecnicamente sto parlando di Event Sourcing ora ma tu hai la mia direzione. Ci sono più messaggi distinti ma non sono necessariamente più granulosi del CUD standard.

    
risposta data 02.04.2012 - 18:01
fonte

Leggi altre domande sui tag