Razvoj

Streamline Your API Design: Build for Clarity, Not Just Code

Pojednostavite dizajn svog API-ja: gradite za jasnoću, a ne samo za kod

API je obećanje dano pod pritiskom. Kad klijenti jednom postanu ovisni o njemu, svako nejasno ime polja, preopterećeni endpoint i neočekivani statusni kod postaju skupi za promjenu. Najbrži način stvaranja tog duga jest tretirati API kao tanki omotač oko aplikacijskog koda ili tablica baze podataka.

Dobar dizajn API-ja počinje negdje promišljenije: poslom koji korisnik pokušava obaviti. Kod je važan, ali jasnoća je proizvod. Dobro dizajniran API omogućuje drugom razvojnom programeru da predvidi kako radi prije nego što pročita njegovu implementaciju.

Dizajnirajte oko mogućnosti, a ne pohrane

Sheme baza podataka optimizirane su za trajnu pohranu. API-ji su optimizirani za komunikaciju. Ti se ciljevi preklapaju, ali nisu isti.

Pretpostavimo da aplikacija pohranjuje narudžbu u tablicama orders, order_items i payments. Izravno izlaganje tih tablica može dovesti do endpointa poput /order_items ili payloada punog internih stranih ključeva. Klijent, međutim, obično želi stvoriti narudžbu, vidjeti njezino trenutačno stanje ili je otkazati. Dizajnirajte oko tih mogućnosti.

{
  "id": "ord_8f31",
  "status": "pending_payment",
  "items": [
    {
      "productId": "prod_42",
      "quantity": 2,
      "unitPrice": {
        "amount": 1999,
        "currency": "USD"
      }
    }
  ],
  "total": {
    "amount": 3998,
    "currency": "USD"
  }
}

Ovaj prikaz ne mora otkriti svaki detalj trajne pohrane. Korisniku daje stabilan, koristan model. U pozadini backend ostaje slobodan normalizirati tablice, zamijeniti pružatelja platnih usluga ili dodati zapise revizije bez pretvaranja interne migracije u nekompatibilno izdanje API-ja.

Učinite uobičajeni put očitim

Korisniku ne bi trebao vodič da zaključi osnovno ponašanje. Nazivi resursa, HTTP metode, tijela zahtjeva, odgovori i pogreške trebaju se međusobno nadopunjavati.

  • Koristite imenice za resurse: /orders, a ne /createOrder.
  • Koristite POST /orders za stvaranje narudžbe i GET /orders/{id} za dohvaćanje narudžbe.
  • Koristite dosljedno zapisivanje velikih i malih slova te imenovanje u svakom payloadu.
  • Vraćajte identifikatore i poveznice samo kada pomažu korisnicima da djeluju na rezultat.
  • Neka neobavezna polja doista budu neobavezna; nemojte prisiljavati klijente da šalju prazne rezervirane vrijednosti.

Postoje opravdane iznimke. Neke su operacije radnje, a ne uobičajena ažuriranja resursa. Naplata plaćanja ili slanje pozivnice može zaslužiti eksplicitan endpoint za radnju, poput POST /orders/{id}/capture. Važno je da iznimka imenuje smisleno poslovno područje, umjesto da izlaže metodu kontrolera.

Pogreške validacije dio su sučelja

Odgovori na neuspjeh mjesto su na kojem API stječe ili gubi povjerenje. Generički 400 Bad Request s porukom “invalid input” klijentu govori gotovo ništa. Aplikacija već zna koje pravilo nije prošlo; vratite tu informaciju u predvidivoj strukturi.

{
  "message": "Validation failed",
  "errors": {
    "email": [
      "Must be a valid email address."
    ],
    "items.0.quantity": [
      "Must be greater than zero."
    ]
  }
}

U PHP aplikaciji sloj za validaciju trebao bi dosljedno pretvarati neuspjehe unosa u domeni u ovaj ugovor, bez obzira dolazi li zahtjev do kontrolera, radnog procesa podržanog redom čekanja ili zasebne usluge. Nemojte izlagati sirove iznimke baze podataka ni stack traceove okvira u javnim odgovorima. Nestabilni su, teško ih je koristiti i mogu otkriti detalje implementacije.

Statusni kodovi trebaju komunicirati kategoriju ishoda. Uspješno stvaranje obično vraća 201. Zahtjev s neispravnim formatom ili nevaljanim unosom najčešće je 400 ili 422, pod uvjetom da je izbor dokumentiran i dosljedno primijenjen. Resursi koji nedostaju trebaju vratiti 404; autentificirani pozivatelj bez dopuštenja trebao bi primiti 403. Dosljednost je vrednija od domišljatih razlikovanja koja klijenti ne mogu pouzdano koristiti.

Odvojite API ugovore od PHP interne implementacije

Primamljivo je izravno serijalizirati ORM entitet. Također je primamljivo dolazni JSON vezati izravno na model i spremiti ga. Oba prečaca povezuju javni ugovor s nazivima polja, odnosima, zadanim postavkama serijalizacije i pogreškama autorizacije skrivenima u aplikacijskom kodu.

