L'ingegnerizzazione del CQRS non è?


15

Ricordo ancora i bei vecchi tempi dei repository. Ma i depositi diventavano brutti con il tempo. Quindi il CQRS è diventato mainstream. Erano carini, erano una boccata d'aria fresca. Ma recentemente mi sono chiesto ripetutamente perché non mantengo la logica corretta nel metodo di azione di un controllore (specialmente in Web Api in cui l'azione è una specie di gestore di comandi / query in sé).

In precedenza avevo una risposta chiara per questo: lo faccio per i test in quanto è difficile testare il controller con tutti quei singleton non smontabili e la brutta infrastruttura ASP.NET complessiva. Ma i tempi sono cambiati e al giorno d'oggi le classi di infrastruttura ASP.NET sono molto più facili da testare le unità (specialmente in ASP.NET Core).

Ecco una tipica chiamata WebApi: viene aggiunto il comando e i client SignalR ne vengono informati:

public void AddClient(string clientName)
{
    using (var dataContext = new DataContext())
    {
        var client = new Client() { Name = clientName };

        dataContext.Clients.Add(client);

        dataContext.SaveChanges();

        GlobalHost.ConnectionManager.GetHubContext<ClientsHub>().ClientWasAdded(client);
    }
}

Posso facilmente testare l'unità / deriderlo. Inoltre, grazie a OWIN, posso configurare i server WebApi e SignalR locali ed effettuare un test di integrazione (e piuttosto velocemente).

Di recente ho sentito sempre meno motivazione a creare ingombranti gestori di comandi / query e tendo a mantenere il codice nelle azioni di Web Api. Faccio un'eccezione solo se la logica è ripetuta o è davvero complicata e voglio isolarla. Ma non sono sicuro se sto facendo la cosa giusta qui.

Qual è l'approccio più ragionevole per la gestione della logica in una tipica applicazione ASP.NET moderna? Quando è ragionevole spostare il codice nei gestori di comandi e query? Ci sono schemi migliori?

Aggiornare. Ho trovato questo articolo sull'approccio DDD-lite. Quindi sembra che il mio approccio allo spostamento di parti complicate del codice in gestori di comandi / query possa essere chiamato CQRS-lite.


1
Non riesco a vedere come CQRS rende le cose ancora più testabili / è di alcun aiuto con i singoli / controller / etc. Sono in gran parte indipendenti. Inoltre, stai ancora creando un comando nel tuo esempio (contatore?), Che è strano.
guillaume31,

Se mantieni il tuo codice con il codice dell'infrastruttura (cioè ottieni l'indirizzo IP del client), è difficile testarlo. Se si isola la logica in una query / comando, è molto più semplice. L'esempio di codice era un po 'confuso, quindi l'ho aggiornato.
Siberian

1
Query e comandi non hanno logica. Sono stupidi DTO. Quindi hai i tuoi gestori di comandi / query , ma sono esattamente gli stessi dei servizi applicativi, degli interlocutori, dei servizi alle imprese, lo chiami ... in un contesto non CQRS. Posizionare la logica del caso applicativo / d'uso in un oggetto separato rispetto al Controller non è una cosa specifica CQRS.
guillaume31,

Inoltre, la questione della dipendenza iniettata Singleton vs è completamente ortogonale al CQRS. Potresti avere un controller che chiama un singleton CommandHandler che chiama un singleton repository ...
guillaume31

1
@ guillaume31, CQRS tende ad essere più ingombrante delle chiamate al servizio repository / aplication. Di solito hanno bisogno di 2-3 classi (es. Query, queryhandler, queryresult), infrastruttura, ecc.
SiberianGuy

Risposte:


17

CQRS è un modello relativamente complicato e costoso? Sì.

È troppo ingegneristico? Assolutamente no.

Nell'articolo originale in cui Martin Fowler parla di CQRS puoi vedere molti avvertimenti sul non usare CQRS dove non è applicabile:

Come ogni modello, CQRS è utile in alcuni punti, ma non in altri.

Il CQRS è un significativo salto mentale per tutti gli interessati, quindi non dovrebbe essere affrontato a meno che il beneficio non valga la pena .

Mentre mi sono imbattuto in usi di successo di CQRS, finora la maggior parte dei casi in cui mi sono imbattuto non è stata così buona ...

Nonostante questi vantaggi, dovresti essere molto cauto sull'uso di CQRS .

