Razvoj

Beyond Boilers: Architecting APIs for Sustainable Backend Evolution

Iznad kotlova: projektiranje API-ja za održivu evoluciju pozadinskog sustava

Pozadinski sustav rijetko postane težak zato što je jedna odluka bila nepromišljena. Češće postane težak zato što se mnogi razumni prečaci neprimjetno učvrste u arhitekturu: kontroler izravno razgovara s bazom podataka, krajnja točka vraća sve što je ORM proizveo, Docker spremnik nosi produkcijsku konfiguraciju, a „privremeno” pravilo integracije postane dio javnog ugovora.

Zato održiv rad na pozadinskom sustavu nije prvenstveno zamjena starog okvira ili dodavanje više servisa. Riječ je o stvaranju dovoljno strukture da se sustav može mijenjati bez osjećaja da je svaka promjena operacija. API-ji su najvažnija granica u tom nastojanju. Oni povezuju klijente, baze podataka, redove čekanja, sustave trećih strana i buduće verzije proizvoda. Tretirajte ih kao arhitekturu, a ne kao infrastrukturu.

Počnite s ugovorima, a ne kontrolerima

API ugovor trebao bi opisivati na što se korisnici mogu osloniti, neovisno o tome kako aplikacija trenutačno pohranjuje podatke. Redak u bazi podataka detalj je implementacije. HTTP odgovor je obećanje.

Razmotrite krajnju točku za kupca. Vraćanje sirovog modela praktično je, ali otkriva nazive stupaca, polja koja mogu biti null, vremenske oznake i odnose koje će možda kasnije trebati promijeniti. Mapper odgovora stvara mali, ali vrijedan sloj neovisnosti.

final class CustomerResponse
{
    public static function from(Customer $customer): array
    {
        return [
            'id' => $customer->id,
            'name' => $customer->fullName(),
            'email' => $customer->emailAddress(),
        ];
    }
}

To nije formalnost radi formalnosti. Timu daje namjensko mjesto za upravljanje preimenovanjima, izračunatim vrijednostima, pravilima privatnosti i povratnom kompatibilnošću. Baza podataka može se razvijati dok vanjski ugovor ostaje stabilan.

Isto načelo vrijedi za ulazne podatke. Validirajte podatke zahtjeva na rubu, a zatim ih prevedite u naredbu ili objekt na razini aplikacije. Ne dopustite da se sadržaj zahtjeva nekontrolirano provlači kroz kontrolere, servise i kod za perzistenciju.

Ugradite promjene u dizajn API-ja

O verzioniranju se često govori kao o izboru URL-a: /v1 ili zaglavlje. URL je manje važan od discipline koja stoji iza njega. Verzija bi trebala predstavljati podržani ugovor, a ne izgovor za dupliciranje cijele aplikacije svaki put kada se promijeni jedno polje.

Kad je moguće, prednost dajte aditivnim promjenama. Dodavanje neobaveznog polja odgovora korisnicima je obično lakše od preimenovanja polja ili promjene njegova značenja. Kada je prijelomna promjena nužna, prijelaz učinite izričitim:

  • Precizno dokumentirajte stari i novi ugovor.
  • Održavajte oba puta funkcionalnima tijekom dogovorenog razdoblja migracije.
  • Pratite upotrebu kako bi se ukidanje temeljilo na dokazima, a ne na nadi.
  • Uklonite stari ugovor tek kada su vlasništvo korisnika i komunikacija jasni.

Odgovori na pogreške zaslužuju istu pažnju kao i uspješni odgovori. Klijent ne bi trebao morati parsirati HTML stranicu pogreške, zaključivati značenje iz nejasne poruke ili nagađati je li ponovno pokušavanje sigurno. Uspostavite dosljedan oblik sa strojno čitljivim kodom, ljudima čitljivom porukom i detaljima na razini polja kada validacija ne uspije.

{
  "error": {
    "code": "validation_failed",
    "message": "Zahtjev sadrži nevaljana polja.",
    "fields": {
      "email": ["Mora biti valjana adresa e-pošte."]
    }
  }
}

Dosljednost smanjuje složenost na strani klijenta i čini operativnu podršku daleko manje dvosmislenom.

Poslovna pravila držite izvan transporta i pohrane

Kontroleri bi trebali koordinirati HTTP aspekte: autentikaciju, validaciju, status odgovora i serijalizaciju. Repozitoriji bi trebali upravljati aspektima perzistencije. Nijedno ne bi trebalo postati dom poslovne politike.

Praktični srednji sloj jest aplikacijski servis ili klasa slučaja upotrebe. Izražava radnju jezikom domene: stvori narudžbu, otkaži pretplatu, odobri povrat novca. Ta klasa može pozivati repozitorije, objaviti događaj ili pozvati prilagodnik za plaćanje, bez toga da API kontroler bude odgovoran za svaki detalj.

Ovo razdvajanje isplati se kada se ista operacija kasnije mora pokrenuti iz radnika reda čekanja, zadatka naredbenog retka ili drugog API-ja. Također čini testove usmjerenijima. Test slučaja upotrebe može provjeriti pravila bez izgradnje HTTP zahtjeva ili povezivanja sa stvarnom bazom podataka.

