Iza upita: Arhitektura softvera iz kojeg umjetna inteligencija uistinu uči
Najvažniji prompt u radnom tijeku inženjeringa uz pomoć umjetne inteligencije često je onaj koji nitko ne napiše. To je akumulirani prompt utjelovljen u repozitoriju: njegovo imenovanje, testovi, sheme, granice, datoteke za implementaciju, rukovanje pogreškama i povijest odluka.
Umjetna inteligencija može generirati uvjerljiv kod na temelju kratkog zahtjeva. Hoće li taj kod postati sigurna promjena ovisi o tome čemu ga okolni softver uči. Kodna baza sa slabim granicama i dvosmislenim konvencijama svaki zahtjev pretvara u nagađanje. Kodna baza koja namjeru čini vidljivom daje i ljudima i umjetnoj inteligenciji mnogo bolju polaznu točku.
Ovo nije argument za to da svaki repozitorij bude ceremonijalan. Ovo je argument za to da važne istine budu lako otkrivene i teško proturječne.
Softver je prikriveni materijal za obuku
Kada inženjer otvori nepoznatu PHP uslugu, brzo traži obrasce: gdje zahtjevi ulaze, kako se provodi validacija, kako se rade promjene u bazi podataka, gdje se nalaze poslovna pravila i kako se prijavljuju neuspjesi. Alati umjetne inteligencije rade uglavnom isto. Zaključuju o konvencijama iz obližnjih primjera, čak i kada su ti primjeri slučajni ili zastarjeli.
Zbog toga je nedosljednost skuplja nego što se na prvi pogled čini. Ako jedna krajnja točka koristi objekte zahtjeva, druga čita izravno iz globalnih varijabli, a treća miješa validaciju s perzistencijom, ne postoji pouzdan lokalni presedan. Generirano rješenje možda radi, ali je manje vjerojatno da će pripadati sustavu.
Korisni repozitoriji izlažu svoj arhitektonski vokabular. Razvojni inženjer trebao bi moći odgovoriti na nekoliko osnovnih pitanja bez obrnutog inženjeringa cijele aplikacije:
- Gdje HTTP ulaz postaje validirani podatak aplikacije?
- Koji sloj posjeduje poslovna pravila?
- Kako su transakcije baze podataka definirane i ponovljene?
- Koje pogreške smiju prijeći granicu API-ja?
- Kako je usluga konfigurirana lokalno i pri implementaciji?
Za ove odgovore nije potreban velik arhitektonski dokument. Potrebno je da budu dosljedno predstavljeni u kodu, testovima i maloj količini usmjerene dokumentacije.
Učinite granice očitima
Umjetna inteligencija posebno je učinkovita kada zadatak ima jasnu spojnicu. „Dodaj polje statusa” neodređeno je kada su kontroleri, upiti, serijalizacija i autorizacija isprepleteni. Postaje rješivo kada sustav odvaja transportne aspekte od operacija aplikacije i pojedinosti perzistencije.
Razmotrite operaciju potvrđivanja narudžbe. Kontroler bi trebao prevesti HTTP zahtjev u poziv usluge aplikacije. Usluga bi trebala provesti smisleno pravilo: narudžba se može potvrditi samo iz dopuštenog stanja. Repozitorij ili sloj perzistencije trebao bi se baviti pohranom. Svaki dio budućoj promjeni daje uže i pouzdanije mjesto na koje može sjesti.
final class ConfirmOrder
{
public function __construct(
private OrderRepository $orders,
) {
}
public function handle(OrderId $id): void
{
$order = $this->orders->get($id);
$order->confirm();
$this->orders->save($order);
}
}
Primjer je namjerno malen. Njegova vrijednost nije u broju klasa; ona je u vidljivom vlasništvu nad pravilom. Ako potvrda također zahtijeva revizijski događaj, provjeru plaćanja ili transakciju, operacija ima očit dom.
Ne stvarajte slojeve samo da biste zadovoljili dijagram. Stvarajte ih tamo gdje promjena jednog aspekta ne bi trebala zahtijevati razumijevanje svakog drugog aspekta. Najbolja arhitektura često se manje odnosi na apstrakciju, a više na smanjenje broja mjesta koja čitatelj mora držati u glavi.
Testovi su izvršiva namjera
Testovi su među najjačim signalima koje sustav može pružiti. Održavatelju govore što mora ostati istinito kada se pojedinosti implementacije promijene. Za rad uz pomoć umjetne inteligencije također pružaju primjere fikstura, imenovanja, očekivanih neuspjeha i preferirane razine pokrivenosti testovima.
Test koji samo potvrđuje uspješan HTTP status koristan je, ali nepotpun. Dobro odabran test izražava poslovnu posljedicu i rubni uvjet koji se ne smije tiho ublažiti.
public function test_an_already_confirmed_order_cannot_be_confirmed_again(): void
{
$order = Order::confirmed(OrderId::fromString('order-123'));
$this->orders->save($order);
$this->expectException(OrderAlreadyConfirmed::class);
$this->confirmOrder->handle($order->id());
}
Takvi testovi jasno ističu ključnu razliku: neuspjeh je dio ugovora, a ne neugodna iznimka koju treba sakriti. Za API-je prenesite tu preciznost na granicu. Definirajte kako se neuspjesi domene pretvaraju u stabilne kodove odgovora i tijela, te testirajte to mapiranje tamo gdje je važno.
Neka testovi budu dovoljno čitljivi da budu poučni. Pretjerano domišljati pomoćnici za testiranje mogu smanjiti broj pritisaka tipki, a pritom zamagliti scenarij. Sažet test trebao bi otkriti što je važno bez potrebe za obilaskom okvira za fiksture.
Neka baza podataka izrazi svoja pravila
Validacija aplikacije nužna je, ali nije konačni autoritet za integritet podataka. Istodobni zahtjevi, pozadinski poslovi, ručne skripte i buduće putanje koda mogu zaobići pretpostavke donesene u jednoj metodi usluge. Važne invarijante trebaju se provoditi na razini baze podataka kada ih baza podataka može izraziti.
Upotrijebite odgovarajuće tipove, strane ključeve, jedinstvena ograničenja i stupce koji ne dopuštaju null kako biste nevažeća stanja učinili teškima ili nemogućima za pohranu. Migracije tretirajte kao produkcijski kod: uređene, podložne pregledu, reverzibilne kada je to praktično te sigurne za veličinu i prometne karakteristike tablice.
Ograničenje jedinstvenosti, na primjer, nije zamjenjivo provjerom postojećeg retka prije umetanja. Provjera može biti u utrci. Ograničenje razrješava utrku; aplikacija tada treba namjerno obraditi nastali sukob.
Promjene sheme također podučavaju buduće održavatelje sustava. Migracija imenovana prema poslovnoj promjeni i jasno imenovano ograničenje komuniciraju više nego što će to ikada učiniti generička izmjena.
Dokumentirajte operativni ugovor
Kod objašnjava kako značajka radi. Operativna dokumentacija objašnjava kako preživljava kontakt s okruženjem. Tu mnoge inače čiste usluge postaju teške za sigurnu izmjenu.
Korisni README ili vodič za uslugu trebao bi odgovoriti na praktična pitanja: potrebne varijable okruženja, koraci lokalnog pokretanja, naredbe za testiranje, postupak migracije baze podataka, ovisnosti o redu čekanja ili raspoređivaču te očekivanja za provjeru stanja. Držite ga blizu usluge i ažurirajte ga promjenama koje mijenjaju operativni model.
Konfiguracija zaslužuje posebnu pažnju. Dajte prednost eksplicitnim varijablama okruženja i validiranoj konfiguraciji pred raspršenim pozivima pristupnicima varijabli okruženja. Držite tajne izvan repozitorija, ali dokumentirajte svrhu, format i sigurnu razvojnu zadanu vrijednost svake postavke kada ona postoji.
docker compose up --build
docker compose exec app php artisan migrate
docker compose exec app php artisan test
Ovakve naredbe vrijedne su samo kada odražavaju stvarne alate projekta. Zastarjela naredba gora je od nikakve naredbe jer stvara lažno povjerenje. Tretirajte razvojno okruženje kao dio proizvoda koji inženjeri koriste za izgradnju proizvoda.
Dizajnirajte za pregled, a ne samo za generiranje
Umjetna inteligencija može ubrzati prvi nacrt, ali pregled ostaje trenutak u kojem promjena zaslužuje povjerenje. Strukturirajte rad tako da recenzent može pregledati promjenu u slojevima: ugovor API-ja, pravilo aplikacije, promjenu podataka, testove i operativni učinak.
Male, kohezivne promjene to olakšavaju. Zahtjev za spajanje koji kombinira novu krajnju točku, opsežno refaktoriranje, preimenovane konvencije i prepisivanje Dockera daje recenzentima previše pokretnih dijelova. Čak i ispravan kod postaje teško provjeriti kada je uzročnost zakopana.
Dobra higijena repozitorija ovdje pomaže: smislene poruke predaja, fokusirane razlike, jasna zastarijevanja i uklanjanje zastarjelih putanja nakon dovršetka migracije. To nisu kozmetičke navike. To su signali koji razlikuju aktualne konvencije od povijesnog otpada.
Prompt koji održavate svaki dan
Timovi često pitaju kako pisati bolje promptove za umjetnu inteligenciju. To je korisno, ali trajnije pitanje jest kako izgraditi softver koji objašnjava sam sebe. Jasne granice, izvršivi testovi, provedena pravila podataka i iskrena operativna dokumentacija poboljšavaju ishode prije nego što itko otvori alat umjetne inteligencije.
Dobit je šira od generiranja koda. Novi inženjeri brže se uvode u posao. Pregledi postaju precizniji. Incidente je lakše dijagnosticirati. Refaktoriranje izaziva manje straha jer sustav navodi što namjerava očuvati.
Na kraju, umjetna inteligencija ne uči vašu arhitekturu iz slogana. Uči iz izbora koje vaš softver ponavlja. Neka ti izbori budu dovoljno jasni da sljedeći inženjer, čovjek ili onaj uz pomoć stroja, može proširiti sustav bez nagađanja o tome što je pokušavao postati.