Umjesto toga upotrijebite eksplicitnu granicu. Objekti zahtjeva ili namjenski preslikavači ulaza mogu validirati i normalizirati dolazne podatke. Transformatori odgovora, serijalizatori ili objekti za prijenos podataka specifični za API mogu oblikovati odlazne podatke. Točan PHP okvir manje je važan od razdvajanja.

final class OrderResponse
{
    public static function fromOrder(Order $order): array
    {
        return [
            'id' => $order->publicId(),
            'status' => $order->status()->value,
            'total' => [
                'amount' => $order->total()->amount(),
                'currency' => $order->total()->currency(),
            ],
        ];
    }
}

Ova mala količina koda stvara vrijednu točku za provjeru. Čini izložena polja namjernima, sprječava slučajno otkrivanje internih atributa i daje timu jasno mjesto za razvoj prikaza.

Rano planirajte ponovne pokušaje i konkurentnost

Mreže otkazuju na uobičajene načine: klijentima istekne vrijeme nakon što je poslužitelj počeo raditi, mobilne veze nestanu, a radnici poslova pokušavaju ponovno. Za operacije koje stvaraju financijsku naplatu, dodjeljuju resurs ili pokreću nuspojavu, ponovljeni zahtjevi ne smiju neprimjetno ponoviti ishod.

Ključevi idempotentnosti praktičan su obrazac za odabrane POST operacije. Klijent šalje jedinstveni ključ, poslužitelj pohranjuje rezultat povezan s tim ključem, a ponovni pokušaj može primiti izvorni rezultat umjesto stvaranja duplikata. To zahtijeva trajnu pohranu, pažljivo rukovanje istodobnim zahtjevima koji koriste isti ključ i definirano razdoblje zadržavanja. Nije riječ samo o zaglavlju dodanom dokumentaciji.

Slično tome, izbjegavajte dopustiti da zadnji zapisivač pobijedi kada dva klijenta uređuju isti zapis. Polje verzije, oznaka entiteta ili drugi mehanizam optimistične kontrole konkurentnosti mogu omogućiti otkrivanje zastarjelih ažuriranja. API bi trebao vratiti jasan odgovor o sukobu i omogućiti korisniku da dohvati trenutačno stanje prije nego što odluči što učiniti dalje.

Performanse su pitanje ugovora

Spore API-je često uzrokuje nesklad između oblika odgovora i načina na koji se podaci učitavaju. Endpoint koji izlistava narudžbe i dohvaća povezane stavke jednu po jednu narudžbu može bezazlen zahtjev pretvoriti u mnogo upita prema bazi podataka. Izmjerite izvršene upite, zatim namjerno učitajte odnose ili preoblikujte endpoint.

Paginacija također treba biti eksplicitna. Vraćanje svakog zapisa rijetko je trajno zadano ponašanje. Podržite ograničenu veličinu stranice, stabilno sortiranje i metapodatke odgovora koji klijentima govore kako nastaviti. Paginacija temeljena na pokazivaču može biti osobito korisna za velike zbirke ili zbirke koje se često mijenjaju, ali samo ako pokazivač ima dokumentirano značenje i klijenti ga tretiraju kao neproziran.

Docker ne mijenja ova pitanja dizajna, ali može olakšati njihovo otkrivanje. Lokalna okruženja trebaju pokretati iste pomoćne usluge o kojima API ovisi, kao što su njegova baza podataka i predmemorija, s konfiguracijom zadanom kroz postavke specifične za okruženje. Time se smanjuju razlike tipa “radi na mom računalu” bez pretvaranja rasporeda kontejnera u dio javnog API ugovora.

Dokumentirajte odluke tamo gdje se mogu testirati

Dokumentacija treba opisivati ugovor, ali sami primjeri nisu dovoljni. Držite izvršivu specifikaciju API-ja ili testove ugovora blizu implementacije. Testirajte uspješne zahtjeve, granice autorizacije, nevaljani unos, prazne zbirke, ponovne pokušaje gdje je primjenjivo te promjene koje bi mogle narušiti postojeće klijente.

Verzioniranje je posljednje sredstvo, a ne zamjena za pažnju. Klijentima je obično lakše prihvatiti aditivne promjene nego preimenovanje polja, mijenjanje značenja ili promjenu tipa vrijednosti. Kada je nekompatibilna promjena neizbježna, pružite put migracije i jasan plan povlačenja umjesto da dopustite da dva nekompatibilna tumačenja koegzistiraju neograničeno.

Jasnoća se umnožava

Najbolji API-ji djeluju manjima od sustava koji stoje iza njih. Skrivaju slučajnu složenost, otkrivaju smislene izbore i ponašaju se dosljedno kada je uspjeh jednostavan i kada je neuspjeh neuredan. To se ne postiže dodavanjem više endpointa ili više apstrakcije. Dolazi od tretiranja svakog polja, pogreške, ponovnog pokušaja i statusnog koda kao dijela dugotrajnog razgovora s drugim inženjerom.

Najprije gradite taj razgovor za jasnoću. Kod će biti lakše održavati jer mu ugovor daje oblik vrijedan očuvanja.

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.