
Acest conținut a fost generat cu ajutorul inteligenței artificiale și publicat fără o verificare umană prealabilă. Poate conține erori și nu constituie consultanță profesională. Semnalați o problemă: info@delionsoft.com.
GitHub a publicat un articol despre rescrierea motorului de execuție al agentului Copilot — motorul comun care stă la baza CLI-ului, aplicației și SDK-ului Copilot — din TypeScript pe Node.js în Rust. Conform raportului original, rezultatul este de peste 800.000 de linii de cod Rust de producție, integrate prin 128 de cereri de pull în ramura principală, cu agenții care au scris cea mai mare parte a codului. Partea interesantă pentru noi, ceilalți, nu este atât alegerea limbajului, cât mai degrabă metoda de migrare.
Ce s-a întâmplat
Mediul de execuție a pornit ca TypeScript, iar SDK-ul a ajuns să fie suprapus peste CLI, și nu invers. Utilizatorii creau un client prin generarea unui subproces CLI și comunicau cu acesta prin JSON-RPC. Asta însemna că fiecare utilizator al SDK-ului — C#, Python, Go, Java, Rust, TypeScript — livra un al doilea runtime de limbaj, aloca aproximativ 100 MB de memorie activă ca minim, transmitea fiecare eveniment și operațiune de fișier peste granița procesului, pierdea sesiunea dacă Node se bloca și avea două procese de supravegheat.
Obiectivul era o bibliotecă fără TUI în interior, care să poată fi încorporată în proces prin intermediul unui ABI C, cu un cost redus de pornire și un consum de memorie previzibil. Rust a fost ales din aceste motive, precum și datorită setului de instrumente și poziției în lanțul de aprovizionare; autorii precizează în mod explicit că aceasta nu este o recomandare generală pentru portarea bazelor de cod mari scrise în TypeScript.
Migrarea s-a realizat pe loc, componentă cu componentă, prin înlocuire atomică: fiecare cerere de preluare (pull request) a înlocuit o implementare TypeScript cu un shim subțire care apela la Rust și a șters codul vechi în cadrul aceleiași modificări. Codul principal a rămas gata de lansare, testele end-to-end existente au fost rulate pe noul cod la fiecare etapă, iar eșuarea testelor obligatorii a blocat fuziunea. Au evitat în mod deliberat să mențină ambele implementări schimbabile în timpul funcționării, deoarece subsistemele care ar beneficia cel mai mult de o trecere paralelă prudentă — de exemplu, orchestrarea sesiunilor — sunt cele cu stare mutabilă partajată și callback-uri bidirecționale, unde menținerea a două copii este cea mai dificilă.
Un detaliu demn de menționat: estimarea inițială indica aproximativ 130.000 de linii de TypeScript. Autorul estimează că aproximativ 430.000 de linii de cod de producție au trecut efectiv prin procesul de portare, deoarece codul continua să coboare din stratul TUI, iar alte echipe continuau să integreze cod nou în TypeScript pe tot parcursul procesului.
De ce este important
Afirmațiile din titlu — un proiect de echipă de un an sau doi realizat în mare parte de un singur dezvoltator în câteva luni, performanță îmbunătățită cu ordine de mărime — provin de la echipa însăși și trebuie interpretate ca atare. Însă lecția structurală se aplică și bazelor de cod mult mai mici: asistența oferită de agenți modifică costul unei rescrieri, ceea ce înseamnă că datoria arhitecturală pe care o consideraseți permanentă ar putea merita acum să fie reevaluată. De asemenea, aceasta sporește valoarea elementelor care asigură siguranța unei astfel de operațiuni, și anume acoperirea testelor, diferențele verificabile și limitele clare ale modulelor.
Ce trebuie făcut
- Înainte de a lua în considerare orice rescriere asistată de agenți, verificați dacă testele end-to-end sunt suficient de bune pentru a acționa ca o poartă de fuziune. Fără aceasta, portarea incrementală nu are o plasă de siguranță.
- Preferă înlocuirea pe loc, componentă cu componentă, în locul unei ramuri de rescriere de lungă durată. Menținerea ramurii principale gata de lansare elimină cel mai grav mod de eșec al migrațiilor de tip „big bang”.
- Împărțiți pe straturi înainte de portare. O mare parte din acest efort a constat în separarea mediului de execuție de interfața cu utilizatorul; această muncă este utilă chiar și dacă nu schimbați niciodată limbajul de programare.
- Definiți domeniul de aplicare în funcție de graficul de dependențe, nu de numărul de linii de cod. Componentele cu stare mutabilă partajată vor costa mult mai mult decât sugerează dimensiunea lor.
