În trecut, am observat adesea o abordare comună în care dezvoltatorii (inclusiv eu, desigur) foloseau același API atât pentru citire, cât și pentru scrieri pentru fiecare caz. Cu atât mai mult, ne-am bazat frecvent pe aceeași sursă de date, cum ar fi MySQL/PostgreSQL, pentru a gestiona ambele operațiuni.
Aceasta înseamnă să scrieți în aceleași coloane și să citiți din ele, ceea ce duce adesea la lupte cu optimizarea indicilor pe câmpurile care au fost interogate intens.
Așa că, de exemplu, ne-am trezi că modificăm frecvent indecșii pentru a se adapta la noi filtre sau a îmbunătăți performanța interogărilor, iar câmpurile utilizate cu operatori precum LIKE au reprezentat provocări deosebite datorită impactului lor asupra performanței.
Aceste modificări duc adesea la ajustări suplimentare ale backend-ului, inclusiv modificarea API-urilor pentru a expune funcționalitatea actualizată, timpi măsurați din cauza JOIN-urilor suplimentare și așa mai departe...
Pentru a răspunde provocării legate de adăugarea de noi filtre și lucruri în API, au existat încercări de optimizare a procesului folosind instrumente și standarde precum Apicalypse și, desigur, GraphQL .
Aceste soluții urmăreau să eficientizeze generarea de interogări API și să reducă efortul manual necesar pentru implementarea de noi filtre și funcționalități, oferind o abordare mai dinamică a gestionării accesului la date, dar aveau o curbă de învățare ridicată.
Odată cu creșterea CQRS (Command Query Responsibility Segregation), a început să apară o nouă abordare. Această mentalitate a încurajat utilizarea surselor separate pentru scrieri și citiri. Scrierile ar putea emite evenimente, iar citirile ar putea construi vederi din acele evenimente în locuri dedicate. Chiar dacă citirile și scrierile au fost gestionate în cadrul aceleiași baze de date (dar tabele diferite), această separare a adus beneficii semnificative și, desigur, a putut scăpa de a doua provocare - JOIN-urile și interogările de căutare pe modele de domenii, deoarece modelele de citire sunt de obicei într-o formă de JSON denormalizate.
Totuși, acest lucru a ridicat o altă problemă. Cu citiri, a trebuit să scalam scrierile, ceea ce înseamnă că singurul motiv pentru care a trebuit să scalam instanțe ale aplicației noastre de la X la Y a fost din cauza citirilor. Această problemă ar putea fi parțial atenuată cu memorarea în cache, iar în lumea microserviciilor, am putea avea microservicii dedicate pentru citiri.
Dar...
Totuși, aceasta nu a fost o soluție ideală pentru alte stiluri arhitecturale, cum ar fi monoliții modulari, unde o astfel de separare ar putea să nu se alinieze bine cu filosofia de proiectare a sistemului. Un alt lucru a fost că, atunci când API-ul era jos, întregul produs era în jos și, ținând cont de faptul că majoritatea produselor se bazează pe mai multe citiri decât scrieri, ar putea avea un impact inutil asupra afacerii (în afară de API-ul inactiv, desigur ;) )
Deci, ce se întâmplă dacă am putea întreba acele „vizualizări”, cunoscute și ca modele de citire, direct, fără a implica API-ul și a gestiona încărcăturile? Aici intră în joc soluții precum Meilisearch , AppSearch și altele, utilizând un model numit „Cheie Valet”. Folosind acest model, front-end-urile pot accesa direct modele optimizate pentru citire, reducând dependența de API-urile backend. Desigur, frontend-ul trebuie să „cere” API-ului „Cheia Valet”, dar frontend-ul poate stoca cheile în cache, așa că, chiar și atunci când API-ul este oprit, frontend-ul poate comunica și afișa conținut.
Cu această abordare, ne putem concentra pe baza de date de citire și nu ne putem îngrijora de gestionarea traficului pentru citiri în API-ul nostru. „Cheia Valet” furnizată frontend-ului prin intermediul API-ului nostru este securizată într-un mod în care frontend-ul nu o poate modifica. Include filtre și indici predefiniti.
Dacă frontend-ul necesită capacități suplimentare, le poate solicita prin intermediul API-ului, unde API-ul poate valida dacă le permite. Sunt încă mai puține apeluri.
Câțiva profesioniști pe care le văd sunt:
Dar, există întotdeauna dezavantaje:
Deci, această abordare nu este un glonț de argint și introduce propriul set de provocări, dar dacă sunteți de acord cu un minus, atunci o mică schimbare pe front-end probabil nu va necesita implicarea echipei backend, eficientizarea procesului de dezvoltare și îmbunătățirea agilitatea generală și, desigur, scalabilitatea ar trebui să fie mai ușoare.