Am gasit acest articol interesant care explica pe intelesul tuturor conceptul de CQRS. Unul din lucrurile pe care vreau sa le invat in 2018 sunt design patterns.
Nu toate !
Doar cele mai uzuale.
Este scris de tekkie !
PS: Revista Today Software Magazine are articole interesante care merita sa fie citite.
Mulțumesc pentru aprecieri, mă bucur să aud că am reușit să mă exprim destul de bine încât să explic conceptul, care e unul destul de greu de înțeles și de internalizat pentru cei care sunt obișnuiți cu CRUD.
CQRS este deosebit de util pentru a înțelege cum se implementează partea de performanță, fără a tot adăuga layere de tehnologie suplimentare. Eu îl apreciez și pentru separarea codului, astfel probabilitatea de a introduce buguri e mai mică.
Lucrez la o aplicatie in .net(win forms) si am o clasa care se chama “DatabaseOps” cu tot felul de metode CRUD. Ar fi ok daca as separa metodele ce tin de aducere de date din bd intr-o clasa dedicata ?
Cum ai facut aici
public class EmployeeReadService {
public function obtineAngajat($id) { /* ... */}
public function obtineAngajatiiInConcediu() { /* ... */}
}
// foloseste acelasi model Angajat
public class EmployeeWriteService {
public function angajeaza(Persoana $persoana, $laData) { /* ... */}
public function promoveaza($id, $noulPost, $deLaData) { /* ... */}
public function maresteRemuneratia($id, $suma, $delaData) { /* ... */}
public function concediaza($id, $laData) { /* ... */}
public function modificaAdresa($id, Adresa $adresa) { /* ... */}
}
CQRS e un concept cam bizar şi nu cred că ar trebui folosit doar ca să te afli în treabă Dar nici să ai o clasă generică de genul DatabaseOps unde să ai tot felul de metode random nu cred că e o idee prea bună.
Asta este problema sunt multe metode si ma incurc in ele. Am inceput-o in primavara, n-am mai facut nimic timp de 6 luni si m-am reapucat sa lucrez la ea din decembrie. Nu este complicata ca functionalitate si logica, dar incepe sa se adune cod
Dacă eşti tentat să faci o clasă cu tot felul de metode random, probabil nu ai structurat bine problema. Mie imi place să lucrez cu entităţi, de genul ăsta:
class Factura {
public load(int id = 0);
public save();
std::string serie;
int nr;
std::string data;
std::list<Produs> produse;
... alte câmpuri ...
}
Ca să decuplez partea de date de GUI de regulă folosesc adapter pattern.
Completare, în cazul celor mai multe proiecte, CQRS este probabil ceea ce se numeşte overengineering. Eu mereu am grijă să nu fac designul mai complicat decât este necesar, din motive de “maintanbilitate” şi de multe ori din considerente practice de genul “consum de memorie” şi “timp de execuţie”. Chiar dacă RAM-ul şi capacitatea de procesare sunt ieftine în zilele noastre, clienţii (cel puţin unii dintre ei) tot vor aprecia fiecare megabyte şi fiecare milisecundă economisită.
Inteleg la ce te referi. Nu doresc sa schimb din temelii aplicatia dpdv arhitectural. Mai mult o organizare a codului, este ceea ce vreau sa fac. Sunt adeptul pricipiului KISS.
N-as putea sa spune ca este overengineering trecerea de la
// foloseste model Angajat
public class EmployeeService {
public function obtineAngajat($id) { /* ... */}
public function obtineAngajatiiInConcediu() { /* ... */}
public function angajeaza(Persoana $persoana, $laData) { /* ... */}
public function promoveaza($id, $noulPost, $deLaData) { /* ... */}
public function maresteRemuneratia($id, $suma, $delaData) { /* ... */}
public function concediaza($id, $laData) { /* ... */}
public function modificaAdresa($id, Adresa $adresa) { /* ... */}
}
la
// foloseste acelasi model Angajat
public class EmployeeReadService {
public function obtineAngajat($id) { /* ... */}
public function obtineAngajatiiInConcediu() { /* ... */}
}
// foloseste acelasi model Angajat
public class EmployeeWriteService {
public function angajeaza(Persoana $persoana, $laData) { /* ... */}
public function promoveaza($id, $noulPost, $deLaData) { /* ... */}
public function maresteRemuneratia($id, $suma, $delaData) { /* ... */}
public function concediaza($id, $laData) { /* ... */}
public function modificaAdresa($id, Adresa $adresa) { /* ... */}
}
Nu imi place sa imi bat joc de resursele de ram si timpi de procesor. Chiar daca sunt din plin in zilele noastre.
PS: In niciun caz nu sunt adeptul overengineering - ului si. Sunt la inceput. Imi place sa invat concepte care m-ar putea ajuta pe viitor.
PPS: Daca vrei, facem topic separat !
When implementing a Bounded Context, you can use different architectural styles:
Spaghetti Architecture: I’m a Rasmus Fanboy (aka fuck phptherightway)
Framework Fanboy: I’m a Fabpot Fanboy (aka coupled to my framework)
Hexagonal Architecture: I’m an Alaistar Cokburn Fanboy (aka decoupled from my framework)
Hexagonal Architecture with CQRS: I’m an Alaistar Cokburn and Martin Fowler Fanboy (aka decoupled with performance tunnings)
Event Sourcing with CQRS: I’m a Greg Young Fanboy (aka I do not know what I’m doing)
Acum, știm că nu exista un silver bullet și că fiecare are metoda sa de a aborda o problemă, însă cred că nu putem aborda o anumită arhitectură în afară de spaghetti/framework fără a avea mai înainte o sesiune de brainstorming între echipa tehnică: developer,tester,ux și domain experts/product owner că să putem trece dincolo de o gândire crud/structurală-relațională și să trecem spre o gândire bazată pe mesaje desfășurate în timp în domeniul respectiv.