Razvoj

Beyond AI: Architecting Software That Learns Your Business Rules

Iznad umjetne inteligencije: Arhitektura softvera koji uči vaša poslovna pravila

Većina softvera ne mora postati „inteligentna” prije nego što postane vrijedna. Mora postati pouzdana u odlukama koje već definiraju poslovanje: koje se narudžbe mogu poslati, koji se popusti mogu kombinirati, kada račun treba provjeru i tko može odobriti iznimku.

Ta pravila često započinju raspršena po kontrolerima, upitima baze podataka, formulama u proračunskim tablicama, znanju tima za podršku i hitnim zakrpama u produkciji. Aplikacija možda radi, ali svaka nova funkcionalnost pretvara se u arheološku vježbu. Pravi arhitektonski izazov nije dodavanje umjetne inteligencije. To je izgradnja softvera koji može izraziti, primijeniti, mijenjati i objasniti poslovna pravila bez da baza koda postane krhka.

Poslovna pravila su prvoklasna briga dizajna

Poslovno pravilo je izjava koja određuje ishod u domeni. „Narudžbe iznad kreditnog limita zahtijevaju odobrenje” pravilo je. „Kupac može dobiti besplatnu dostavu samo u prihvatljivim regijama” pravilo je. „Računi se mogu otkazati samo prije namire” pravilo je.

Pravila nisu isto što i tehnička validacija. Provjera je li e-pošta sintaktički valjana tehničko je pitanje. Provjera pripada li ta e-pošta odobrenoj korporativnoj domeni za ugovornu razinu poslovna je logika. Miješanje tog dvoga stvara kod koji je teško testirati i još teže sigurno mijenjati.

Prva korisna razlika jest ona između stabilnih koncepata domene i promjenjive politike. Order, Invoice i Customer trajni su koncepti. Prag pri kojem narudžba zahtijeva odobrenje jest politika. Svakome dodijelite mjesto u dizajnu.

Držite pravila izvan transportnih slojeva

U PHP aplikaciji kontroleri trebaju prevoditi HTTP zahtjeve u radnje aplikacije. Ne bi trebali odlučivati je li transakcija dopuštena. Isto tako, ORM model obično je pogrešno mjesto za rastuću zbirku sveobuhvatnih odluka o politici.

Mala aplikacijska usluga može koordinirati rad, dok usmjereni objekt politike donosi odluku:

final class CreditApprovalPolicy
{
    public function requiresApproval(Order $order, Customer $customer): bool
    {
        return $order->totalAmount()->isGreaterThan(
            $customer->creditLimit()
        );
    }
}

final class PlaceOrder
{
    public function __construct(
        private CreditApprovalPolicy $approvalPolicy,
        private OrderRepository $orders
    ) {
    }

    public function handle(Order $order, Customer $customer): void
    {
        if ($this->approvalPolicy->requiresApproval($order, $customer)) {
            $order->markPendingApproval();
        } else {
            $order->confirm();
        }

        $this->orders->save($order);
    }
}

To nije formalnost radi same formalnosti. Odluka je imenovana, neovisno testabilna i ponovno upotrebljiva iz API krajnje točke, radnika reda čekanja, procesa uvoza ili zadatka naredbenog retka. Aplikacijska usluga opisuje tijek rada; politika opisuje pravilo.

Modelirajte jezik koji ljudi stvarno koriste

Poslovni softver koji se može održavati ima koristi od zajedničkog rječnika. Ako financije kažu „namira”, nemojte stanje imenovati completed u jednoj usluzi, paid u drugoj i finalized u trećoj, osim ako ti pojmovi doista ne znače različite stvari.

Dobra imena smanjuju pogreške pri prevođenju. Također rano otkrivaju dvosmislenosti. Metoda nazvana canCancel() potiče tim da definira što otkazivanje znači. Uključuje li povrat novca? Je li dopušteno nakon slanja? Mijenja li odgovor bankovni prijenos na čekanju? Ta su pitanja odluke o proizvodu, a arhitektura bi ih trebala učiniti vidljivima umjesto da ih skriva u ugniježđenim uvjetima.

Za značajne tijekove rada eksplicitno modelirajte prijelaze stanja. Booleova vrijednost poput is_approved nije dovoljna kada stvarni životni ciklus uključuje poslano, na pregledu, odobreno, odbijeno, isteklo i opozvano. Jasna stanja otežavaju slučajno uvođenje nevaljanih prijelaza.

Koristite podatke za politiku, a kod za značenje

Timovi često prelaze između dviju nekorisnih krajnosti: tvrdo kodiraju svaki prag ili cijelu domenu stavljaju u generički mehanizam pravila. Pragmatična granica funkcionira bolje.

Pohranite kao podatke vrijednosti koje poslovni korisnici razumno trebaju prilagođavati: limite odobrenja, prihvatljive zemlje, datume stupanja na snagu, preslikavanja kategorija proizvoda i prava na funkcionalnosti. Zadržite značenje domene i složeno ponašanje u kodu: kako se iznosi uspoređuju, kako pravila međusobno djeluju, kako se izvodi prijelaz i što se događa kada nedostaje potrebna politika.

