Copierea-lipire (copy-paste) — este practica de a copia fragmente de cod dintr-un loc în altul fără adaptare la noul context. Cel mai adesea, dezvoltatorul copiază un bloc dintr-un modul existent, face modificări minime și îl lipește în cel nou — împreună cu bug-uri, comentarii învechite și dependențe inutile. Conform studiului TIOBE Code Quality Survey (2025), proiectele cu un nivel ridicat de copiere-lipire conțin de trei ori mai multe defecte la o mie de linii de cod decât proiectele cu o abstracție unică. Duplicarea codului — principalul furnizor de datorie tehnică: fiecare copie necesită întreținere separată, iar remedierea unei erori într-un loc nu garantează remedierea ei în celelalte.
Principalele puncte
Copierea-lipire (copy-paste programming) — este transferul codului existent într-un loc nou cu modificări minore sau fără modificări. Termenul este folosit în sens peiorativ: sugerează că dezvoltatorul nu proiectează soluția, ci copiază mecanic un bloc gata făcut, adesea fără a înțelege pe deplin cum funcționează.
Copierea-lipire este de două tipuri: justificată (intentional) și accidentală (accidental). Justificată — când dezvoltatorul copiază intenționat codul cu planul unei refactorizări ulterioare (dar adesea planul nu este executat). Accidentală — când duplicarea apare neobservată, de exemplu, doi dezvoltatori scriu independent aceeași logică pentru ecrane diferite.
Conform raportului SonarQube State of Clean Code (2025), codul duplicat reprezintă în medie 12–18 procente din volumul total de cod în proiectele comerciale. În același timp, costul remedierii unei erori în codul duplicat este de 2,5 ori mai mare decât în codul cu o implementare unică, deoarece dezvoltatorul trebuie să găsească și să repare toate copiile.
Principalul instrument de combatere a copierii-lipirii este principiul DRY (Don't Repeat Yourself). Cu toate acestea, absolutizarea DRY este de asemenea periculoasă: uneori copierea este justificată atunci când două copii trebuie să evolueze independent una de cealaltă. Este important să distingem „duplicarea accidentală” (care trebuie eliminată) de „duplicarea necesară” (care trebuie documentată).
Primul și cel mai important pericol — multiplicarea bug-urilor. Dacă în codul sursă există un defect, acesta este copiat în toate locurile noi împreună cu codul. Când defectul este descoperit și remediat în modulul sursă, copiile rămân nereparate. Dezvoltatorul poate nici măcar să nu bănuiască că eroarea există în cinci fișiere diferite.
Al doilea pericol — evoluția inegală. Două copii ale aceluiași algoritm acumulează în timp modificări diferite. Într-o copie s-a adăugat validarea valorilor limită, în cealaltă — s-a schimbat formatul de ieșire. După câteva luni devine imposibil de determinat care versiune este „corectă”, iar proiectul pierde consistența comportamentului.
Al treilea pericol — creșterea volumului de teste. Fiecare copiere-lipire necesită propriile teste. Dacă logica comună este extrasă într-o singură funcție, poate fi acoperită cu un set de teste și reutilizată. La duplicare, fiecare copie trebuie testată separat — aceasta multiplică timpul de rulare al CI și volumul bazei de teste întreținute.
Al patrulea pericol — iluzia productivității. Copierea-lipire creează o senzație falsă de viteză: dezvoltatorul inserează rapid codul și vede că ecranul funcționează. Dar această „viteză” se transformă în datorie tehnică care va trebui plătită cu dobândă atunci când în blocul duplicat se găsește o eroare sau este necesară o modificare a logicii de afaceri.
Înțelegerea cauzelor copierii-lipirii ajută la construirea unei profilaxii corecte. Cel mai adesea, dezvoltatorii copiază codul nu din lene, ci din cauza presiunii termenelor, lipsei de cunoștințe sau a unei arhitecturi incomode.
Prima cauză — termenele limită. Când trebuie realizat un ecran în două zile, iar un ecran similar există deja, dezvoltatorul îl copiază integral și schimbă doar ceea ce vede utilizatorul. Pentru refactorizare cu extragerea unei componente comune nu există timp — clientul așteaptă rezultatul. Ca urmare, apare un al doilea ecran cu 80% cod comun, dar cu o istorie independentă de modificări.
A doua cauză — lipsa unei abstracții unitare. Dacă în proiect nu există o componentă comună pentru o sarcină tipică (de exemplu, un ecran de listă cu pull-to-refresh), fiecare dezvoltator își va scrie propria implementare sau o va copia pe cea învecinată. Deciziile arhitecturale luate la începutul proiectului influențează direct cantitatea viitoarei copieri-lipiri.
A treia cauză — teama de a strica codul funcțional. Dezvoltatorul știe că modulul existent funcționează. Refactorizarea cu extragerea codului comun poate afecta funcționalitatea existentă. Dacă acoperirea cu teste este scăzută, riscul de avarie depășește beneficiul perceput al refactorizării, iar dezvoltatorul alege calea sigură — copierea.
Eliminați cauzele, nu simptomele. Reducerea termenelor și implementarea code review nu vor rezolva problema dacă în proiect lipsește o bază arhitecturală comună. Investiți timp în crearea de componente reutilizabile în fazele incipiente — este singura modalitate de a reduce tentația copierii-lipirii în viitor.
Căutarea copierii-lipirii se face prin analizoare automate care compară fragmentele de cod și determină potrivirile peste un prag stabilit. Cele mai bune instrumente funcționează la nivel de AST (arbore sintactic abstract) și ignoră formatarea, numele variabilelor și comentariile.
PMD CPD (Copy-Paste Detector) — cel mai răspândit instrument pentru Java, Kotlin, Swift, JavaScript, Python și C++. CPD analizează token-urile codului sursă și găsește duplicate mai lungi decât un număr minim de token-uri stabilit (implicit 100). Setarea pragului este cheia unui rezultat calitativ: un prag prea scăzut dă multe rezultate false pozitive (pattern-uri comune precum import-urile), un prag prea ridicat ratează duplicatele reale.
plugins {
id 'pmd'
}
pmd {
toolVersion = '7.0.0'
ruleSetFiles = files("pmd-rules.xml")
}
tasks.register('cpd') {
doLast {
exec {
workingDir = projectDir
commandLine 'cpd',
'--minimum-tokens', '75',
'--language', 'kotlin',
'--files', 'src/main/kotlin',
'--format', 'xml',
'--failOnViolation', 'true'
}
}
}
SonarQube încorporează detectorul de duplicate direct în Quality Gate. Regula Duplicated Blocks (%) arată proporția de cod duplicat. Pragul de 5 procente este considerat sănătos pentru proiectele comerciale. Depășirea blochează promovarea în ramura de release. SonarQube grupează suplimentar duplicatele după tip: copii exacte (exact match) și copii structurale (cu nume modificate).
Pentru JavaScript și TypeScript, duplicatele sunt căutate cu ESLint și pluginul eslint-plugin-sonarjs (regula no-duplicate-string) și cu utilitarul jscpd, care suportă 150+ limbi. jscpd este deosebit de convenabil pentru monorepozitorii: găsește duplicate între pachete, nu doar în interiorul unui singur modul.
Refactorizarea copierii-lipirii se rezumă la un principiu: extrageți ceea ce este comun și parametrizați diferențele. Tehnica concretă depinde de volumul duplicării și de context.
Cazul cel mai simplu — duplicarea într-o singură clasă (de exemplu, două metode cu aceeași logică, dar cu tipuri diferite). Soluția — generalizarea prin generice sau reutilizarea metodei cu un parametru de tip. Dacă duplicarea acoperă mai multe clase — extrageți codul comun într-o clasă utilitară sau funcție de extensie.
Cazul mai complex — duplicarea la nivel de ecrane sau module. Aici simpla extragere a funcției nu ajută, deoarece se duplică structura UI, logica ciclului de viață și legarea datelor. Soluția — crearea unei clase de bază comune pentru ecran sau a unei componente de vizualizare compozită, iar diferențele se transmit prin parametri sau protocol.
// înainte - două copii ale aceluiași UITableViewController
class UserListController: UITableViewController {
private let viewModel = UserListViewModel()
// 40 de linii de cod
}
class ProductListController: UITableViewController {
private let viewModel = ProductListViewModel()
// aceleași 40 de linii dar cu Product în loc de User
}
// după - clasă de bază generică partajată
class ListViewController<T: ListViewModel>: UITableViewController {
let viewModel: T
// 40 de linii de cod - doar o dată
init(viewModel: T) {
self.viewModel = viewModel
super.init(style: .plain)
}
}
Cazul cel mai complex — duplicarea între microservicii sau biblioteci. Extragerea codului comun poate duce la dependențe ciclice sau la o cuplare nejustificată. În astfel de cazuri, copierea-lipire poate fi o decizie conștientă: două echipe întrețin servicii independente, iar o bibliotecă comună creează mai multe probleme decât rezolvă. Cel mai important — documentați o astfel de decizie și verificați regulat dacă copiile nu au divergat atât de mult încât a sosit momentul unificării.
Profilaxia copierii-lipirii este mai eficientă decât refactorizarea codului deja duplicat. Principalele măsuri preventive constau în organizarea procesului de dezvoltare, nu în tehnologii.
Prima măsură — code review cu accent pe duplicare. Lista de verificare a revizuirii trebuie să includă punctul: „Nu există în acest PR cod care există deja în proiect?”. Dacă recenzentul vede copiere-lipire — blochează integrarea până la extragerea componentei comune. Această cerință trebuie înscrisă în Definition of Done a echipei.
A doua măsură — biblioteca comună de componente. Fiecare pattern UI care apare pe două sau mai multe ecrane trebuie extras într-un modul comun. Creați un modul partajat în proiect și faceți-l punct de intrare obligatoriu pentru toate componentele UI. Dacă componenta nu există — mai întâi creați-o, apoi utilizați-o pe ecran.
A treia măsură — automatizarea în CI/CD. Adăugați în pipeline un pas cu verificarea codului duplicat (PMD CPD, jscpd, SonarQube). Depășirea pragului — eroare de compilare. Dezvoltatorul nu poate integra un PR care crește proporția de copiere-lipire peste nivelul admisibil. Aceasta mută responsabilitatea de la code review la automatizare și garantează că niciun duplicat nu va fi omis.
Implementați cultura „o implementare — un loc”. Dacă vedeți o posibilitate de reutilizare — nu amânați refactorizarea pe mai târziu. Fiecare copiere-lipire lăsată „pentru mai târziu” se multiplică și se transformă într-o datorie tehnică incontrolabilă.
Întrebări frecvente
Nu, există scenarii de duplicare conștientă: microservicii diferite care trebuie să evolueze independent; cod copiat pentru experiment cu plan de ștergere; DTO-uri șablon pentru diferite versiuni de API. Important este să documentați motivul și să stabiliți un termen de verificare pentru refactorizare.
Copierea-lipire — atunci când două părți de cod fac același lucru, dar nu au o abstracție comună. Reutilizarea sănătoasă — atunci când codul comun este extras într-o funcție, clasă sau modul, iar diferențele sunt parametrizate. Dacă modificarea logicii necesită corecturi în trei sau mai multe locuri — este copiere-lipire.
PMD CPD suportă Swift și Objective-C. Pentru Xcode există pluginuri precum SwiftCop și detectorul de duplicate încorporat în AppCode. SonarQube analizează și proiectele Swift, arătând blocurile duplicate direct în pull request.
Deschideți un ticket tehnic pentru refactorizarea fiecărei copii mari. Stabiliți prioritatea: ecranele care se modifică frecvent — în primul rând, cele stabile — în al doilea. Pentru fiecare PR nou care atinge cod duplicat, alocați 15–20 procente din timp pentru consolidarea treptată.
Da, asistenții AI moderni (GitHub Copilot, Codeium) pot analiza contextul și propune extragerea codului comun la detectarea pattern-urilor repetitive. Cu toate acestea, ei nu înlocuiesc analizoarele automate — utilizați Copilot pentru prevenție, iar CPD / SonarQube pentru detecție.
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