– Ikke ta for lett på typene, ellers gjør KI-agenten det
– AI-agenter trenger strenge rammer for hva de skal få lov til å gjøre, og da ble det viktig å få orden på typene, skriver Kurt Lekanger om prosjektet han holder på med.
Årets NDC Oslo er over, og som vanlig var det ikke vanskelig å finne interessante temaer. Men, som jeg overhørte noen si: det var ikke lett å finne foredrag som ikke handlet om AI.
Ett av foredragene som ikke hadde AI i tittelen var “Types are worth the typing” av Filip Sodic. Det virket interessant, for jeg har for lengst innsett at livet som utvikler blir uendelig mye enklere når jeg har korrekte typedefinisjoner overalt.
Det viste seg riktignok fort at også dette foredraget handlet mye om AI – blant annet hvordan gode typer hjelper AI-agentene:
– Engelsk er et utmerket språk for å oppdage spesifikasjonene og for å iterere på spesifikasjonene, sa Sodic – med referanse til hvordan vi prompter på engelsk.
– Men det er ikke brukbart som et språk for å lage spesifikasjonene.
Tid brukt på typer er tid spart senere
Da jeg for noen år siden gikk over fra å kode i “vanilla” JavaScript til TypeScript, skrev jeg mye av koden før jeg fikset typene. Det vil si – enkle typer som string, number og boolean var stort sett på plass fra start.
Men jeg må innrømme at jeg nok strødde om meg med temmelig mange any bare for at jeg skulle kunne kode meg ferdig uten å måtte tenke på komplekse typer midt oppi det hele.
Det tok ikke lang tid før jeg innså at det lønte seg å snu på rekkefølgen: Typene først – og så resten av koden.
Tiden jeg brukte på å skrive typedefinisjoner på forhånd, sparte jeg fort inn senere. Jeg fikk autofullføring på felter, metoder og parametere, slapp å lete gjennom dokumentasjon (”hva het det feltet igjen?”), og ikke minst: Jeg unngikk skrivefeil som kunne føre til irriterende bugs.
Nå starter jeg alltid med å definere typer eller interfacer når jeg skal skrive en ny funksjon eller lage en ny komponent. Det har mange fordeler:
Du må tenke gjennom datamodellen og grensesnittene før implementasjonen. Dermed oppdager du ofte designfeil eller ting du ikke har tenkt igjennom tidlig – mens det er billig og enkelt å fikse opp i.
Typene fungerer som levende dokumentasjon. De forteller deg hva funksjoner forventer av input og hva de returnerer.
Typene blir tydelige kontrakter mellom koden din og API-er.
Du fanger opp feil før koden havner i prod.
Har du gode typer, trenger du ikke bruke like mye tid på å skrive defensiv kode (har objektet dette feltet? Kan denne verdien noen gang være null?).
Du får bedre autofullføring og mindre risiko for bugs forårsaket av skrivefeil.
Ulovlige tilstander blir umulige
Sodic viste et eksempel på hva som kan skje når man koder først og tenker på typer etterpå. Han startet med en løst typet JavaScript-funksjon for en kaffemaskin. Maskinen kunne lage mange ulike typer kaffe: med eller uten melk, filterkaffe- eller espresso-basert, og så videre.
Men ikke alle kombinasjoner av ingredienser og måter å lage kaffe på er "lovlige". Løsningen mange tyr til når noe ikke stemmer, er å forklare agenten hva som er galt og be den om å rette opp i feilene og skrive dokumentasjon for det.
Hvis agenten senere gjør feil til tross for dokumentasjonen, ber vi den om å skrive tester. De fanger opp noen feil, men er langt fra idiotsikre.
Den riktige måten å unngå feil på er ifølge Sodic å gå tilbake og skrive presise typer først. Så snart typene er presise nok, kan du fjerne runtime-sjekker og tester som ble laget for å fange opp de samme feilene.
Hvis ulovlige tilstander (states) er gjort umulige gjennom typedefinisjonene, trenger du heller ikke å teste for dem.
AI-agenter trenger strenge rammer
Det går selvfølgelig an å bruke AI-agenten til å hjelpe deg med å skrive typedefinisjonene.
I et prosjekt jeg jobber på nå er det integrasjoner mot et svært komplekst system med et stort antall API-endepunkter. De returnerer ofte enorme JSON-objekter på tusenvis av linjer.
Som ny utvikler på prosjektet for snart ett år siden syntes jeg det var frustrerende å ikke få autofullføring når jeg prøvde å aksessere felter på disse objektene. Jeg brukte mye tid på å lete i dokumentasjon fordi typedefinisjoner enten manglet eller var ufullstendige.
Etter hvert som AI-agentene ble bedre, begynte jeg å overlate mer av kodeskrivingen til dem. Men AI-agenter trenger strenge rammer for hva de skal få lov til å gjøre, og da ble det viktig å få orden på typene. Å lage alle typedefinisjonene manuelt ville vært for tidkrevende, men heldigvis var API-ene godt dokumentert.
Bonus: Claude fant bugs
Jeg ba Claude om å sjekke eksisterende typedefinisjoner mot OpenAPI-spesifikasjoner, og skrive nye definisjoner der det manglet. Claude skulle aldri finne på typer selv – bortsett fra der hvor typene kunne utledes fra koden.
Da typene var fikset, ble det mye enklere for meg å jobbe videre med koden. I tillegg fikk AI-agenten det Sodic kalte en deterministisk harness: noe den kan sjekke koden sin mot, i stedet for fritekstdokumentasjon som gir rom for tolkning og feil.
En bonus-effekt jeg ikke hadde tenkt på var at Claude under arbeidet med typedefinisjonene fant flere bugs i koden. Ingen hadde oppdaget dem tidligere, men de hadde garantert gitt oss hodebry senere.
Sodic oppfordret til å skrive typer på forhånd. Det synes jeg er et veldig godt råd. Men det er heller ikke for sent å skrive typedefinisjoner etter koden er skrevet.
Det viktigste er å få orden på typene.
Foretrekk oss i Google Discover
Ved å legge oss til som foretrukket kilde i Google vil du blant annet få opp flere av sakene våre i Google Discover. Tusen takk for støtten!