Na primjer, tablica politike s verzijama može sadržavati prag odobrenja s razdobljem valjanosti. Kod i dalje odlučuje da se mora odabrati točno jedna aktivna politika te da nedostajuća politika blokira operaciju umjesto da je prešutno odobri.

  • Koristite ograničenja baze podataka za invarijante koje uvijek moraju vrijediti, poput nenegativnih količina i jedinstvenih vanjskih referenci.
  • Koristite transakcije kada pravilo ovisi o tome da više upisa uspije zajedno.
  • Koristite politike na razini aplikacije za odluke koje zahtijevaju kontekst domene.
  • Zabilježite verziju politike ili ulaze korištene za važne odluke kada je kasnije objašnjenje važno.

Ova podjela sprječava da konfiguracija postane netipizirani programski jezik, a istodobno dopušta kontroliranu promjenu politike.

Učinite odluke objašnjivima

Booleov odgovor rijetko je dovoljan. Operativni timovi, kupci i budući razvojni inženjeri trebaju znati zašto je zahtjev odbijen ili usmjeren na pregled. Cilj nije otkrivati interne pojedinosti implementacije; cilj je zadržati smislen kontekst odluke.

Umjesto vraćanja samo false, vratite mali objekt rezultata sa statusom i šifrom razloga. API može preslikati taj rezultat u stabilan odgovor, dok zapisi i revizijski zapisi čuvaju relevantne identifikatore i verziju politike.

final class EligibilityResult
{
    public function __construct(
        public readonly bool $eligible,
        public readonly string $reason
    ) {
    }
}

// Example reasons: "region_not_supported", "account_overdue"

Šifre razloga bolje su od kopiranja teksta namijenjenog ljudima kroz svaki sloj. Ostaju dovoljno stabilne za klijente i izvještavanje, dok se prikaz može lokalizirati ili promijeniti bez promjene temeljnog ugovora pravila.

Dizajnirajte API-je oko ishoda, a ne tablica baze podataka

API koji samo zrcali perzistenciju otkriva internu strukturu i potiče klijente da ponovno stvaraju poslovnu logiku. Ako klijenti moraju pregledati pet polja kako bi odredili može li se račun otkazati, pravilo će se razilaziti među web aplikacijama, integracijama i mobilnim klijentima.

Umjesto toga izložite smislene radnje i ishode. Krajnja točka poput POST /invoices/{id}/cancellation-requests može predstavljati namjernu poslovnu operaciju. Njezin odgovor može priopćiti je li zahtjev prihvaćen, odbijen ili zahtijeva pregled.

Idempotentnost je važna kad god su ponovni pokušaji mogući. Mrežno vremensko ograničenje ne govori pozivatelju je li poslužitelj obradio zahtjev. Za naredbe pokrenute izvana prihvatite ključ idempotentnosti, pohranite ga s dobivenim ishodom i vratite izvorni ishod pri valjanom ponovnom pokušaju. Time se pravilo štiti od dvostruke primjene zato što se infrastruktura ponašala normalno.

Testirajte pravilo na pravoj razini

Poslovna pravila zaslužuju izravne testove s čitljivim primjerima. Test nazvan order_over_credit_limit_requires_approval sažet je dio izvršive dokumentacije politike. Vrjedniji je od testa kontrolera koji isti uvjet zakopava pod postavljanjem zahtjeva i pitanjima autentikacije.

Također testirajte granice: iznos točno na limitu, prvi trenutak kada politika postaje učinkovita, isteklo pravo i konkurentske uvjete koji mogu proizvesti različite ishode. Integracijski testovi zatim trebaju potvrditi da perzistencija, transakcije i API preslikavanje čuvaju namjeravano ponašanje.

Kada pravila postanu složena, koristite tablice primjera umjesto domišljatih pomoćnih funkcija za testiranje. Budući održavatelj trebao bi moći vidjeti slučajeve koje je poslovanje smatralo važnima bez obrnutog inženjeringa apstrakcije.

Mijenjajte pravila kao produkcijski softver

Promjene politike mogu imati veće posljedice od promjena koda jer odmah mijenjaju aktivne odluke. Postupajte s njima u skladu s tim. Validirajte nove konfiguracije prije aktivacije, čuvajte prethodne verzije, pažljivo definirajte datume stupanja na snagu i osigurajte put za vraćanje promjena. Ako promjena politike utječe na postojeće zapise, izričito odlučite primjenjuje li se samo na nove odluke ili pokreće kontroliranu ponovnu evaluaciju.

Promatranje je dio arhitekture. Pratite neuspjele prijelaze, odbijene naredbe, nedostajuću konfiguraciju i neočekivane kombinacije pravila. Izbjegavajte nepotrebno bilježenje osjetljivih vrijednosti, ali zadržite dovoljno konteksta za dijagnosticiranje odluke bez rekonstruiranja cijelog produkcijskog incidenta iz sjećanja.

Trajna alternativa magičnom softveru

Sustavi zaslužuju povjerenje kada su njihove odluke predvidljive, provjerljive i prilagodljive. To ih ne čini manje sofisticiranima. Njihovu sofisticiranost čini korisnom.

Započnite pronalaženjem pravila koja su trenutačno skrivena u kontrolerima, upitima i plemenskom znanju. Imenujte ih. Dajte im usmjerena mjesta. Pohranite promjenjivu politiku s verzioniranjem. Vraćajte objašnjenja, dizajnirajte naredbe sigurne za ponovni pokušaj i testirajte granične slučajeve s kojima će se ljudi naposljetku susresti.

Softver koji uči vaša poslovna pravila nije softver koji nagađa. To je softver čija struktura omogućuje poslovanju da ga jasno poučava — i inženjerima da to poučavanje održavaju ispravnim kako se poslovanje razvija.

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.