... l'aggiunta di CQRS a tale sistema può aggiungere una complessità significativa .

La mia enfasi sopra.

Se la tua applicazione utilizza CQRS per tutto, che non è CQRS troppo ingegnerizzato, è la tua applicazione. Questo è un modello eccellente per risolvere alcuni problemi specifici, in particolare le applicazioni ad alte prestazioni / alto volume in cui la concorrenza in scrittura può essere una delle principali preoccupazioni.

E potrebbe non essere l'intera applicazione, ma solo una piccola parte di essa.

Un esempio dal vivo del mio lavoro, impieghiamo CQRS nel sistema di inserimento ordini, dove non possiamo perdere alcun ordine, e abbiamo picchi in cui migliaia di ordini provengono contemporaneamente da fonti diverse, in alcune ore specifiche. CQRS ci ha aiutato a mantenere il sistema attivo e reattivo, consentendoci nel contempo di ridimensionare bene i sistemi di backend per elaborare questi ordini più velocemente quando necessario (più server backend) e più lenti / economici quando non necessari.

CQRS è perfetto per il problema in cui diversi attori collaborano nella stessa serie di dati o scrivono sulla stessa risorsa.

Oltre a ciò, diffondere un modello creato per risolvere un singolo problema a tutti i tuoi problemi ti creerà solo altri problemi.


Alcuni altri link utili:

http://udidahan.com/2011/04/22/when-to-avoid-cqrs/

http://codebetter.com/gregyoung/2012/09/09/cqrs-is-not-an-architecture-2/


3
Concordare tutto tranne la parte "schema relativamente complicato e costoso". CQRS sta solo separando le letture dalle scritture. Puoi farlo con nastro adesivo, zero middleware / strumenti complicati e mantenendo lo stesso database di prima, per tutto ciò che interessa.
guillaume31,

@ guillaume31, questo è un punto giusto. Penso che sia abbastanza correlato all'idea della domanda originale: "in Api Web in cui l'azione è una sorta di comando / query in sé". Ma hai visto qualche esempio CQRS funzionante (preferibilmente github) che non usa classi separate per comandi e query? Questo è quello che trovo quando provo a vedere come altre persone implementano CQRS in .NET.
Siberian

Sì, ma non è troppo ingegneristico. È la premessa di base del modello: separare le query dalle scritture, leggere il modello dal modello di dominio.
guillaume31,

L'approccio CQRS potrebbe essere più di uccidere in un sacco di contesti, ma questa è una storia completamente diversa. Non è eccessivo a causa di tutti i piccoli dettagli tecnici che erroneamente attribuisci a CQRS nella tua Q, è eccessivo perché non hai sempre bisogno di ciò che ti offre CQRS.
guillaume31,

Penso che il punto di Fowler sia valido solo fino a un certo punto. SQL Views è un tipo di CQRS ed è con noi da secoli e nessuno dice che sono molto complessi. Dal momento che ci sono molti gusti di CQRS, ovvero proiezioni di approvvigionamento di eventi, che potrebbero essere visti come complessi in alcune aree, mentre possono essere banali in un'altra.
Alexey Zimarev,

3

CQRS non è un sostituto uno-a-uno per i repository, proprio perché è un modello complesso e costoso che è utile solo in alcuni casi.

Ecco cosa ha da dire Udi Dahan in merito:

La maggior parte delle persone che usano CQRS (e anche Event Sourcing) non avrebbero dovuto farlo.

[...]

Mi dispiace dire che la maggior parte delle applicazioni di esempio che vedrai online mostrano che CQRS è architettonicamente errato. Sarei anche estremamente diffidente nei confronti dei framework che ti guidano verso un modello CQRS radice aggregato in stile entità.

( fonte )

Martin Fowler:

[...] dovresti essere molto cauto sull'uso di CQRS . Molti sistemi di informazione si adattano bene alla nozione di base di informazioni che viene aggiornata nello stesso modo in cui viene letta, l'aggiunta di CQRS a tale sistema può aggiungere una notevole complessità.

( fonte )

Infine, Greg Young:

CQRS può essere chiamato un modello architettonico.

[...]

Questo è molto importante per capire che la maggior parte dei motivi architettonici non è buona da applicare ovunque. Se vedi modelli architettonici in una linea guida architettonica, probabilmente hai un problema

[...]

Il più grande fallimento che vedo dalle persone che usano il sourcing di eventi è che provano a usarlo ovunque.

( fonte )

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.