Копи-пејст (copy-paste) — је пракса копирања фрагмената кода са једног места на друго без прилагођавања новом контексту. Најчешће програмер копира блок из постојећег модула, уноси минималне измене и лепи у нови — заједно са баговима, застарелим коментарима и непотребним зависностима. Према истраживању TIOBE Code Quality Survey (2025), пројекти са високим нивоом копи-пејста садрже три пута више дефеката на хиљаду линија кода него пројекти са јединственом апстракцијом. Дуплирање кода — главни добављач техничког дуга: свака копија захтева посебно одржавање, а исправка бага на једном месту не гарантује његову исправку на осталима.
Главно
Копи-пејст (copy-paste programming) — је преношење постојећег кода на ново место са мањим изменама или без њих. Термин се користи у погрдном смислу: сугерише да програмер не пројектује решење, већ механички копира готов блок, често не разумевајући у потпуности како ради.
Копи-пејст је два типа: оправдани (intentional) и случајни (accidental). Оправдани — када програмер намерно копира код са планом каснијег рефакторинга (али се план често не испуњава). Случајни — када дуплирање настаје неприметно, на пример, два програмера независно пишу исту логику за различите екране.
Према извештају SonarQube State of Clean Code (2025), дуплирани код чини у просеку 12–18 процената укупног обима кода у комерцијалним пројектима. Истовремено, трошак исправке бага у дуплираном коду је 2,5 пута већи него у коду са јединственом имплементацијом, јер програмер мора да пронађе и поправи све копије.
Главни алат за борбу против копи-пејста је принцип DRY (Don't Repeat Yourself). Међутим, апсолутизовање DRY-ја је такође опасно: понекад је копирање оправдано када две копије морају да еволуирају независно једна од друге. Важно је разликовати „случајно дуплирање” (које треба отклонити) и „неопходно дуплирање” (које треба документовати).
Прва и највећа опасност — размножавање багова. Ако у изворном коду постоји дефект, он се копира у сва нова места заједно са кодом. Када се дефект открије и поправи у изворном модулу, копије остају неисправљене. Програмер можда чак ни не слути да баг постоји у пет различитих фајлова.
Друга опасност — неравномерна еволуција. Две копије истог алгоритма временом добијају различите измене. У једној копији је додата валидација граничних вредности, у другој — промењен је формат излаза. Неколико месеци касније постаје немогуће одредити која верзија је „исправна”, а пројекат губи конзистентност понашања.
Трећа опасност — повећање обима тестова. Сваки копи-пејст захтева сопствене тестове. Ако се заједничка логика издвоји у једну функцију, може се покрити једним скупом тестова и поновно користити. Код дуплирања, сваку копију треба тестирати одвојено — то вишеструко повећава време извршавања CI-ја и обим одржаване тест базе.
Четврта опасност — илузија продуктивности. Копи-пејст ствара лажни осећај брзине: програмер брзо убацује код и види да екран ради. Али ова „брзина” се претвара у технички дуг који ће се морати вратити са каматом када се у дуплираном блоку пронађе баг или буде потребна промена пословне логике.
Разумевање узрока копи-пејста помаже у изградњи правилне превенције. Најчешће програмери копирају код не из лењости, већ због притиска рокова, недостатка знања или незгодне архитектуре.
Први разлог — рокови. Када треба направити екран за два дана, а сличан екран већ постоји, програмер га копира у целини и мења само оно што корисник види. За рефакторинг са издвајањем заједничке компоненте нема времена — клијент очекује резултат. Као резултат настаје други екран са 80 посто заједничког кода, али са независном историјом измена.
Други разлог — недостатак јединствене апстракције. Ако у пројекту не постоји заједничка компонента за типичан задатак (на пример, екран листе са pull-to-refresh), сваки програмер ће писати своју имплементацију или копирати суседну. Архитектонске одлуке донете на почетку пројекта директно утичу на количину будућег копи-пејста.
Трећи разлог — страх од ломљења радећег кода. Програмер зна да постојећи модул ради. Рефакторинг са издвајањем заједничког кода може утицати на постојећу функционалност. Ако је покривеност тестовима ниска, ризик од ломљења превазилази перципирану корист од рефакторинга, и програмер бира сигуран пут — копирање.
Отклањајте узроке, а не симптоме. Скраћивање рокова и увођење code review-ја неће решити проблем ако у пројекту недостаје заједничка архитектонска основа. Улажите време у стварање компоненти за вишекратну употребу у раним фазама — то је једини начин да се смањи искушење копи-пејста у будућности.
Претрага копи-пејста се обавља аутоматским анализаторима који упоређују фрагменте кода и одређују подударања изнад задатог прага. Најбољи алати раде на нивоу AST (апстрактног синтаксног стабла) и игноришу форматирање, имена променљивих и коментаре.
PMD CPD (Copy-Paste Detector) — најраспрострањенији алат за Java, Kotlin, Swift, JavaScript, Python и C++. CPD анализира токене изворног кода и проналази дупликате дуже од задатог минималног броја токена (подразумевано 100). Подешавање прага је кључ за квалитетан резултат: пренизак праг даје много лажних поклапања (заједнички обрасци попут import-а), превисок — пропушта стварне дупликате.
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 уграђује детектор дупликата директно у Quality Gate. Правило Duplicated Blocks (%) показује удео дуплираног кода. Праг од 5 процената се сматра здравим за комерцијалне пројекте. Прекорачење блокира промоцију у релизну грану. SonarQube додатно групише дупликате по типу: тачне копије (exact match) и структурне копије (са измењеним именима).
За JavaScript и TypeScript дупликати се траже ESLint-ом са додатком eslint-plugin-sonarjs (правило no-duplicate-string) и алатом jscpd, који подржава 150+ језика. jscpd је посебно погодан за монорепозиторијуме: проналази дупликате између пакета, а не само унутар једног модула.
Рефакторинг копи-пејста се своди на један принцип: издвојити заједничко и параметризовати разлике. Конкретна техника зависи од обима дуплирања и контекста.
Најједноставнији случај — дуплирање у једној класи (на пример, два метода са истом логиком, али различитим типовима). Решење — генерализовати кроз генерике или поновно користити метод са параметром типа. Ако дуплирање обухвата неколико класа — издвојити заједнички код у утилитну класу или extension функцију.
Сложенији случај — дуплирање на нивоу екрана или модула. Овде једноставно издвајање функције не помаже, јер се дуплира структура UI-ја, логика животног циклуса и повезивање података. Решење — креирати заједничку базну класу екрана или композитну View компоненту, а разлике преносити кроз параметре или протокол.
// пре - две копије истог UITableViewController-а
class UserListController: UITableViewController {
private let viewModel = UserListViewModel()
// 40 линија кода
}
class ProductListController: UITableViewController {
private let viewModel = ProductListViewModel()
// истих 40 линија али са Product уместо User
}
// после - заједничка базна класа
class ListViewController<T: ListViewModel>: UITableViewController {
let viewModel: T
// 40 линија кода - само једном
init(viewModel: T) {
self.viewModel = viewModel
super.init(style: .plain)
}
}
Најсложенији случај — дуплирање између микросервиса или библиотека. Издвајање заједничког кода може довести до цикличних зависности или неоправданог повезивања. У таквим случајевима копи-пејст може бити свесна одлука: два тима одржавају независне сервисе, а заједничка библиотека ствара више проблема него што решава. Најважније — документовати такву одлуку и редовно проверавати да ли су се копије толико разишле да је време за унификацију.
Превенција копи-пејста је ефикаснија од рефакторинга већ дуплираног кода. Главне превентивне мере леже у организацији развојног процеса, а не у технологијама.
Прва мера — code review са акцентом на дуплирање. Контролна листа ревизије треба да садржи тачку: „Нема ли у овом PR-у кода који већ постоји у пројекту?”. Ако рецензент види копи-пејст — блокира спајање до издвајања заједничке компоненте. Овај захтев треба да буде утврђен у Definition of Done тима.
Друга мера — заједничка библиотека компоненти. Сваки UI образац који се појављује на два или више екрана треба да буде издвојен у заједнички модул. Направите shared модул у пројекту и учините га обавезном тачком улаза за све UI компоненте. Ако компонента не постоји — прво је направите, а тек онда користите на екрану.
Трећа мера — аутоматизација у CI/CD. Додајте у цевовод корак са провером дуплираног кода (PMD CPD, jscpd, SonarQube). Прекорачење прага — грешка изградње. Програмер не може да споји PR који повећава удео копи-пејста изнад дозвољеног нивоа. Ово помера одговорност са code review-ја на аутоматизацију и гарантује да ниједан дупликат неће бити пропуштен.
Уводите културу „једна имплементација — једно место”. Ако видите могућност поновног коришћења — не одлажите рефакторинг за касније. Сваки копи-пејст остављен „за касније” се умножава и претвара у неконтролисани технички дуг.
Често постављана питања
Не, постоје сценарији свесног дуплирања: различити микросервиси који морају да еволуирају независно; код копиран за експеримент са планом уклањања; шаблонски DTO-и за различите верзије API-ја. Важно је документовати разлог и поставити рок за проверу рефакторинга.
Копи-пејст — када два дела кода раде исту ствар, али немају заједничку апстракцију. Здраво поновно коришћење — када је заједнички код издвојен у функцију, класу или модул, а разлике су параметризоване. Ако промена логике захтева исправку на три или више места — то је копи-пејст.
PMD CPD подржава Swift и Objective-C. За Xcode постоје додаци попут SwiftCop и уграђени детектор дупликата у AppCode-у. SonarQube такође анализира Swift пројекте, приказујући дуплиране блокове директно у pull request-у.
Отворите технички тикет за рефакторинг сваке веће копије. Одредите приоритет: екрани који се често мењају — у првом реду, стабилни — у другом. За сваки нови PR који дотиче дуплирани код, издвајајте 15–20 процената времена за постепену консолидацију.
Да, савремени AI асистенти (GitHub Copilot, Codeium) могу анализирати контекст и предложити издвајање заједничког кода при откривању понављајућих образаца. Међутим, они не замењују аутоматске анализе — користите Copilot за превенцију, а CPD / SonarQube за детекцију.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође