Sprogdesignsammenligning i LLM-baserede kodegenereringsmiljøer: abstraktionsomkostninger og Gos eksplicitthed

Moderne sprog
Moderne sprog refererer til sprog, der tilbyder højere produktivitet, stabilitet, sikkerhed og vedligeholdelsesvenlighed sammenlignet med tidligere sprog. Disse sprog anvender aktivt nyere teknikker og koncepter og giver udviklere mere effektive og sikre udviklingsværktøjer. Repræsentative moderne sprog omfatter Java, Rust, Python og TypeScript, og de har følgende karakteristika.
1. Objektorienteret design (OOP)
Moderne sprog er for det meste baseret på objektorienterede koncepter. Objektorientering understøtter principper som indkapsling, nedarvning og polymorfi, og ved at opdele komplekse systemer i mindre objektenheder gør den programmets struktur klar og fleksibel. Dette er særligt effektivt i storskala softwareudvikling, hvor det hjælper med at kontrollere udviklingsomkostninger og indsats samt reducerer de problemer, der kan opstå ved vedligeholdelse.
2. Syntaktisk sukker og udtryksbaseret syntaks
Moderne sprog tilbyder forskellige former for syntaktisk sukker og udtryksbaseret syntaks for at øge kodens læsbarhed og udviklingsproduktivitet. Funktioner såsom ternære operatorer, lambdaudtryk og mønstermatchning reducerer boilerplate-kode, gør koden forudsigelig og forbedrer udviklerens produktivitet.
3. Modulsystem
Moderne sprog gør det muligt at opdele og administrere programmer i flere enheder gennem et modulsystem. Dette letter genbrug af kode og afhængighedsstyring og gør det lettere at vedligeholde projekter, selv når deres omfang vokser. Typiske eksempler er Maven/Gradle i Java, Cargo i Rust og npm/yarn i TypeScript.
4. Mellemliggende sprog og virtuelle maskiner
Moderne sprog anvender mellemliggende sprog og virtuelle maskiner for at opnå platformsuafhængighed, ydeevneoptimering og sikkerhed. Typiske eksempler omfatter JVM, LLVM, WASM og GraalVM.
Udvikling i AI-æraen og de moderne sprogs begrænsninger
Moderne sprog opstod under den forudsætning, at mennesker skriver størstedelen af koden. Naturligt nok er formålet med moderne sprog at reducere gentagne opgaver, øge produktiviteten og gennem strukturer, der muliggør samarbejde mellem udviklere, implementere store softwaresystemer effektivt. Denne forudsætning bliver dog gradvist ugyldig i AI-æraen. AI-baserede værktøjer såsom Copilot og Cody automatiserer en stor del af kodeskrivningen, og mængden af kode, som én enkelt udvikler kan producere, stiger markant. Som følge heraf udvikler de karakteristika ved moderne sprog, der tidligere blev opfattet som fordele, sig gradvist til forældede ulemper.
Objektorienteret design
AI kan hurtigt og præcist analysere strukturer, hvor al information i en enkelt funktion eller et enkelt modul er eksplicit angivet. Efterhånden som konteksten vokser, øges imidlertid antallet af intervaller, der skal udledes, og AI'ens produktivitet og præcision falder. Kode skrevet i OOP fordeler logikken over flere objekter i stedet for at administrere den ét sted, hvilket resultatet af at kræve mere kontekst af AI. Se nedenstående kode.
1public class AnimalHandler {
2 public void handle(Animal animal) {
3 animal.speak();
4 }
5}
6
7public class Main {
8 public static void main(String[] args) {
9 AnimalHandler handler = new AnimalHandler();
10
11 Animal a1 = new Dog();
12 Animal a2 = new Cat();
13 Animal a3 = new Horse();
14
15 handler.handle(a1);
16 handler.handle(a2);
17 handler.handle(a3);
18 }
19}
I koden ovenfor skal AI gentagne gange foretage følgende ræsonnementer for at forstå, hvilken faktisk handling metoden speak() udfører
- Hvilken konkret klasses instans er animal?
- Hvor er den overskrevne speak()-metode i den klasse defineret?
- Hvor findes definitionerne af klasserne Dog og Cat, og hvad er adfærden inde i dem?
- Er der nogen mulighed for, at klasserne Dog og Cat overskrives i andre klasser?
Disse oplysninger er ikke samlet i én fil eller ét funktionskald, men kan kun forstås ved at følge relationerne og arvestrukturen mellem klassefilerne. Desuden er elementer, der afgøres ved kørselstid, såsom refleksion eller dynamisk indlæsning, for AI nærmest en black box, og analyse er derfor faktisk umulig.
Syntaktisk sukker og udtryksbaseret syntaks
AI foretrækker eksplicit adfærd frem for implicit adfærd og foretrækker at kombinere simple strukturer for at skabe ét entydigt svar frem for at anvende komplekse strukturer. Syntaktisk sukker tillader derimod mange forskellige udtryk, men den underliggende adfærd er ofte identisk eller lignende. AI skal lære betydningen af disse mange udtryk én for én, og det kan blive vanskeligt at afgøre, hvilken syntaks der bør anbefales i en given situation, og hvilken prioritering der gælder.
Mellemliggende sprog og virtuelle maskiner
AI lærer for det meste ud fra kildekode. Mellemliggende sprog (bytecode) fjerner derimod betydningsbærende elementer såsom variabelnavne under kompileringen, og den virtuelle maskine skal genfortolke dem på kørselstidspunktet. Dette er en opgave, som AI meget vanskeligt kan forstå eller transformere. For eksempel er det muligt for AI at oversætte fra TypeScript til Go, men det er praktisk talt umuligt at oversætte bytecode fra V8-motoren til JVM-bytecode eller maskinkode.
Det sande moderne sprog i AI-æraen
Ud fra ovenstående kan vi se, at de karakteristika, der kendetegner moderne sprog, i virkeligheden er forældede elementer, som ikke passer til AI-æraen. Hvilket sprog kan så blive det mest egnede moderne sprog i AI-æraen? Svaret kan findes i de elementer, som tidligere moderne sprog forkastede. Et moderne sprog for AI-æraen bør
- have eksplicit syntaks og et naturligt flow.
- bryde med overdreven OOP-struktur og have en flad og enkel struktur.
- frem for unødvendigt syntaktisk sukker eller implicitte mønstre, opbygge flere funktioner ud fra et begrænset sæt grundlæggende nøgleord.
- have et simpelt og forudsigeligt byggesystem frem for et komplekst byggesystem.
Det sprog, der bedst opfylder disse kriterier, er Golang. Go er designet til, at de fleste praktiske funktioner kan implementeres med et minimum af kernenøgleord og en simpel syntakskombination, og det udelukker konsekvent unødvendig abstraktion og implicit adfærd. Dette er en struktur, der er fordelagtig både for udviklere og for AI, når den skal fortolke og generere kode.
Goes egenskaber, som lægger vægt på en forudsigelig og flad struktur, eksplicit flow og konsistent syntaks, passer bedre til udviklingsmiljøer, hvor AI deltager aktivt, end de eksisterende moderne sprog, der er designet med udgangspunkt i menneskelige udviklere. Goes konservative designfilosofi, som engang blev anset for forældet, bliver dermed i AI-æraen netop det mest avancerede valg.