Intensjonsbasert programmering (ofte omtalt som "vibe coding") representerer et skifte i hvordan programvareutvikling kan gjennomføres. Tradisjonelt har programmering innebåret å gi maskinen detaljerte instruksjoner om hvordan den skal utføre en spesifikk oppgave – en prosess som kan være tidkrevende og kompleks. I intensjonsbasert programmering er fokuset på resultatet: hva programmet skal gjøre, i stedet for hvordan det skal gjøres. Denne metoden gjør det mulig for utviklere å uttrykke sine intensjoner på et høyere abstraksjonsnivå, ofte ved å bruke naturlig språk, og la kunstig intelligens (AI) oversette dette til fungerende kode.

Dette er ikke et nytt konsept, men de siste fremskrittene innen AI har gjort det praktisk å beskrive komplekse oppgaver på en enkel måte, og deretter motta fungerende kode. Et sentralt element i denne prosessen er "prompten" – en kort beskrivelse av hva utvikleren ønsker at programmet skal gjøre. I stedet for å skrive ut detaljert kode, gir utvikleren en beskrivelse som for eksempel kan være: «Les denne CSV-filen og hent e-postadressene til alle brukere som er eldre enn 18 år». AI-en vil da generere kode som utfører denne oppgaven.

Hva som gjør denne utviklingen mulig, er de enorme fremskrittene innen store språkmodeller (LLM-er), som har blitt trent på enorme mengder tekst og kode. Disse modellene har lært å forstå både programmeringsspråk og den menneskelige beskrivelsen av oppgaver. Når du gir en prompt, er det ikke bare enkle instruksjoner for AI-en, men en beskrivelse av hva du ønsker å oppnå, som AI-en deretter konverterer til syntaktisk korrekt kode.

I denne nye tilnærmingen blir prompten et sentralt element i programmeringsprosessen, et verktøy som kan beskrive programmenes funksjonalitet og logikk på en mer intuitiv måte. Prompten blir den nye enheten for å uttrykke intensjonene dine, og utviklere kan nå jobbe med en mer overordnet forståelse av hva programmet skal gjøre, i stedet for å måtte bryte ned hvert enkelt steg i detalj.

AI-en genererer koden ved å analysere teksten i prompten. Når utvikleren gir AI-en en forespørsel, analyserer modellen teksten og bruker statistiske mønstre for å forutsi hva den beste løsningen på oppgaven vil være. AI-en benytter seg av mønstrene den har lært fra tusenvis av eksempler for å produsere kode som fungerer, selv om den ikke nødvendigvis "forstår" oppgaven slik et menneske gjør.

I praksis er intensjonsbasert programmering en iterativ prosess. Utvikleren gir først en prompt, deretter genererer AI-en en løsning. Denne løsningen blir så evaluert og testet av utvikleren, og ved behov blir prompten eller koden raffinert og justert. Det er ikke et spørsmål om å få en fullstendig løsning umiddelbart, men om å samarbeide med AI-en for å gradvis komme frem til et fungerende resultat. Denne prosessen er rask og kan gjennomføres på sekunder, noe som sparer utvikleren for tid.

AI-en fungerer som en assistent som genererer kode, men den menneskelige utvikleren er fortsatt ansvarlig for å gjennomgå og verifisere koden. Dette er en form for samarbeid der AI-en tar på seg det tunge arbeidet med å produsere kode basert på menneskelige intensjoner, men hvor den siste kontrollen og kvalitetssikringen ligger hos utvikleren.

For å få utbytte av intensjonsbasert programmering, er det viktig å forstå hvordan man formulerer effektive prompt. En vag eller dårlig formulert prompt kan føre til feil eller ineffektiv kode, akkurat som en dårlig kravspesifikasjon kan føre til misforståelser i et tradisjonelt programmeringsprosjekt. Jo mer presist du kan uttrykke intensjonen din i prompten, jo mer presis vil koden som genereres være.

AI-modellene som benyttes i intensjonsbasert programmering, har blitt trent på enorme datamengder fra kodebiblioteker, fora og annen programvaredokumentasjon. De har lært hvordan kode skal struktureres, samt hvilke løsninger som er mest hensiktsmessige for forskjellige problemer. Dermed er det ikke bare snakk om å skrive kode, men også om å forstå hvordan man best kan beskrive en oppgave slik at AI-en kan bruke sitt store repertoar av informasjon til å løse den.

