Compararea limbajelor de programare în contexte de generare de cod cu LLM-uri: costul abstractizării și explicitatea în Go

Limbaje moderne
Limbajele moderne sunt limbajele care oferă, în comparație cu limbajele din trecut, o productivitate, stabilitate, securitate și întreținere mai ridicate. Aceste limbaje adoptă activ tehnici și concepte recente și oferă dezvoltatorilor instrumente de dezvoltare mai eficiente și mai sigure. Printre limbajele moderne reprezentative se numără Java, Rust, Python, TypeScript etc., iar acestea au următoarele caracteristici.
1. Proiectare orientată pe obiecte ( OOP )
Limbajele moderne sunt, în cea mai mare parte, proiectate pe baza conceptelor orientate pe obiecte. Programarea orientată pe obiecte susține principii precum încapsularea, moștenirea și polimorfismul și, prin împărțirea unui sistem complex în obiecte de dimensiuni mici, face structura programului clară și flexibilă. Aceasta este deosebit de eficientă în dezvoltarea software la scară mare, deoarece permite controlul costurilor și al efortului de dezvoltare și reduce problemele care pot apărea în timpul întreținerii.
2. Zaharul sintactic și expresiile
Limbajele moderne oferă diverse forme de zahăr sintactic și sintaxă bazată pe expresii, pentru a crește lizibilitatea codului și productivitatea dezvoltării. Operatorul ternar, expresiile lambda și potrivirea de modele (pattern matching) reduc codul standard (boilerplate), fac codul previzibil și sporesc productivitatea dezvoltatorului.
3. Sistemul de module
Limbajele moderne permit, prin intermediul sistemului de module, ca programul să fie separat în mai multe unități și gestionat ca atare. Acest lucru facilitează reutilizarea codului și gestionarea dependențelor și face ca întreținerea să rămână ușoară chiar și atunci când dimensiunea proiectului crește. Exemple reprezentative includ Maven/Gradle pentru Java, Cargo pentru Rust și npm/yarn pentru TypeScript.
4. Limbaje intermediare și mașini virtuale
Limbajele moderne adoptă limbaje intermediare și mașini virtuale pentru independența față de platformă, optimizarea performanței și securitate. Exemple reprezentative includ JVM, LLVM, WASM, GraalVM etc.
Dezvoltarea în era AI și limitele limbajelor moderne
Limbajele moderne au apărut pornind de la premisa că majoritatea codului este scris de oameni. În mod firesc, scopul limbajelor moderne este reducerea activităților repetitive, creșterea productivității și realizarea eficientă a software-ului de mari dimensiuni, prin structuri care permit colaborarea dezvoltatorilor. Totuși, în era AI, această premisă se erodează treptat. Instrumente bazate pe AI precum Copilot, Cody etc. automatizează o mare parte din scrierea codului, iar cantitatea de cod pe care o poate produce un singur dezvoltator crește vertiginos. Ca urmare, trăsăturile limbajelor moderne care odinioară erau percepute ca avantaje se transformă treptat în dezavantaje ale unei epoci trecute.
Proiectarea orientată pe obiecte
AI poate analiza rapid și precis o funcție sau un modul în care toate informațiile sunt explicite. În schimb, pe măsură ce contextul crește, crește și intervalul pe care trebuie să-l deducă, astfel încât productivitatea și precizia AI scad. Codul scris în OOP distribuie logica între mai multe obiecte, în loc să o gestioneze într-un singur loc, ceea ce, în final, necesită din partea AI un context mai amplu. Să considerăm codul de mai jos.
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}
În codul de mai sus, pentru a afla ce acțiune efectuează în realitate metoda speak(), AI trebuie să repete următoarele deducții
- animal este instanța cărei clase concrete?
- Unde este definită metoda speak() suprascrisă în acea clasă?
- Unde se află definițiile claselor Dog și Cat și care este comportamentul din interiorul lor?
- Nu există posibilitatea ca clasele Dog și Cat să fie suprascrise într-o altă clasă?
Aceste informații nu sunt adunate într-un singur fișier sau într-o singură funcție, ci pot fi înțelese doar urmărind relațiile dintre fișierele de clasă și structura de moștenire. Mai mult, elementele care sunt determinate în timpul execuției, precum reflecția sau încărcarea dinamică, sunt pentru AI asemenea unei cutii negre, făcând analiza practic imposibilă.
Zaharul sintactic și expresiile
AI preferă comportamentul explicit în locul celui implicit și preferă să combine structuri simple pentru a obține un singur răspuns corect, în locul utilizării unor structuri complexe. În schimb, zaharul sintactic permite multiple forme de exprimare, dar comportamentul intern al acestora este adesea identic sau similar. AI trebuie să învețe sensul fiecăreia dintre aceste forme de exprimare și poate ajunge să aibă dificultăți în a stabili ce sintaxă să recomande într-o situație dată.
Limbaje intermediare și mașini virtuale
AI învață în mare parte pe baza codului sursă. În schimb, limbajul intermediar (bytecode) elimină, în timpul compilării, semnificația numelor variabilelor și a altor elemente, iar mașina virtuală trebuie să îl reinterpreteze în momentul execuției. Aceasta este o sarcină extrem de dificil de înțeles sau de transformat pentru AI. De exemplu, pentru AI, conversia de la TypeScript la Go este posibilă, dar conversia bytecode-ului motorului V8 în bytecode JVM sau în cod mașină este practic imposibilă.
Adevăratul limbaj modern al erei AI
Din cele de mai sus reiese că trăsăturile limbajelor moderne sunt, în realitate, elemente nepotrivite pentru era AI, adică elemente ale unei epoci trecute. Ce limbaj ar putea deveni, atunci, cel mai potrivit limbaj modern pentru era AI? Răspunsul poate fi găsit analizând elementele pe care limbajele moderne din trecut le-au respins. Limbajul modern al erei AI trebuie:
- Să aibă o sintaxă explicită și un flux natural.
- Să depășească structura OOP excesivă și să aibă o structură plată și simplă.
- În loc de zahăr sintactic inutil sau modele implicite, să realizeze multiple funcționalități doar cu un set limitat de cuvinte cheie de bază.
- Să aibă un sistem de build simplu și previzibil, nu unul complex.
Limbajul care corespunde cel mai bine acestor criterii este Golang. Limbajul Go a fost proiectat astfel încât să poată implementa majoritatea funcționalităților practice doar cu un set minim de cuvinte cheie esențiale și o combinație simplă de sintaxă, excluzând în mod riguros abstractizările inutile și comportamentele implicite. Acest lucru este avantajos atât pentru dezvoltatori, cât și pentru AI, în procesul de interpretare și generare a codului.
Astfel, caracteristicile Go, care vizează o structură previzibilă și plată, un flux explicit și o sintaxă consecventă, se potrivesc mai bine unui mediu de dezvoltare în care AI participă activ, spre deosebire de limbajele moderne tradiționale, concepute pentru dezvoltatorii umani. Filosofia de proiectare conservatoare a Go, considerată cândva depășită, devine, în era AI, de fapt cea mai avansată alegere.