U prošlosti sam često primjećivao uobičajeni pristup gdje su programeri (uključujući i mene, naravno) koristili isti API za čitanje i pisanje u svakom slučaju. Štaviše, često smo se oslanjali na isti izvor podataka, kao što je MySQL/PostgreSQL, za rukovanje obje operacije.
To znači pisati u iste kolone i čitati iz njih, što često dovodi do problema s optimizacijom indeksa na poljima koja su bila jako upitna.
Tako, na primjer, često bismo prilagođavali indekse kako bismo prilagodili nove filtere ili poboljšali performanse upita, a polja koja se koriste s operatorima kao što je LIKE predstavljala su posebne izazove zbog svog utjecaja na performanse.
Ove promjene često dovode do daljnjih prilagođavanja pozadine, uključujući modificiranje API-ja kako bi se otkrila ažurirana funkcionalnost, mjerena vremena zbog dodatnih JOIN-ova i tako dalje...
Kako bi se riješio izazov u vezi sa dodavanjem novih filtera i stvari u API, bilo je pokušaja da se optimizira proces korištenjem alata i standarda kao što su Apicalypse i, naravno, GraphQL .
Ova rješenja su imala za cilj da pojednostave generiranje API upita i smanje ručni napor potreban za implementaciju novih filtera i funkcionalnosti, nudeći dinamičniji pristup rukovanju pristupom podacima, ali su imali visoku krivulju učenja.
Sa usponom CQRS (Command Query Responsibility Segregation), počeo je da se pojavljuje novi pristup. Ovakav način razmišljanja podstakao je upotrebu odvojenih izvora za pisanje i čitanje. Pisanje može emitovati događaje, a čitanje može izgraditi poglede iz tih događaja na određenim mjestima. Čak i kada bi se čitanjem i pisanjem upravljalo unutar iste baze podataka (ali različitim tabelama), ovo razdvajanje je donijelo značajne prednosti i, naravno, moglo se riješiti drugog izazova - JOIN-ova i upita za pretraživanje na modelima domena, kao što su modeli čitanja obično u obliku denormaliziranih JSON-ova.
Međutim, ovo je izazvalo još jedan problem. Kod čitanja, morali smo skalirati zapise, što znači da je jedini razlog zašto smo morali skalirati instance naše aplikacije od X do Y bio zbog čitanja. Ovaj problem bi se mogao djelomično ublažiti keširanjem, a u svijetu mikroservisa mogli bismo imati namjenske mikroservise za čitanje.
ali...
Ipak, ovo nije bilo idealno rješenje za druge arhitektonske stilove kao što su modularni monoliti, gdje takvo razdvajanje možda neće biti u skladu s filozofijom dizajna sistema. Druga stvar je bila, kada je API nestao, cijeli proizvod je nestao, a imajući na umu da se većina proizvoda oslanja na više čitanja nego upisivanja, to bi moglo nepotrebno utjecati na poslovanje (osim donjeg API-ja naravno ;) )
Dakle, šta ako bismo mogli pitati te "preglede", također poznate kao modeli čitanja, direktno bez uključivanja API-ja i rukovanja opterećenjima? Ovdje na scenu stupaju rješenja kao što su Meilisearch , AppSearch i druga, koristeći obrazac koji se zove "Valet Key". Koristeći ovaj obrazac, frontendovi mogu direktno pristupiti modelima optimiziranim za čitanje, smanjujući ovisnost o backend API-jima. Naravno, frontend i dalje mora "tražiti" API za "Valet ključ", ali frontend može keširati ključeve, tako da čak i kada je API isključen, frontend i dalje može komunicirati i prikazivati sadržaj.
Sa ovim pristupom, možemo se fokusirati na čitanu bazu podataka i ne brinuti o rukovanju prometom za čitanja u našem API-ju. "Valet Key" dostavljen frontendu preko našeg API-ja je osiguran na način da ga frontend ne može promijeniti. Uključuje unaprijed definirane filtere i indekse.
Ako frontend zahtijeva dodatne mogućnosti, može ih zatražiti preko API-ja, gdje API može potvrditi da li da ih dozvoli. I dalje je manje poziva.
Neke prednosti koje mogu vidjeti su:
Ali, uvek postoje nedostaci:
Dakle, ovaj pristup nije srebrni metak i uvodi svoj skup izazova, ali ako ste u redu s nedostacima, onda mala promjena na frontendu vjerovatno neće zahtijevati uključivanje pozadinskog tima, pojednostavljenje procesa razvoja i poboljšanje ukupna agilnost i naravno skalabilnost bi trebali biti lakši.