Održivost nije odsutnost koda. Ona je prisutnost granica koje sljedeću promjenu čine razumljivom.

Neka baza podataka provodi ono što je važno

Validacija u aplikaciji korisna je, ali nije zamjena za ograničenja baze podataka. Dva istodobna zahtjeva mogu oba proći provjeru jedinstvenosti na razini aplikacije prije nego što ijedan upiše podatke. Jedinstveni indeks konačni je autoritet. Strani ključevi, check ograničenja gdje su podržana, odgovarajuća mogućnost null vrijednosti i indeksi za stvarne obrasce upita štite sustav u uvjetima koje sam aplikacijski kod ne može u potpunosti kontrolirati.

Promjene sheme također trebaju strategiju razvoja. Izbjegavajte implementacije koje zahtijevaju da aplikacijski kod i promjene sheme postanu vidljivi u točno istom trenutku. Sigurniji obrazac je proširi, migriraj, suzi:

  1. Dodajte kompatibilan element sheme, kao što je novi nullable stupac ili tablica.
  2. Implementirajte kod koji može raditi i sa starim i s novim prikazima.
  3. Po potrebi dopunite podatke u kontroliranim skupinama.
  4. Prebacite čitanja i upise na novi prikaz.
  5. Uklonite stari put tek kada se više ne koristi.

Ovaj je pristup sporiji od jedne destruktivne migracije, ali mnogo više oprašta tijekom vraćanja promjena, djelomične implementacije i operativnih iznenađenja.

Upotrijebite Docker kako bi okruženja bila dosadna

Spremnici su korisni kada smanjuju odstupanja među okruženjima, a ne kada ih skrivaju. Slika PHP aplikacije trebala bi sadržavati potrebno izvršno okruženje i kôd; konfiguraciju poput vjerodajnica, vanjskih URL-ova i zastavica specifičnih za okruženje treba isporučiti tijekom izvođenja. Jasno navedite ovisnosti za lokalni razvoj, uključujući bazu podataka, predmemoriju i servise reda čekanja koje aplikacija stvarno koristi.

Dobar tijek rada sa spremnicima također razlikuje potrebe u vrijeme izgradnje i tijekom izvođenja. Jednom izgradite nepromjenjivu sliku, a zatim istu sliku promovirajte kroz okruženja s različitom konfiguracijom. Ako produkcija zahtijeva ponovnu izgradnju zato što se vrijednost konfiguracije promijenila, model isporuke nosi previše znanja o okruženju unutar artefakta.

Provjere stanja trebale bi potvrđivati smisleno stanje spremnosti, a ne samo postojanje procesa. PHP proces može biti aktivan dok povezivost s bazom podataka, migracije ili potrebne ovisnosti nisu dostupne. Istodobno, izbjegavajte da svaka krajnja točka za provjeru stanja izvodi skupe udaljene provjere; odaberite provjere koje odgovaraju svrsi platforme za implementaciju.

Mjerite prije optimizacije

Rad na performansama počinje pitanjem: gdje se vrijeme zapravo troši? Spori odgovori mogu dolaziti od upita bez indeksa, prekomjerne serijalizacije, udaljene ovisnosti, ponavljanih promašaja predmemorije ili zaostatka u redu čekanja. „Optimiziranje PHP-a” prije utvrđivanja uskog grla često je samo preuređivanje složenosti.

Za krajnje točke koje se oslanjaju na bazu podataka pregledajte broj upita i planove upita, a zatim smanjite nepotreban rad. Uobičajena poboljšanja uključuju odabir samo potrebnih stupaca, izbjegavanje slučajnih upita po pojedinačnom zapisu, dodavanje indeksa koji odgovara stvarnom filtru ili spajanju te paginiranje ograničenih kolekcija. Predmemoriranje može pomoći, ali dodaje odluke o invalidaciji i dosljednosti. Predmemorirajte stabilne podatke čiji je izračun skup uz jasnu strategiju vlasništva i isteka; nemojte ga koristiti za prikrivanje temeljno neučinkovitog obrasca pristupa.

Gradite sustave koji se mogu mirno mijenjati

Najbolja arhitektura pozadinskog sustava rijetko je ona najsloženija. To je ona čiji su ugovori jasni, čiji integritet podataka ima stvarno provođenje, čiji koraci implementacije toleriraju promjenu i čije su odluke o performansama utemeljene na opažanju.

Iza kotlova i predložaka koda, održivo inženjerstvo navika je očuvanja mogućnosti. Svaka izričita granica, kompatibilna migracija, predvidljiv odgovor na pogrešku i mjerljiva operacija čine sljedeću značajku manje rizičnom. Tako pozadinski sustav raste a da ne postane nešto čega se tim boji dotaknuti.

Portret autora bloga

Mihajlo

Ja sam Mihajlo — programer vođen znatiželjom, disciplinom i stalnom željom da stvorim nešto smisleno. Dijelim uvide, tutorijale i besplatne usluge kako bih pomogao drugima da pojednostave svoj rad i rastu u svijetu softvera i umjetne inteligencije koji se neprestano razvija.