Et av de mest bemerkelsesverdige aspektene ved intensjonsbasert programmering er at det er et samarbeid, en syklisk prosess mellom menneske og maskin. Utvikleren beskriver hva de ønsker å oppnå, AI-en genererer en første versjon av koden, og utvikleren gjennomgår og finjusterer. Denne prosessen gjentas til løsningen er optimal, og kan til og med inkludere automatiserte enhetstester og feilretting. Dette gjør at utviklere kan fokusere mer på design, funksjonalitet og løsningens overordnede mål, mens AI-en håndterer de tekniske detaljene.

Det er viktig å merke seg at dette er en kontinuerlig utvikling. AI-en forbedres kontinuerlig, og de som er dyktige til å formulere presise og klare prompt, vil kunne dra større nytte av systemet. Et godt samarbeid mellom utvikleren og AI-en kan føre til betydelig raskere utvikling, høyere kvalitet på koden, og mer kreative løsninger på problemer.

Hvordan autonome AI-agenter kan endre utviklerrollen i fremtidens programvareutvikling

Teknologiutviklingen går raskt, og det er verdt å reflektere over de langsiktige implikasjonene og hvordan ting kan utvikle seg i løpet av de neste årene. Et område som vil gjennomgå store endringer er programvareutvikling, spesielt når det gjelder bruk av autonome AI-agenter i utviklingsprosessen. Fremtidens utviklere kan i stor grad få sine arbeidsoppgaver utført av AI, og deres rolle vil endres betraktelig.

I en fremtid der AI-agenter er en standard del av utviklingsteamet, vil arbeidsprosesser se annerledes ut. Akkurat som vi i dag har kildekontroll og CI/CD som uunnværlige verktøy, kan det i framtiden være normalt å sjekke et "AI-assistenttavle" hver morgen som viser hva agentene har fått gjort over natten. Når du logger inn, kan kodegjennomgangene allerede være utført, og du er klar til å gå videre med ditt arbeid. Dette kan bli en naturlig del av arbeidsdagen, der utviklere om kvelden delegerer en bunke oppgaver til agentene, som forsøker å løse dem til neste morgen.

Utviklerens rolle vil i større grad skifte fra det å skrive boilerplate-kode og gjøre rutinemessige oppdateringer, til å definere problemer, integrere løsninger og veilede AI-ene. Utviklere vil mer og mer fungere som produktledere for AI-utviklere, spesifisere hva som skal gjøres, og sikre at det møter de nødvendige kravene.

En annen viktig utvikling vil være at flere AI-agenter kan samarbeide om løsninger. I dag jobber hver agent for det meste isolert på en oppgave, men i fremtiden kan vi se at flere spesialiserte agenter samarbeider om en oppgave. For eksempel kan én agent være ekspert på frontend-utvikling, mens en annen er spesialisert på backend. Agentene kan dele en oppgave mellom seg, eller kanskje finne ut hvordan de kan dele oppgaven i underoppgaver. En annen mulighet er at en agent utforsker flere løsningsveier parallelt, slik som multibransjeeksplorasjon, der en AI løser et komplekst problem ved å lage flere alternative løsninger og deretter velge den beste.

Det er også mulig at AI-agenter kan be om hjelp eller veiledning fra mennesker når de står fast. Forskning på usikkerhetsestimering og selvrefleksjon for store språkmodeller (LLM) viser at AI-er kan trenes til å gjenkjenne når de er usikre og be om hjelp, i stedet for å gjøre antagelser. Dette skaper en følelse av tillit, ettersom agentene oppfører seg mer som samarbeidspartnere enn svarte bokser. En agent kan for eksempel nå et punkt der to forskjellige biblioteker kan brukes til å implementere en løsning, og i stedet for å gjette, kan den stoppe og spørre: "Jeg kan bruke bibliotek A eller B for dette – har du en preferanse?" Denne typen "intelligent sjekkpunkt" er et viktig steg mot å gjøre AI-er mer pålitelige som samarbeidspartnere.

