Програмування методом копіювання-вставленняПрограмування методом копіювання-вставлення, C&P-програмування або копіпаста в програмуванні — процес створення програмного коду з часто повторюваними частинами, створений операціями копіювати-вставити[1][2]. Зазвичай цей термін використовується в зневажливому розумінні для позначення недостатніх навичок комп'ютерного програмування або відсутності виразного середовища розробки, в якому, як правило, можна використовувати спільні бібліотеки. Програмування методом копіювання-вставлення — поширений антипатерн, що приводить до появи дубльованого коду, зазвичай великого й складного для сприйняття. Повторювані фрагменти коду розмножують помилку, допущену в оригінальному коді, а багаторазові повтори ускладнюють виправлення цієї помилки в копіях[1][3]. Трапляється, коли копіпаста в програмуванні може бути прийнятна або необхідна: шаблони, розмотування циклу (коли немає автоматичної підтримки компілятором), а також у разі застосування деяких парадигм програмування або в разі підтримки редакторами початкового коду у вигляді сніпетів. ПлагіатКопіювання-вставлення часто використовується досвідченим або початківцем-програмістом, який вважає шлях написання коду з нуля складним і намагається шукати написані раніше рішення або часткові рішення, які можна використовувати як основу для вирішення своєї проблеми[4]. Програмісти, які часто копіюють чужий програмний код, часто не розуміють його частково або повністю. Як така, проблема виникає скоріше через їх недосвідченість й відсутність наполегливості, ніж через сам факт копіювання. Скопійований код часто береться у друзів, колег, з інтернет-форумів, від викладачів або з книг із програмування. У результаті код ризикує бути незв'язним набором стилів і може містити надлишок, що вирішує вже відсутні проблеми. Існує певна різниця між програмуванням методом копіювати-вставити і програмуванням типу карго-культ. Під першим мається на увазі сам факт багаторазового дублювання частин коду програми[5], другий тип може мати на увазі як копіювання коду для вирішення завдання, здійснюване з програми або зовнішніх джерел і без розуміння схеми роботи коду, так і копіювання частин коду без необхідності[5][6]. Додаткова проблема полягає в тому, що баги також можуть додаватися з копійованим кодом. Прийоми проєктування, використані в різних початкових кодах, можуть бути не прийнятні в разі їх комбінування в новому середовищі. Такий код також ненавмисно може стати обфускованим, оскільки назви змінних, класів, функцій тощо після копіювання, зазвичай залишаються незмінними, навіть якщо їх призначення абсолютно відрізняється в новому контексті[4]. ДублюванняЯк формі дублювання коду, C&P-програмуванню властиві деякі проблеми, що загострюються, якщо код не зберігає ніякого семантичного зв'язку між оригіналом і копією. У цьому випадку, якщо потрібні зміни, то час витрачається даремно на пошуки всіх частин, що дублюються. Цей процес може бути частково прискорений при добре коментованому коді, але все ж не скасовує необхідність здійснення кількох правок. Оскільки супровід коду часто опускає оновлення коментарів[7], коментарі, які описують, де знайти повторювані частини коду, свідомо застарівають. Ерік Аллен в книзі «Типові помилки проєктування» використовує термін «Фальшива черепиця» для позначення помилок, що викликаються копіюванням фрагмента програми. Виокремлення повторюваного фрагмента в метод (основний «рецепт» позбавлення від такого роду проблем) може виявитися нетривіальним завданням[8]. Використання бібліотекПрограмування методом копіювання-вставлення також нерідко застосовується досвідченими програмістами, що мають свої бібліотеки добре протестованих і готових до використання сніпетів і загальних алгоритмів, що пристосовуються до конкретних завдань[2]. Замість створення декількох змінених копій узагальненого алгоритму, об'єктозорієнтований підхід пропонує абстрагування алгоритму в інкапсульований клас, який може бути використаний повторно. Такий клас створюється гнучким, з повною підтримкою успадкування і перевантаження, що дозволяє коду, який робить виклик, взаємодіяти з одним узагальненим кодом, а не з декількома або багатьма зміненими[9]. У міру розширення необхідної функціональності, бібліотека також збільшується в розмірі (зі збереженням зворотної сумісності). Так, якщо в оригінальний алгоритм вносять виправлення багу, то все програмне забезпечення, що використовує цей алгоритм і бібліотеку, виграє. РозгалуженняРозгалуження є нормальним процесом при розробці програмного забезпечення у великих командах. Він дозволяє здійснювати паралельну розробку на гілках і, отже, скорочувати цикли розробки. Класичне розгалуження володіє наступними особливостями:
Програмування методом копіювати-вставити — це менш формальна альтернатива класичному розгалуженню, часто використовувана в разі, якщо передбачається, що гілки будуть розходитися (різниця коду в гілках буде збільшуватися) з часом більше і більше, як у разі виділення нового програмного продукту з уже наявного. Як спосіб відокремлення нового продукту, копіпаста має деякі переваги. Оскільки розробка нового продукту не вносить зміни у створений раніше, то:
Недоліки:
Ще однією альтернативою C&P-підходу є модульний підхід:
Повторювані завдання або варіації завданняОдна з найбільш шкідливих форм C&P-програмування виражається в появі дубльованого коду, що виконує повторювану задачу або варіацію основного завдання, залежно від деякої змінної. Кожен екземпляр копіює раніше створений, з внесенням незначних змін. Викликаються ефекти:
Навмисний вибір підходуКопіпаста в програмуванні іноді приймається як нормальна техніка програмування. Зазвичай, це можна спостерігати в шаблонах, таких як оголошення класу, підключення стандартних бібліотек або у використанні шаблону наявного коду (з порожнім змістом або функціями-заглушками) як основи для заповнення. Використання ідіом програмування і патернів проєктування схоже на підхід копіювати-вставити, оскільки вони теж використовують шаблонний код. В одних випадках це може бути виражено фрагментом, який на вимогу вставляється в код, хоча часто він просто «викликається» з розуму програміста. В інших випадках використання ідіом не може бути зведене до шаблонного коду. У більшості випадків, однак, навіть якщо ідіома може бути зведена до коду, він буде або занадто довгим (що буде виділено в функцію), або занадто коротким (таким, що його можна набрати безпосередньо). ПрикладПростим прикладом допустимого застосування підходу може бути цикл for, який може виглядати як void foo(int n) {
for (int i=0; i!=n; ++i) {
}
}
Код циклу може бути згенерований наступним сніпетом (визначаючи типи і імена змінних): for ($type $loop_var = 0; $loop_var != $stop; ++$loop_var) {
}
Багато програмістів часто використовують підхід, через небажання переписувати рядок, що відрізняється від попереднього лише кількома символами (наприклад, виклик однієї функції для двох однотипних об'єктів, імена яких розрізняються незначно). Дублювати попередню рядок (також за допомогою клавіатурних скорочень) виявляється швидше, ніж переписати його заново. Але ймовірність допустити помилку не зменшується[14], особливо для останнього рядку[15]. У випадку, якщо необхідно внести більше однієї правки в дубльований рядок, помилки виникають частіше. Як видно з прикладу, після дублювання автор виправив присвоюване значення, але не виправив індекс масиву в лівій частині: mArray[12] = "a";
mArray[13] = "b";
mArray[14] = "c";
mArray[14] = "d";
Існує дослідження[16], спрямоване на «декриміналізацію» програмування методом копіювати-вставити — Subtext (мова програмування)[en]. Слід зазначити, що в цій моделі, копіпаста — основна модель взаємодії і, отже, не розглядається як антипатерн. Див. такожДжерела
Література
|