U prošlosti sam često primjećivao uobičajeni pristup u kojem su programeri (uključujući i mene naravno) koristili isti API za čitanje i pisanje u svakom slučaju. Čak štoviše, često smo se oslanjali na isti izvor podataka, kao što je MySQL/PostgreSQL, za rukovanje objema operacijama.
To znači pisanje u iste stupce i čitanje iz njih, što često dovodi do problema s optimiziranjem indeksa na poljima koja su bila jako upitna.
Tako bismo, na primjer, često mijenjali indekse kako bismo prilagodili nove filtre ili poboljšali izvedbu upita, a polja korištena s operatorima poput LIKE predstavljala su posebne izazove zbog utjecaja na izvedbu.
Ove promjene često dovode do daljnjih prilagodbi pozadine, uključujući modificiranje API-ja za izlaganje ažurirane funkcionalnosti, izmjerena vremena zbog dodatnih JOIN-ova i tako dalje...
Kako bi se riješio izazov dodavanja novih filtara i stvari u API-ju, bilo je pokušaja optimizacije procesa pomoću alata i standarda kao što su Apicalypse i, naravno, GraphQL .
Ova su rješenja imala za cilj pojednostaviti generiranje API upita i smanjiti ručni napor potreban za implementaciju novih filtara i funkcionalnosti, nudeći dinamičniji pristup rukovanju pristupom podacima, ali su imala dugu krivulju učenja.
S pojavom CQRS-a (Command Query Responsibility Segregation), počeo se pojavljivati novi pristup. Ovakav način razmišljanja poticao je korištenje odvojenih izvora za pisanje i čitanje. Pisanje bi moglo emitirati događaje, a čitanje moglo graditi prikaze iz tih događaja na namjenskim mjestima. Čak i ako se čitanjem i pisanjem upravljalo unutar iste baze podataka (ali različitih tablica), ovo odvajanje donijelo je značajne prednosti i, naravno, uspjelo se riješiti drugog izazova - JOIN-ova i upita za pretraživanje na modelima domene, budući da su modeli za čitanje obično u obliku denormaliziranih JSON-ova.
Međutim, ovo je otvorilo još jedan problem. Kod čitanja smo morali mjeriti pisanje, što znači da je jedini razlog zbog kojeg smo morali skalirati instance naše aplikacije od X do Y bilo čitanje. Taj bi se problem mogao djelomično ublažiti predmemoriranjem, a u svijetu mikroservisa mogli bismo imati namjenske mikroservise za čitanje.
Ali...
Ipak, ovo nije bilo idealno rješenje za druge arhitektonske stilove poput modularnih monolita, gdje se takvo odvajanje možda neće dobro uskladiti s filozofijom dizajna sustava. Druga stvar je bila, kada API nije radio, cijeli je proizvod bio u kvaru, a imajući na umu da se većina proizvoda oslanja na više čitanja nego pisanja, to bi moglo nepotrebno utjecati na poslovanje (Osim neispravnog API-ja, naravno ;) )
Dakle, što ako bismo mogli pitati te "poglede", također poznate kao modeli čitanja, izravno bez uključivanja API-ja i rukovanja opterećenjima? Ovdje na scenu stupaju rješenja kao što su Meilisearch , AppSearch i druga, koja koriste obrazac nazvan "Valet Key". Korištenjem ovog uzorka, sučelja mogu izravno pristupiti modelima optimiziranim za čitanje, smanjujući ovisnost o pozadinskim API-jima. Naravno, sučelje i dalje mora "pitati" API za "Valet ključ", ali sučelje može predmemorirati ključeve, tako da čak i kada API ne radi, sučelje još uvijek može komunicirati i prikazivati sadržaj.
Ovim pristupom možemo se usredotočiti na bazu podataka za čitanje i ne brinuti o rukovanju prometom za čitanja u našem API-ju. "Valet Key" dostavljen sučelju putem našeg API-ja osiguran je na način da ga sučelje ne može promijeniti. Uključuje unaprijed definirane filtre i indekse.
Ako sučelje zahtijeva dodatne mogućnosti, može ih zatražiti putem API-ja, gdje API može potvrditi treba li ih dopustiti. Još uvijek je manje poziva.
Neke prednosti koje vidim su:
Ali uvijek postoje nedostaci:
Dakle, ovaj pristup nije srebrni metak i uvodi vlastiti niz izazova, ali ako se slažete s nedostacima, tada mala promjena na sučelju vjerojatno neće zahtijevati uključivanje pozadinskog tima, pojednostavljenje razvojnog procesa i poboljšanje ukupna agilnost, i naravno skalabilnost bi trebala biti lakša.