Et annet viktig aspekt ved AI-agenter i utvikling er forbedringen av brukergrensesnittene (UX). Når vi begynner å delegere mer av arbeidet vårt til agenter, vil vi ha behov for bedre verktøy for å holde oversikt over hva agentene gjør. Ett forslag er et "agent-innboks" – en samlet visning av hvilke oppgaver agentene jobber med, hva som er gjort, og hva som trenger menneskelig oppmerksomhet. Dette kan være et dashbord som viser alle aktive agentoppgaver, fremdrift og resultater. Istedenfor dagens loggfiler og pull-requests kan et klart grensesnitt for å administrere agentene dukke opp. Det vil også kunne være varsler som informerer utvikleren når en agent har fullført en oppgave eller trenger innspill for å fortsette.

Ettersom AI-agenter blir mer integrert i utviklingsverktøyene, vil de også kobles tett sammen med systemer som problemhåndterere og kontinuerlig integrasjon (CI). Dette vil kunne skape en strammere arbeidsflyt, hvor en feil i systemet automatisk kan adresseres av en AI-agent som utfører nødvendige tiltak, som å oppdatere en sårbar biblioteksversjon eller forbedre testdekning. Eksempler på dette finnes allerede, som for eksempel Dependabot, som åpner PR-er for å oppdatere avhengigheter. I fremtiden kan AI-agenter ikke bare åpne PR-er, men også håndtere eventuelle problemer som oppstår som følge av oppdateringen, og dermed eliminere behovet for manuell inngripen.

En av de store utfordringene for utviklingen av AI-agenter er gapet mellom hva dagens modeller kan håndtere, og hva som kreves for å utføre mer komplekse oppgaver. De store AI-modellene som GPT-4, Gemini og Claude vil fortsette å forbedres, og det er sannsynlig at dette gapet vil krympe etter hvert som modellene får bedre forståelse og genereringsevne for kode. Med bedre modeller vil agenter gjøre færre feil, kreve mindre tilsyn, og kunne håndtere mer komplekse oppgaver. Likevel er det stor sannsynlighet for at det alltid vil være behov for menneskelig vurdering i de mest komplekse situasjonene.

I fremtiden vil AI-agenter også bli mer spesialiserte. Vi kan se frem til spesialiserte kodeagenter for ulike domener, som en "BugFixer"-agent for feilretting, en "PerformanceGuru"-agent for ytelsestesting og optimalisering, eller en agent for å generere dokumentasjon og kommentarer for eksisterende kodebaser. Ved å spesialisere agentene, kan de integrere mer domene-spesifikk kunnskap og verktøy, og dermed bli mer effektive på sitt spesifikke område.

For utviklerne selv vil det skje en kulturell og ferdighetsmessig overgang. Når agentene tar over flere av de rutinemessige oppgavene, vil utviklernes ferdigheter måtte dreie seg mer om design, arkitektur og overvåkning av AI-arbeidet. Dette kan også inkludere en større vekt på myke ferdigheter, som å kommunisere krav tydelig til både mennesker og AI-agenter.

Hvordan bygge effektive testrammer for AI-genererte systemer?

Utvikling og implementering av AI-genererte systemer har skapt nye utfordringer og muligheter for programvareutviklere. Når flere AI-genererte komponenter integreres i et system, oppstår det komplekse problemer relatert til usikkerhet, kvalitetssikring, og vedlikehold av kodebasen. For å takle disse utfordringene er det avgjørende å utvikle effektive testrammer og strategier som kan håndtere de unike egenskapene ved AI-generert kode.

AI-systemer er ofte preget av en viss grad av ikke-determinisme. Dette betyr at selv når systemet kjøres under samme betingelser, kan resultatene variere på tvers av forskjellige kjøringer. Denne variabiliteten utfordrer tradisjonelle metoder for testing og verifisering. Testene må derfor designes på en måte som tar høyde for at resultater kan endres selv med identiske innganger. Å utvikle rammeverk som kan identifisere og håndtere denne usikkerheten er avgjørende for at systemene skal være pålitelige og robuste.

En annen viktig komponent i testing av AI-genererte systemer er å sørge for at det er tilstrekkelig kodegjennomgang og kvalitetssikring. Det er spesielt viktig å fokusere på vedlikeholdbarheten av kodebasen. AI-assisterte utviklingsverktøy kan generere kode raskt, men ofte kan det føre til at koden blir vanskelig å forstå og vedlikeholde. Derfor er det nødvendig å implementere kodegjennomgang som en del av arbeidsflyten for å sikre at AI-generert kode er lett å vedlikeholde, forstå og videreutvikle.

