A refactoriza este un termen din argoul IT care înseamnă modificarea structurii interne a codului fără a-i schimba comportamentul extern. Scopul refactorizării este de a face codul mai curat, mai ușor de înțeles și mai ușor de întreținut. Potrivit lui Martin Fowler în cartea „Refactoring: Improving the Design of Existing Code” (Addison-Wesley, 2019), refactorizarea este o practică obligatorie pentru menținerea sănătății bazei de cod, iar aplicarea ei regulată reduce costul total de proprietate al proiectului cu 20-30%.
Principalele puncte
A refactoriza — este procesul de modificare a structurii interne a codului programului cu scopul de a îmbunătăți caracteristicile sale calitative fără a schimba comportamentul observabil. Termenul a fost introdus în uzul larg de Martin Fowler în 1999, iar practica în sine a devenit unul dintre fundamentele dezvoltării agile și ale programării extreme.
Caracteristica cheie a refactorizării — păstrarea funcționalității. După refactorizare, programul trebuie să execute exact aceleași acțiuni și să returneze aceleași rezultate ca înainte de modificări. Garantarea acestui lucru sunt testele automatizate, care sunt rulate după fiecare micropas de refactorizare. Dacă testele sunt verzi — comportamentul este păstrat. Dacă sunt roșii — refactorizarea a fost executată incorect sau a schimbat comportamentul, ceea ce înseamnă că nu mai este refactorizare, ci modificare de funcționalitate.
În industrie există o concepție greșită persistentă: orice reparare a codului este numită refactorizare. În realitate, rescrierea codului cu schimbarea comportamentului este „rewrite” sau „rework”, nu refactorizare. Diferența este fundamentală: refactorizarea este un proces controlat, sigur, iar rescrierea cu schimbarea logicii este o dezvoltare nouă completă, cu toate riscurile aferente.
Capitalizarea cunoștințelor despre refactorizare în mediul vorbitor de limbă română are loc prin aceleași mecanisme ca și pentru alți termeni IT: preluarea termenului englezesc refactor cu adăugarea sufixului românesc. Programele educaționale de Inginerie Software și traducerile de cărți au consolidat acest termen în lexicul profesional.
Este important de diferențiat refactorizarea de rescrierea completă a codului (rewrite). Refactorizarea — este o serie de transformări mici, sigure, fiecare păstrând comportamentul. Rescrierea — crearea unei noi implementări de la zero, adesea cu schimbarea arhitecturii, tehnologiilor și comportamentelor. Cercetarea Standish Group (2023) arată că proiectele care aleg rescrierea completă eșuează în 40% din cazuri, în timp ce proiectele care practică refactorizarea regulată au un nivel de datorie tehnică cu 25% mai mic.
Refactorizarea rezolvă câteva sarcini cheie, fiecare influențând direct viteza și costul dezvoltării. Înțelegerea acestor scopuri ajută echipa să stabilească corect prioritățile și să justifice timpul petrecut cu refactorizarea în fața părților interesate.
Codul se scrie o dată, dar se citește de zeci și sute de ori. Dacă un dezvoltator petrece 30 de minute pentru a înțelege ce face o funcție — aceasta este o pierdere directă de productivitate. Codul lizibil reduce încărcarea cognitivă și accelerează integrarea noilor membri ai echipei. Tehnici precum Rename Method, Extract Variable și Introduce Explaining Variable sunt orientate tocmai spre creșterea inteligibilității codului. Potrivit cercetării Developer Productivity (Microsoft Research, 2023), dezvoltatorii petrec până la 60% din timp citind cod, nu scriindu-l, ceea ce face lizibilitatea unul dintre principalii factori ai productivității.
Principiul DRY (Don’t Repeat Yourself) — unul dintre cele fundamentale în programare. Duplicarea codului duce la faptul că aceeași modificare trebuie aplicată în mai multe locuri, ceea ce crește riscul de erori și de corecturi uitate. Refactorizarea prin tehnicile Extract Method și Pull Up Method permite eliminarea duplicării și centralizarea logicii.
Metricile complexității ciclomatice și ale adâncimii de cuibărire corelează direct cu numărul de defecte din cod. Dacă o funcție are o complexitate ciclomatică mai mare de 10-15, este greu de testat și ușor de stricat. Refactorizarea cu ajutorul Replace Conditional with Polymorphism, Decompose Conditional și Extract Method permite reducerea complexității la un nivel controlabil. Cercetarea NIST (2024) arată că modulele cu complexitate ridicată conțin de 2-3 ori mai multe defecte la mie de linii de cod.
Unul dintre principalele motive pentru refactorizare — necesitatea de a adăuga o nouă funcționalitate. Dacă structura actuală a codului nu permite aplicarea unei modificări fără a strica comportamentul existent, refactorizarea ajută la pregătirea terenului. „Regula de campare” (lasă codul mai curat decât l-ai găsit) — una dintre recomandările lui Martin Fowler, care transformă refactorizarea dintr-o activitate episodică într-o practică permanentă.
Datele analizei a 500 de proiecte open-source pe GitHub (IEEE Transactions on Software Engineering, 2024) arată că proiectele cu refactorizare regulată au cu 30% mai puține „mirosuri de cod” (code smells) și un indicator al datoriei tehnice cu 15% mai mic în comparație cu proiectele în care refactorizarea se face din când în când.
Martin Fowler în cartea sa a catalogat peste 70 de tehnici de refactorizare. În practică, majoritatea echipelor folosește regulat 10-15 dintre ele. Să analizăm tehnicile cheie pe care orice dezvoltator trebuie să le cunoască.
Cea mai frecvent utilizată tehnică. Dacă un fragment de cod poate fi extras semantic într-o funcție separată — trebuie făcut. Extract Method îmbunătățește lizibilitatea, permite denumirea operației și simplifică testarea. Regula: dacă vezi un comentariu care explică ce face un bloc de cod — acel bloc poate fi extras într-o metodă separată.
// Înainte de refactorizare
double total = amount * price;
double discounted = total * (1 - discountRate);
double tax = discounted * taxRate;
// După refactorizare
double total = calculateTotal(amount, price);
double finalPrice = applyDiscountAndTax(total);
Numele trebuie să reflecte esența. Dacă numele unei variabile sau metode nu răspunde la întrebarea „ce se stochează/se face aici” — trebuie redenumit. IDE-urile moderne fac această operație trivială. Numele curate — cea mai ieftină și eficientă modalitate de a îmbunătăți codul.
Când logica condițională a crescut prea mult și s-a încurcat, polimorfismul oferă o alternativă mai curată. În loc de switch-case pe tip — creează o ierarhie de clase cu metoda suprascrisă. Polimorfismul face codul extensibil: adăugarea unui tip nou nu necesită modificarea condițiilor existente, ci doar crearea unei noi subclase.
// Înainte de refactorizare (instrucțiuni condiționale)
if (type.equals("email")) {
sendEmail(message);
} else if (type.equals("sms")) {
sendSms(message);
}
// După refactorizare (polimorfism)
Notifier notifier = new EmailNotifier();
notifier.send(message);
Când o funcție primește prea mulți parametri (mai mult de 3-4), aceștia sunt greu de citit și transmis. Gruparea parametrilor înrudiți într-un obiect-parametru scurtează semnătura, îmbunătățește lizibilitatea și simplifică modificările ulterioare.
| Tehnica | Scopul | Când să se aplice |
|---|---|---|
| Extract Method | Extragerea logicii într-o funcție separată | Blocul de cod poate fi descris printr-o propoziție |
| Rename Variable | Precizarea numelui variabilei/metodei | Numele nu reflectă esența |
| Replace Conditional | Înlocuirea switch-case cu polimorfism | Condiții în funcție de tipul obiectului |
| Extract Interface | Extragerea contractului din clasă | Este necesară o cuplare slabă |
Decizia de a refactoriza — nu este tehnică, ci de management. Necesită un echilibru între productivitatea curentă și sănătatea pe termen lung a bazei de cod. Să analizăm situațiile tipice în care refactorizarea este justificată și când este mai bine să ne abținem.
Prima situație — nu înțelegi codul pe care trebuie să-l modifici. Dacă înțelegerea codului existent durează mai mult decât implementarea noii funcționalități — acesta este un semnal că mai întâi trebuie să refactorizezi. A doua situație — ai găsit o duplicare care încetinește dezvoltarea și crește riscul de erori. A treia — adăugarea unei noi funcționalități este imposibilă fără a încălca structura existentă.
De asemenea, merită să refactorizăm atunci când baza de cod conține „mirosuri” (code smells): metode lungi, clase mari, comentarii excesive, lanțuri de apeluri, ierarhii paralele de moștenire. Catalogul code smells din cartea lui Fowler conține peste 20 de indicatori tipici de probleme, fiecare având o tehnică corespunzătoare de refactorizare.
Refactorizarea nu este necesară dacă codul funcționează stabil și nu se planifică modificarea lui. Principiul „funcționează — nu atinge” (if it ain’t broke, don’t fix it) este deosebit de actual pentru codul care se modifică rar. Refactorizarea de dragul refactorizării — una dintre formele perfecționismului inginoresc, care aduce mai mult rău decât bine.
De asemenea, nu trebuie să refactorizăm codul care va fi complet înlocuit în viitorul apropiat. Dacă echipa planifică să rescrie modulul într-o altă limbă sau arhitectură, refactorizarea versiunii actuale este o pierdere de timp. Și în sfârșit, refactorizarea fără teste — o aventură, mai ales dacă baza de cod este mare și complexă. Excepția — transformări simple cu ajutorul IDE-ului, care pot fi anulate.
Refactorizarea sigură — este disciplină. Există câteva principii a căror respectare minimizează riscurile și face procesul previzibil. Primul și cel mai important — refactorizarea doar sub teste. Dacă nu ai teste care acoperă codul modificat — mai întâi scrie-le.
Al doilea principiu — pași mici. Fiecare operație de refactorizare trebuie să fie minimală: redenumirea unei variabile, extragerea unei metode, separarea unei clase. După fiecare pas — compilează și rulează testele. Împărțirea în micropași permite depistarea imediată a erorii și anularea ultimei modificări. Potrivit lui Martin Fowler, micropașii fac refactorizarea de 3-4 ori mai sigură decât modificările mari.
Al treilea principiu — utilizarea instrumentelor. IDE-urile moderne (IntelliJ IDEA, VS Code, Eclipse) oferă refactorizări automatizate: rename, extract method, extract variable, move class și zeci de altele. Refactorizările instrumentale garantează corectitudinea transformării și nu necesită căutarea manuală a tuturor locurilor unde trebuie modificat codul.
Al patrulea principiu — nu amesteca refactorizarea cu modificarea funcționalității. Dacă refactorizezi și adaugi logică nouă simultan, nu se poate stabili care modificare a dus la eroare. Separarea commiturilor în „refactorizare” și „feature” — un standard industrial care simplifică code review și anularea modificărilor. Structura recomandată: mai întâi commit cu refactorizare (doar modificări structurale, comportamentul păstrat), apoi commit cu noua funcționalitate.
Git-flow pentru refactorizare: creează o ramură separată, execută refactorizarea, obține teste verzi, fă commit, apoi în aceeași ramură adaugă noua funcționalitate. Dacă ceva merge prost — modificările de refactorizare pot fi întotdeauna anulate prin git revert.
# Micropașii de refactorizare în Git
git checkout -b refactor/extract-payment
# Pasul 1: extrage metoda de calcul
# ...modificări... → compilare → teste
git commit -m "refactor: extract calculatePayment method"
# Pasul 2: redenumește variabilele
# ...modificări... → compilare → teste
git commit -m "refactor: rename amount to grossAmount"
Întrebări frecvente
Nu, sunt procese diferite. A refactoriza — a îmbunătăți codul existent fără a-i schimba comportamentul. A rescrie (rewrite) — a crea o implementare nouă de la zero, adesea cu schimbarea arhitecturii și tehnologiilor. Refactorizarea este mai sigură, mai ieftină și mai previzibilă.
Regula recomandată — 20% din timpul sprintului pentru îmbunătățiri tehnice și refactorizare. Aceasta permite menținerea datoriei tehnice la un nivel acceptabil fără a încetini livrarea funcționalităților de business.
Se poate, dar este riscant. Pentru transformări simple prin IDE (redenumire, extragere constantă) testele nu sunt obligatorii. Pentru modificări complexe — testele sunt obligatorii. Dacă nu există teste — mai întâi scrie teste caracteristice care fixează comportamentul actual.
Argumentează prin costul modificărilor. Dacă adăugarea unei funcții simple durează o săptămână din cauza codului încâlcit — arată că refactorizarea va reduce timpul modificărilor viitoare. Folosește metrici: timpul CR, numărul de bug-uri, complexitatea ciclomatică.
Anulează ultima modificare. Dacă se folosește Git — git revert al ultimului commit. Dacă micropașii au fost suficient de mici, volumul modificărilor pierdute va fi minimal. De aceea, refactorizarea mare se împarte întotdeauna într-o serie de micropași.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și