En av de viktigste utfordringene ved testing av AI-generert kode er å verifisere at koden oppfyller de nødvendige funksjonskravene og er sikker. Å inkludere tester for sikkerhet, som for eksempel enhetstester som fokuserer på potensielle sårbarheter som XSS (cross-site scripting) eller feilaktig autentisering og autorisering, er essensielt. Dette kan bidra til å oppdage og rette opp feil før systemet går i produksjon.

Når AI-genererte systemer er i produksjon, er det viktig å fortsette å gjennomføre testing og verifisering for å sikre at systemet fungerer som forventet i et levende miljø. Dette kan inkludere skyggesjekking gjennom distribusjon, hvor systemet kontinuerlig overvåkes og eventuelle problemer kan adresseres raskt. Denne prosessen bør være en del av en kontinuerlig integrasjons- og distribusjonsflyt for å sikre at eventuelle feil fanges opp og håndteres tidlig.

Det er også viktig å tenke på enhetstester, integrasjonstester og ende-til-ende-tester som en kontinuerlig prosess gjennom hele utviklingssyklusen, fra prototyping til produksjon. Ved å bruke AI-drevne verktøy kan prototyper utvikles raskt og feil kan fanges tidlig. Men når systemet skaleres og går i produksjon, blir behovet for mer grundige tester mer kritisk. Dette innebærer at teamene må ha en helhetlig forståelse av testmetodene og hvordan de skal tilpasses ulike stadier av utviklingsprosessen.

Når man jobber med AI-genererte systemer, er det avgjørende å implementere et rammeverk for testdrevet feilsøking. Dette kan inkludere å bruke verktøy for automatisk debugging som kan identifisere og rette opp feil på en raskere og mer presis måte. Det er også viktig å integrere verktøy for versjonskontroll i arbeidsflyten, ettersom endringer i AI-generert kode kan føre til uforutsette problemer i senere faser av utviklingen.

Når man utvikler med AI, er det lett å fokusere på produktiviteten som oppnås ved å bruke AI-assistenter. Men det er viktig å ikke glemme at de samme verktøyene kan introdusere utfordringer knyttet til forståelse og vedlikehold av koden som genereres. Derfor bør utviklere være kritiske til hva AI-verktøyene genererer og sørge for at de gjennomgår og tester koden grundig. Det handler om å finne balansen mellom effektivitet og kvalitet.

Testing og validering er spesielt viktig i AI-drevne webapplikasjoner. I tillegg til funksjonalitet og ytelse, må også sikkerheten vurderes på en grundig måte. Dette inkluderer å teste for vanlige sikkerhetssårbarheter i AI-generert kode, som feilaktig autentisering, manglende tilgangskontroller eller feil i datavalidering. Ved å inkorporere slike sikkerhetstester tidlig i utviklingsprosessen, kan man unngå mange av de vanligste sårbarhetene som kan utnyttes av angripere.

Selv om AI kan bidra til å skape mer effektive og innovative løsninger, kan det også introdusere nye utfordringer, spesielt når det gjelder UI/UX-design og brukeropplevelse. Generative designverktøy kan hjelpe til med å skape brukergrensesnitt raskt, men dette kan også føre til at man mister fokus på de menneskelige aspektene ved design. Det er derfor viktig å kombinere AI-drevne verktøy med menneskelig kreativitet for å sikre at brukeropplevelsen er både effektiv og intuitiv.

Ved å bruke oppdaterte AI-drevne verktøy og verktøy med sikkerhetsfokus, kan utviklere sikre at AI-generert kode er av høy kvalitet og fri for sårbarheter. Men det er også viktig å være oppmerksom på etiske utfordringer knyttet til bruken av AI i utvikling, som for eksempel potensielle skjevheter i modellen eller urettferdighet som kan oppstå som et resultat av bruken av AI i bestemte sammenhenger. Å ha en ansvarlig tilnærming til AI-bruk, kombinert med effektive testrammer, kan bidra til å redusere disse risikoene og forbedre kvaliteten på AI-genererte systemer.