Як ви безпечно видаляєте фрагмент коду, який виглядає так, що він ніколи не вводиться?


125

Ви знайшли якийсь код, який виглядає зайвим, і компілятор цього не помічає. Що ви робите, щоб бути впевненим (чи максимально близьким до впевненості), що видалення цього коду не спричинить регресу.

Дві ідеї спадають на думку.

  1. "Просто" використовувати відрахування на основі того, виглядає чи ні код, який він повинен виконати. Однак, іноді це може бути складною, трудомісткою роботою, трохи ризикованою (ваша оцінка схильна до помилок), без істотного повернення бізнесу.

  2. Розмістіть журнал у цьому розділі коду і побачте, як часто він вводиться на практиці. Після достатньої кількості виконань, ви повинні мати достатню впевненість, що видалення коду безпечно.

Чи є кращі ідеї чи щось на зразок канонічного підходу?


55
Можливо, буде корисно переглянути історію контролю версій: Коли був створений "мертвий код"? Чи виглядав він мертвим, коли його створили? Чи перевірявся інший код (який з тих пір був змінений або видалений), у якому він використовувався, одночасно з його створенням?
ChrisW

9
Компілятору не можна довіряти, якщо в роботі є будь-яка форма метапрограмування, наприклад, відображення. Належне схвалення базового каталогу - важлива практика. Також звичайно мати кілька програм спільного використання програм, тому не забудьте ввести правильний рівень каталогу.
Адам Порожня

16
Я б запитав - "Навіщо турбуватися видаляти його?". Якщо він використовується в якомусь крайовому випадку, який називається один раз синім місяцем, ви зламали речі. Якщо він ніколи не використовується, і ви залишите його там, шкода полягає в тому, що виконуваний файл є трохи меншим за розмір. Якщо це не для якогось вбудованого пристрою, це велика справа? Напишіть на нього коментар і перейдіть до продуктивного використання свого часу.
mickeyf

40
@mickeyf Шкода в тому, що хтось повинен підтримувати цей код. Це означає, що розробник повинен розуміти, що він робить. Розробник повинен змінити його, якщо все зміниться, і код навколо нього тепер повинен зробити щось інше. Повірте, коли ти залишаєш лежачи навколо, це головний біль для тих, хто намагається зрозуміти речі пізніше.
jpmc26

9
@MichaelJ. Моя думка, це не повинно було там бути в першу чергу. І якщо я залишу це, ситуація ще гірша: тепер якийсь інший розробник, який знаходиться в лінійці, повинен це дослідити. Чим довше він залишається, тим більше часу витрачається на його розуміння. Це вартість зайвого коду.
jpmc26

Відповіді:


112

У моєму ідеальному світі фантазій, де я маю 100% тестовий покрив, я би просто видалив його, запустив мої тестові одиниці, і коли жоден тест не стане червоним, я виконую його.

Але, на жаль, я маю прокидатися щоранку і стикатися з суворою реальністю, коли багато коду або не мають одиничних тестів, або коли вони там є, не можна довіряти, щоб справді висвітлити всі можливі випадки. Тож я б розглядав ризик / винагороду і прийшов до висновку, що цього просто не варто:

  • Нагорода: Код трохи простіше підтримувати в майбутньому.
  • Ризик: розбийте код у якомусь незрозумілому краєвому випадку, про який я не думав, спричиніть інцидент, коли я його найменше очікую, і винен у ньому, тому що мені довелося задовольнити якість коду OCD та внести зміни, не маючи ділової цінності. будь-якій із зацікавлених сторін, яка не є самим кодером.

249
Спостерігаючи за станом великих програмних проектів, де інженери протягом десяти-дванадцяти років здебільшого дотримувалися підходу "не варто" для видалення ймовірного зайвого коду, я не можу рекомендувати такий підхід.
njuffa

125
Також одиничні тести нічого не говорять про те, чи справді цей код використовується у виробництві. Код міг би бути ідеально перевіреним, але все ще не використовується у виробництві, тому зайвим.
кнб

8
На мій досвід, стан таких проектів ніколи не пов'язаний із підходом "не варто" до виправлення коду після факту, це завжди пов'язано з тим, що в першу чергу пишеться поганий код. Помилково написати неправильний код, але також помилка (більш вдосконалена помилка) вважати, що код очищення завжди того вартий.
Вейланд Ютані

42
@Weyland Yutani Це зовсім не відповідає моєму досвіду. Більшість можливих зайвих кодів, які я бачив, були достатньо добре написаними та цілком розумними, враховуючи специфікації програмного забезпечення, апаратні платформи або версії операційної системи, що існували за десяток років до цього, необхідні для усунення помилок або обмежень у ланцюжку інструментів чи обладнання, наявних раніше тощо. .
njuffa

20
Відповідь пропускає одну з найважливіших і найважливіших переваг іти вперед та вносити зміни: навчитися щось. Дізнавшись про це, ви можете додати структуру (коментарі, тести), щоб пізніше допомогти у підтримці розробників. Вибір не змінювати щось, тому що ви не знаєте наслідків - це програмування культового культу, навіть якщо цей вибір не полягає в тому, щоб щось видалити.
Кідро

84

У цьому процесі є дві половини. Перший - підтвердження того, що код дійсно мертвий. Друге - це розуміння витрат на помилку та переконання, що вони належним чином зменшені.

Багато відповідей тут мають чудові рішення для колишньої половини. Такі інструменти, як статичні аналізатори, чудово підходять для виявлення мертвого коду. grepможе бути вашим другом у деяких випадках. Один незвичайний крок, який я часто роблю, - це спробувати визначити, в чому полягала початкова мета коду. Набагато простіше стверджувати, що "X більше не є характеристикою нашого продукту, і сегмент коду Y був розроблений для підтримки функції X", ніж це сказати "Я не бачу жодної мети для кодового сегмента Y."

Друга половина є ключовим кроком для вирішення будь-якого блокування сітки щодо того, чи слід видаляти код. Вам потрібно зрозуміти, які наслідки мають неправильну відповідь. Якщо люди помруть, якщо ви отримаєте неправильну відповідь, зверніть увагу! Можливо, настав час прийняти, що кодовий супровід розвивається з часом, і натомість намагайтеся не писати більше сурових матеріалів. Якщо люди не помруть, запитайте себе, як прощають ваші користувачі. Чи можете ви надіслати їм виправлення, якщо ви щось зламали і підтримуєте відносини з клієнтами? Чи є у вас група з питань відповідей, яка оплачує пошук таких питань? Такі питання важливі для розуміння того, наскільки ви повинні бути певними, перш ніж натиснути клавішу видалення.

У коментарях rmun вказав на відмінне формулювання концепції розуміння початкової мети коду перед його видаленням. Цитата тепер відома як огорожа Честертона . Хоча вона занадто велика, щоб цитувати її безпосередньо в коментарі, я думаю, що вона заслуговує на те, щоб її тут цитували належним чином:

Що стосується реформування речей, на відміну від їх деформування, існує один простий і простий принцип; принцип, який, ймовірно, буде називатися парадоксом. У такому випадку існує певна установа чи закон; Скажімо, для простоти паркан або ворота, встановлені через дорогу. Більш сучасний тип реформаторів підходить до цього і каже: "Я не бачу в цьому використання; давайте нам це очистимо ». На що більш розумний тип реформатора буде добре відповідати:« Якщо ви не бачите в ньому використання, я, безумовно, не дозволять вам це очистити. Іди геть і думай. Тоді, коли ви зможете повернутися і сказати мені, що ви бачите використання цього, я можу дозволити вам знищити його.


14
Огорожа Честертона передбачає, що відкриття відбувається виключно за допомогою мислення, і не пропонує регресу - досить давньогрецька філософія. Науковий метод є більш сучасним - розробити контрольований експеримент для визначення наслідків видалення структури. Безумовно, я б не пропонував цей експеримент проводити у виробництві. Але якщо альтернативи немає, а витрати на випробування на виробництві дуже високі, я б швидше покинув робоче місце, яке не запропонувало мені безпечних засобів дізнатися, чому існує якийсь код - особистий ризик на такій роботі занадто високий .
kojiro

15
@kojiro Це дуже правда. Мені подобається думати, що Честертон був би добре, якби я, як "сучасний реформатор", зайшов і сказав: "Я не знаю, чому цей паркан тут, я це визнаю. Але я хотів би пофарбувати його в червоний колір, щоб побачити, чи що дає мені будь-яку нову інформацію, "Честертон, певно, був би задоволений цим.
Корт Аммон

41
Метод декодування тактового режиму ядра VMS OS SYS $ ASCTIM містить рядок коду, який допомагає виправити бічний зсув весняного рівнодення. Жоден з підрозділів тестів ДЕК не виконує цей код. Він пробіг один раз - правильно - 2000-02-28 о 23: 59: 59: 999. Він не працюватиме знову до 2400 року. Будь ласка, не видаляйте його.
А. І. Бревелері

13
@AIBreveleri Я сподіваюся, що в самому коді є коментар, що пояснює це, а не лише тут, на StackExchange: D
Кайл Странд

11
@KyleStrand Про що ти говориш? Це є документація. Чи можете ви придумати краще місце для розміщення важливої ​​інформації, щоб інші люди знаходили її, ніж StackExchange? ;-)
Корт Аммон

43

Я також схильний до grepназви функції / класу в коді, який може дати додаткові переваги, які аналізатор коду може не мати, наприклад, якщо ім'я згадується в коментарі або в файлі документації, або скрипті, наприклад. Я запускаю grep на файли у вихідному дереві та зберігаю результат у файлі; зазвичай результат дає стисну інформацію: ім'я / шлях файлу, номер рядка та рядок, де зустрічається ім'я, що може дати підказки, де функція / клас викликається або згадується без будь-якого семантичного значення (на відміну від аналізатора коду ) і незалежно від розширень файлів. Однозначно не остаточне рішення, а приємне доповнення до аналізу.


11
Я не прихильник, але що робити, якщо розділ коду, який ви підозрюєте, ніколи не запускається, не є повною функцією чи класом, а розділом методу / функції?
Тулен Кордова

9
Залежно від мови це не завжди може бути надійним - деякі мови дозволяють здійснювати виклики методів динамічно. Наприклад php:$object->$variableMethod($arg1, $arg2);
Dezza

9
@ TulainsCórdova Тоді, мабуть, це не вдале рішення, очевидно. Що стосується кожного потенційного рішення, використовуйте його, якщо воно має сенс у даному контексті. Але, можливо, grepін. Функція, що охоплює розділ коду, може дати підказки щодо того, як функція використовується і, отже, її вміст?
piwi

7
"наприклад, якщо ім'я згадується в коментарі або у файлі документації або сценарії" - Або якщо хтось використовує відображення для виклику методу (якщо використовується мова високого рівня / OO). Хоча це все ще не обов'язково на 100% точно, оскільки деякі мови підтримують деякі дуже тупі способи пошуку та виклику методів.
aroth

Це корисно, якщо у вас є доступ до всіх можливих кодів, які можуть використовувати цю функцію. Однак якщо код є частиною бібліотеки, як ви дізнаєтесь, що щось інше, через яке ви не можете шукати, не зламається?
Кевін Ши

30
  • Визначте код, який виглядає мертвим (статичний аналіз тощо).
  • Додайте повідомлення журналу до кожного виклику нібито мертвого коду. Це легко за допомогою функцій / методів; зі статичними членами, такими як константи, складніше. Іноді ви можете просто позначити код як устарений, і час виконання автоматично запише повідомлення для вас. Залиште код інакше недоторканим.
    • Запишіть повідомлення під час завантаження мертвого модуля: у більшості мов є спосіб запустити статичну ініціалізацію під час завантаження, що може бути підкріплено.
    • Переконайтеся, що ваше повідомлення журналу містить розумний слід стека, щоб ви зрозуміли, що називається мертвим кодом.
  • Запустіть змінений код через усі ваші тестові набори. Ваші тестові набори також повинні перевіряти особливі часи, наприклад, перехід півночі, поворот чверті, рік року тощо. Погляньте на журнали, оновіть своє розуміння того, що померло. Зауважте, що одиничні тести можуть спеціально перевіряти мертвий код, тоді як жодні інші тести одиниці та інтеграційні тести не торкаються цього.
  • Запустіть змінений код у виробництві протягом декількох тижнів. Переконайтесь, що протягом цього періоду виконується кожен періодичний процес, як-от такі, що виконуються завданнями ETL cron один раз на місяць.
  • Подивіться на колоди. Все, що було зареєстровано, насправді не є мертвим. Перехідне закриття графіку виклику для решти мертвого коду також потенційно не є мертвим, навіть якщо воно не було викликано. Проаналізуйте це. Можливо, деякі гілки надійно мертві (наприклад, робота з API вже вимерлого сервісу), а деякі - ще. Можливо, весь модуль / клас завантажується лише для визначеної в ньому константи, і ви можете легко використовувати його.
  • Те, що залишилося, безпечно мертве, і його можна вилучити.

Все є вперше, тому те, що код не запускався раніше, не означає, що він ніколи не запускається, особливо, якщо до нього є шлях виконання. Однак, рішення про видалення того, що може виконати, відрізняється від визначення того, чи може воно працювати.

7
@nocomprende саме те, що відбувається, якщо цей код використовується лише для функції кінця року, і ви запустили тест, який запускається лютий - листопад. Ви не знайдете використання, навіть якщо ви його пропрацювали майже цілий рік.
Ерік

1
@ 9000 Я погоджуюсь в теорії, але застарілі системи пронизані прихованими залежностями, які можуть перешкодити такому випробуванню. Щоб ваш тестовий приклад працював, ви повинні знати, що існує якась часова зв'язок. Якщо тимчасова зв’язка є зовнішньою для коду, який ви тестуєте, ви не збираєтеся бачити це в коді і знаєте, що тимчасова зв’язка є фактором. Наприклад, код силосу A встановлений в GAC . Роки тому силос B попросив силос A додати шлях коду для звіту, який їм потрібен для даних даних силосу A. продовження
Ерік

1
@ 9000 продовж. Тепер код силосу B має тимчасову прив'язку до "мертвого" кодового шляху в коді силосу A, який не видно, просто переглядаючи код силосу A. Як би ви провели тестування для цієї тимчасової муфти, оскільки тимчасова муфта є лише в коді силосу B, не знаючи говорити з силосом B? Навіть тоді час не є фактором у вашому коді (силос A), то як би виглядав тимчасовий тест?
Ерік

2
Хтось пам’ятає паніку Y2k ? Якийсь код був правильний у 2000 році, оскільки він був неправильним для 2100! У нас виникла потенційна проблема, яка могла виникнути раз на 100 років або навіть раз на 400 років.
Стів Барнс

16

На додаток до згаданих відповідей ви також можете ітеративно вилучити код у кількох версіях.

У початковій версії ви можете зробити попередження про депресацію, коли блок коду все ще функціонує. У версії після цього ви можете видалити блок коду, але залишити повідомлення про помилку, що дозволяє користувачам функція застаріла і більше недоступна. У остаточній версії ви видалите блок коду та будь-які повідомлення.

Це може допомогти виявити непередбачені функціональні можливості без попередження для кінцевих користувачів. У кращому випадку сценарій насправді нічого не робить, і все, що трапляється, полягає в тому, що непотрібний код зберігається протягом декількох версій, перш ніж видалятися.


7
+1. Я бачив так багато помилок і проблем, пов'язаних із клієнтами, яких можна було б уникнути, якби розробники (або їх керівництво) готові були розбити проект на дві-три безпечні фази, а не намагатися перекинути все відразу, щоб відповісти довільний термін до переходу до наступного проекту.
ruakh

Це відповідає на запитання, задане в заголовку, але якщо ви запитаєте мене, питання має неправильну назву. Заголовок запитує, як видалити код, але в тілі йдеться про те, як визначити, чи безпечно його в першу чергу видалити. Ви, безумовно, відповідаєте на колишнього, але я не впевнений, що це дійсно просив ОП.
підкреслюю_d

7

Дуже багато людей припускають, що "безпечну" річ - це залишити код, якщо ви не можете довести, що він не використовується.

Але код - це не актив, це відповідальність.

Якщо ви не зможете пояснити, чому це важливо, і не вказати на його тести, "безпечнішою" альтернативою цілком може бути її видалення.

Якщо ви все ще не впевнені, то принаймні обов'язково додайте тести для виконання коду зомбі.


Крок 1: Видаліть увесь код. Крок 2: Поставте назад те, що потрібно. Крок 3: повторити.

1
@Adrian Чи можу я звернути вашу увагу на Knight Capital? en.wikipedia.org/wiki/… - на всякий випадок, якщо ви хочете посилити свою точку з посиланням на неї. Вони в основному розкрилися через те, що якийсь старий код повернувся до життя і люб’язно втратив майже 500 мільйонів доларів за них. Наступний запит був зосереджений на процедурах їх випуску, але основна проблема полягала в тому, що "мертву функціональність не було видалено".
SusanW

6

Ви можете використовувати функціональні перемикачі, щоб змінити шлях виконання вашого програмного забезпечення, щоб повністю ігнорувати код, про який йде мова.

Таким чином ви можете безпечно розгорнути свої зміни за допомогою не використовуваного коду та вимкнути його. Якщо ви помітили деякі основні помилки, пов’язані з кодом, увімкніть перемикач назад і дослідіть можливий шлях до нього.

Цей підхід повинен дати вам впевненість, якщо ви не бачите жодних проблем протягом тривалого періоду часу, а також можливість повернути його назад у прямому режимі без розгортання. Однак ще кращим способом було б також застосувати додаткове лісозаготівельне та тестове покриття навколо розглянутої області, що дасть більше доказів, застосовується воно чи ні.

Детальніше про тумблери читайте тут: https://martinfowler.com/articles/feature-toggles.html


6

Статичний аналіз звичайно ... і приємно, що вам не потрібні нові інструменти; Ваш компілятор має всі необхідні інструменти статичного аналізу.

Просто змініть назву методу (наприклад, змініть DoSomethingна DoSomethingX), а потім запустіть збірку.

Якщо ваша збірка вдається, метод, очевидно, нічим не використовується. Безпечне видалення.

Якщо збірка не вдається, виділіть рядок коду, який її викликає, і перевірте, які ifоператори оточують виклик, щоб визначити, як його запустити. Якщо ви не зможете знайти жоден можливий випадок використання даних, який його запускає, можете сміливо видалити його.

Якщо ви дійсно переживаєте за його видалення, подумайте про збереження коду, але позначте його ObsoleteAttribute (або еквівалентом вашої мови). Відпустіть його так для однієї версії, а потім видаліть код після того, як у природі не знайдено жодних проблем.


8
Це нормальна порада для мов програмування, які не мають повного динамічного / пізнього прив’язки . Однак для тих, хто є, це складніше. І, звичайно, - код може використовувати метод, навіть якщо він ніколи не використовується у виробництві.
eis

Питання передбачає розв’язання символу часу компіляції ( Отже, ви знайшли якийсь код, який виглядає зайвим. Компілятор цього не помічає. ). Навіть функція або об'єкти із пізньою зв’язкою зазвичай визначаються в двох місцях, наприклад, інтерфейс або файл карти, тому збірка все-таки не зможе.
Джон Ву

1
Хм ... я заінтригований, я не думаю, що останнє, про яке ви говорите, є правдою. Наприклад, це не для ванільного javascript (не попередньо складеного), рубіну, пітона або малих розмов, наприклад? Якщо ви посилаєтесь на речі, які не існують, вони помиляються лише під час виконання.
eis

Можливо, ми не погоджуємося з тим, що означає "прив'язка", яка для мене вказує на дозвіл логічного подання до фізичного зображення, наприклад, символу на адресу. Функції Javascript зберігаються як пари тегів / значень у межах об'єкта, що міститься, тому будь-яке поняття зв'язування здається не послідовним.
Джон Ву

1
Так, ми дійсно не згодні. Термін має інше значення для мов, які не мають повного пізнього зв’язування (як я пояснив у першому коментарі). Коли ви прив'язуєте методи під час виконання - мовами, які можуть додавати та видаляти методи виконання, на ходу - ви використовуєте пізнє прив'язування так, як я розумію, що це робиться. Це вірно в мовах стилю ruby ​​/ python / smalltalk, і там у вас немає окремих файлів карт. Оскільки особливо широко використовуються рубін та пітон, я не погоджуюся з вашим уявленням про те, що це означатиме «типово».
eis

4
  • Я б почав використовувати аналізатор коду, щоб перевірити, чи це мертвий код
  • Я б почав перевіряти свої тести і намагався дійти до коду. Якщо я не зможу дістати код у тестовому випадку, це може бути мертвий код
  • Я б видалив код і замість цього викинув би виняток. Для одного випуску активується виняток, а при другому випуску виняток можна видалити. Щоб забезпечити безпеку, поставте прапор надзвичайних ситуацій (на Java, властивість системи), щоб мати можливість активувати оригінальний код, коли клієнт помічає виняток. Тож виняток можна відключити, а вихідний код можна активувати у виробничому середовищі.

6
-1. Вносити ці зміни у продуктивний код, прапор безпеки чи ні, абсолютно не рекомендується. Тільки тоді, коли ви впевнені, що розглянутий код не використовується, він повинен бути видалений у виробничому коді. Саме такий загрозливий випадок саме тому завжди повинен бути різним продуктивним та тестувальним середовищем.
Йоханнес Хан

3
Це буде працювати в фантазії, коли покриття тесту майже 90%, але що, як ні, і у вас є проект зі 100 000 рядків коду. Ось чому я описав спробувати тестування коду, і якщо жоден тест не зможе дійти до коду ... він може бути мертвим.
Маркус Лаусберг

IMHO Якщо ви не впевнені, що не зможете повністю видалити код - вам не слід викидати винятки у виробництві - ведення журналів, запропонованих ОП, є набагато кращою альтернативою, домогтися того ж, і ви можете отримати діагностику, а не покладатися на скарги клієнтів.
Себі

@JohannesHahn Я думаю, ви маєте на увазі "виробничий код", який є кодом, який працює у виробничому середовищі.
jpmc26

@ jpmc26 Так, звичайно.
Йоханнес Хан

3

Видалення недоступного коду

У принциповій статичній мові ви завжди повинні знати, чи дійсно код доступний чи ні: видаліть його, компілюйте, якщо немає помилки, він не був доступний.

На жаль, не всі мови введені статично, і не всі статично типізовані мови є принциповими. Те, що може піти не так, включає: 1) роздуми та (2) безпринципне перевантаження.

Якщо ви використовуєте динамічну мову або мову з достатньо потужним відображенням, щоб фрагмент коду під контролем міг бути доступний під час виконання за допомогою відображення, ви не можете покластися на компілятор. До таких мов належать Python, Ruby або Java.

Якщо ви використовуєте мову з безпринципною перевантаженням, то просто видалення перевантаження може просто переключити роздільну здатність перевантаження на іншу перевантаження безшумно. Деякі такі мови дозволяють запрограмувати попередження / помилку під час компіляції, пов’язані з використанням коду, інакше ви не можете покластися на компілятор. До таких мов належать Java (використання @Deprecated) або C ++ (використання [[deprecated]]або = delete).

Тож, якщо вам не пощастить працювати зі строгими мовами (на розум приходить іронія), ви, справді, можете стріляти собі в ногу, довіряючи компілятору. І, на жаль, тестові набори, як правило, неповні, тому не набагато більше допомоги.

Перегляньте наступний розділ ...


Видалення потенційно невикористаного коду

Швидше за все, на код посилається насправді, проте ви підозрюєте, що на практиці гілки коду, на які він посилається, ніколи не приймаються.

У цьому випадку, незалежно від мови, код може бути доступним, і можна використовувати лише інструменти, що працюють під час виконання.

Раніше я успішно використовував 3-фазний підхід до видалення такого коду:

  1. На кожній гілці, яку підозрюють, що її НЕ брати, запишіть попередження.
  2. Після одного циклу киньте виняток / поверніть помилку при введенні конкретного фрагмента коду.
  3. Після іншого циклу видаліть код.

Що таке цикл? Це цикл використання коду. Наприклад, для фінансової заявки я б очікував короткий місячний цикл (зарплата виплачується в кінці місяця) та тривалий річний цикл. У цьому випадку вам доведеться почекати щонайменше рік, щоб переконатися, що жодне попередження не надходить, щоб інвентар на кінець року не міг використовувати кодові шляхи, які в іншому випадку ніколи не використовуються.

Сподіваємось, більшість застосувань мають коротший цикл.

Я раджу розмістити коментар TODO із датою та порадою, коли перейти до наступного кроку. І нагадування у вашому календарі.


1
Насправді в C ++ ви можете позначити підозріле перевантаження як [[deprecated]]ідентифікацію сайтів, які називають цю версію; то ви можете оглянути їх, щоб побачити, чи зміниться їх поведінка. Крім того, визначте свою перевантаження як = delete- у цьому випадку вам потрібно буде чітко наводити аргументи, щоб використовувати одну з інших версій.
Toby Speight

@TobySpeight: Це правда, і хороша альтернатива теж. Дозвольте мені це відредагувати.
Матьє М.

"Докторе, боляче, коли я це роблю". "Ну не робіть цього! " Не використовуйте підходи, які роблять код некерованим.

2

Видалення коду з виробництва - це як прибирання будинку. Щойно ви викинете предмет з горища, ваша дружина вб'є вас на наступний день за те, що викинула подарунок третьому племінникові своєї великої матері від їхнього сусіда, який помер у 1923 році.

Серйозно, після побіжного аналізу з використанням різних інструментів, про які вже згадували всі, та після використання вже згаданого підходу поетапної амортизації, майте на увазі, що ви можете піти з компанії, коли відбудеться фактичне видалення. Залишити код і зберегти його виконання, а також гарантувати, що будь-які сповіщення про його виконання обов'язково повідомляються вам (або вашим наступникам та присвоєним), є надзвичайно важливим.

Якщо ви не будете дотримуватися такого підходу, ви, ймовірно, буде вбита вашою дружиною. Якщо ви зберігаєте код (як і кожен подарунок), то можете спокійно сумліватися у тому, що на допомогу приходить закон Мура, а вартість небажаного дискового простору, що використовується кодом, який відчуває себе "скелею в моєму взутті", зменшує кожен рік, і ви не ризикуєте стати центром безлічі пліток, що охолоджують воду, і дивних поглядів у передпокої.

PS: Для уточнення у відповідь на коментар. Оригінальне питання "Як ви безпечно видаляєте .." Звичайно, у моїй відповіді передбачається контроль версій. Так само, як передбачається копати в смітнику, щоб знайти цінне. Жодне тіло з будь-яким сенсом не скидає код і контроль версій не повинні бути частиною суворості кожного розробника.

Проблема полягає в коді, який може бути зайвим. Ми ніколи не можемо дізнатись, що фрагмент коду є зайвим, якщо ми не можемо гарантувати, що 100% шляхів виконання не досягнуть цього. І передбачається, що це досить велика частина програмного забезпечення, що ця гарантія поруч із неможливою. І якщо я не прочитав питання неправильно, єдиний раз, коли ціла нитка розмови є актуальною, це випадки, коли виробництво може викликати видалений код, і, отже, у нас є час виконання / виробництво. Контроль версій нікого не рятує через виробничі збої, тому коментар про "Контроль версій" не стосується питання чи мого початкового пункту, тобто належним чином застарілий протягом надзвичайно тривалого періоду часу, якщо це дійсно доведеться, інакше не робіть "

ІМХО, коментар є зайвим і є кандидатом на видалення.


12
Якщо б я мав еквівалент контролю версій , заперечення моєї дружини буде легко відмінено. Так само і зі видаленням коду: це не вбивство. Сховище ніколи не викидається.
JDługosz

Я думав, що об'єктно-орієнтоване програмування повинно звузити сферу, в якій може бути названий метод. Тож це повинно вести до коду, який легше зрозуміти та керувати, правда? Інакше чому ми це робимо саме так?

@nocomprende Ніде в цій темі не вказано, що обговорення обмежується лише дизайном / мовами OOP. Я не впевнений, чому ви вважаєте, що це актуально.
підкреслюй_d

1

Можливо, компілятор це помічає, він просто не суєтиться.

Запустіть збірку з повною оптимізацією компілятора, орієнтованою на розмір. Потім видаліть підозрілий код і запустіть збірку заново.

Порівняйте двійкові файли. Якщо вони однакові, компілятор помітив і мовчки видалив код. Ви можете безпечно видалити його з джерела.

Якщо бінарні файли різні ... то це непереконливо. Це може бути якась інша зміна. Деякі компілятори навіть включають дату та час компіляції у двійковій файл (і, можливо, її можна налаштувати далеко!)


1
Не всі мови компільовані, не всі компілятори мають оптимізацію, і не всі оптимізації рівні, багато хто не видаляє незакликаний код на випадок, якщо код є з причини. Якщо код живе у спільній бібліотеці / DLL, він не буде видалений.
Стів Барнс

1
@SteveBarnes Ну так, якщо ви не займаєтесь LTO і статичним зв'язком все, ви відчуваєте біль. Це дано.
Навін

1

Я фактично нещодавно зіткнувся з такою точною ситуацією, з методом, який називається "deleteFoo". Ніде у всій кодовій базі не було знайдено, що рядок, окрім декларації методу, я мудро написав рядок журналу у верхній частині методу.

PHP:

public function deleteFoo()
{
    error_log("In deleteFoo()", 3, "/path/to/log");
}

Виявляється, що код був використаний! Деякий метод AJAX викликає "метод: delete, elem = Foo", який потім об'єднується і викликається за допомогою call_user_func_array () .

Коли ви сумніваєтесь, увійдіть! Якщо ви пройшли достатньо часу, не побачивши журнал заповненим, тоді подумайте про видалення коду. Але навіть якщо ви видалите код, залиште журнал на місці та прокоментуйте дату, щоб полегшити пошук фіксації в Git хлопцеві, який має його підтримувати!


Тут можуть бути корисні бібліотеки PHP та Perl під назвою Tombstone (php: github.com/scheb/tombstone ).
Алістер Бульман

0

grepСпершу використовуйте будь-які інструменти, які у вас є, ви можете знайти посилання на код. (Спочатку не моя інструкція / порада.)

Тоді вирішіть, чи хочете ви ризикувати видаленням коду, чи могла моя пропозиція використати:

Ви можете змінити функцію / блок коду, щоб записати, що він був використаний у файлі журналу. Якщо таке повідомлення ніколи не записується у файл журналу, ви, ймовірно, можете видалити код журналу.

Дві проблеми:

  1. Отримання журналу від інших користувачів. Можливо, ви можете встановити глобальний прапор, який розбить програму при виході і ласкаво попросіть користувача надіслати вам журнал помилок.

  2. Відстеження абонента. У деяких мовах високого рівня (наприклад, Python) ви можете легко отримати прослідкування. Але в компільованих мовах вам доведеться зберегти зворотну адресу в журнал і примусити скинути основний дамп при виході (точка 1).
    У C це повинно бути досить простим: використовуйте умовний блок (наприклад, #ifdef ... #endif), щоб використовувати це лише тоді, коли ви знаєте, що він буде працювати (і перевірили, що він робить), і просто прочитайте зворотну адресу зі стека (може бути, а може і не вимагати вбудованої мови складання).

Збереження аргументів у файлі журналу може чи не може бути корисним.


0

Якщо ви знаєте, що робить код, що оточує, тестуйте його, щоб він не порушився. Це найпростіший і найвигідніший спосіб змінити коефіцієнт коду, над яким ви працюєте, і все-таки це слід зробити в будь-якому випадку для розробки будь-яких змін коду, над яким ви працюєте.

Якщо, з іншого боку, ви переробляєте фрагмент коду, де ви не знаєте, що це робить, не видаляйте його . Спершу зрозумійте це, а потім перефактуруйте його, якщо визначите, що це безпечно (і лише якщо ви зможете визначити, що рефакторинг буде належним чином використовувати ваш час).

Зараз можуть виникнути певні обставини (я знаю, що я сам зіткнувся з цим), коли код "мертвий" насправді не пов'язаний ні з чим . Наприклад, бібліотеки коду, розроблені підрядником, які ніколи насправді ніде не впроваджувались, оскільки вони застаріли відразу після доставки програми (чому так, я маю на увазі конкретний приклад, як ви це знали?).

Я особисто завершив видалення всього цього коду, але це величезний ризик, що я не рекомендую робити це злегка - залежно від того, скільки коду ця зміна може потенційно вплинути (адже завжди є потенціал, що ви щось не помітили) ви слід бути надзвичайно обережними та проводити агресивні тестові одиниці, щоб визначити, чи видалення цього старовинного застарілого коду порушить вашу програму.

Тепер все, про що йдеться, мабуть , не варто витрачати свій час чи розум, щоб спробувати видалити такий код. Якщо тільки ви не станете серйозною проблемою з вашою заявкою (наприклад, не в змозі завершити сканування безпеки через розрив програми ... чому так, я все ще маю на увазі приклад), тому я б не рекомендував це, якщо ви не досягнете така ситуація, коли код справді почав гнити вражаючим чином.

Отже, коротше - якщо ви знаєте, що робить код, спершу протестуйте його. Якщо цього не зробити, ви, ймовірно, можете залишити його в спокої. Якщо ви знаєте, що не можете залишити його в спокої, приділіть свій час, щоб перевірити зміну агресивно, перш ніж вносити зміни.


0

Мій підхід, який я завжди вважав галузевим стандартом у цьому випадку, дивно не згадувався досі:

Отримайте другу пару очей.

Існують різні види "невикористаного коду", а в деяких випадках видалення доречне, в інших випадках слід перефактурувати його, а в інших випадках ви тікаєте, наскільки можете, і ніколи не озираєтесь назад. Вам потрібно розібратися, що це таке, і для цього вам найкраще пару з другою - досвідченою! - розробник, той, хто дуже добре знайомий з кодовою базою. Це суттєво знижує ризик виникнення непотрібної помилки та дозволяє внести необхідні вдосконалення, щоб утримувати базу коду в стані, що підтримується. Якщо ви цього не зробите, у якийсь момент у вас закінчуються розробники, які дуже добре знайомі з кодовою базою.

Я бачив і підхід до ведення журналів - точніше, я бачив код реєстрації: ще більше мертвого коду, який залишився там протягом 10 років. Підхід до реєстрації даних є досить пристойним, якщо ви говорите про видалення цілих функцій, але не, якщо ви просто видаляєте невеликий шматочок мертвого коду.


0

Проста відповідь на ваше запитання полягає в тому, що ви не можете безпечно видалити код, який ви не розумієте, що включає не розуміння, як його викликати. Буде якийсь ризик.

Вам доведеться судити, як найкраще пом'якшити цей неминучий ризик. Інші згадували лісозаготівлю. Звичайно, журнал може довести, що він використовується, але не може довести, що він не є. Оскільки головною проблемою з мертвим кодом є те, що він зберігається, ви можете уникнути, додавши коментар, у якому йдеться про те, що він підозрюється у мертвому коді, і не робити його на підтримку.

Якщо код знаходиться під контролем джерела, ви завжди можете дізнатися, коли він був доданий, і визначити, як він тоді називався.

Зрештою, ви або розумієте це, залишаєте його в спокої, або ризикуєте.


0

Якщо розробник відповідного коду все ще доступний, перегляньте його видалення . Також читайте коментарі в коді .

Ви отримаєте належне пояснення, чому цей код додано і для якої функції він використовується. Це легко може бути підтримкою конкретного випадку використання, або ви навіть не можете мати достатньо досвіду, щоб оцінити, чи справді це не потрібно. В крайньому випадку, ви можете видалити всі безкоштовні заяви із програми C і не помітити нічого поганого (це може зайняти кілька хвилин, щоб не вистачило пам'яті).

Це справді погана культура, коли автор коду сидить поруч, але ти не бачиш приводу говорити, бо ти впевнений, що він просто пише поганий код, а твій все так ідеально. І, звичайно, він просто пише випадкові слова в коментарях, не потрібно витрачати час на читання.

Однією з найважливіших причин писати коментар у коді є пояснення ЧОМУ це було реалізовано таким чином. Ви можете не погодитися з рішенням, але вам потрібно взяти до уваги проблему.

Обговорення з автором може також виявити, що код є історичним залишком чогось вилученого або ніколи не закінченого, тому його безпечно видалити.


-1

Я повністю погоджуюся з першим моментом Маркуса Лаусберга: Код, безумовно, слід проаналізувати за допомогою інструментів. Мавпам мавп не варто довіряти подібне завдання !!

Більшість стандартних мов програмування можна використовувати в IDE, і кожен IDE, який варто викликати, має "знахідку для всіх звичаїв" - особливості, яка є правильним інструментом для подібної ситуації. (Ctrl + Shift + G в Eclipse, наприклад)

Звичайно: Статичні інструменти аналізатора не є ідеальними. Потрібно знати про складніші ситуації, коли рішення про те, що викликається відповідний метод, відбувається лише під час виконання та не раніше (дзвінки через Reflection, виклики функцій "eval" у мовах скриптів тощо).


5
Можливо, мавпам мавп не слід писати код? " Недоторкані людськими руками " раніше були маркетинговою фразою. Я завжди уявляв руки горили, яка виконує роботу.

3
(Ape мозги теж писали інструменти) (Shhh! Ви

1
Я думаю, ви обидва пропускаєте мою думку. Я чітко сказав, що немає гарантії, що статичний аналіз коду знайде кожне виклик методу чи класу. Це, як говориться на бляшанці, статичний аналіз. Не можна і не слід очікувати, що вони зможуть знайти динамічні виклики за допомогою відображення, eval () тощо. Думаю, що статичний аналіз коду слід вважати необхідною умовою для видалення фрагмента коду. І чим більший проект, тим меншою є ймовірність того, що людський мозок навіть здатний взагалі робити цей аналіз, а не робити це правильно ...
Йоханнес Хан

1
... статичний аналіз коду - втомлива, повторювана робота, яку найкраще виконувати за допомогою комп'ютера. Саме таку задачу, яку можна надійно виконати на комп’ютерах, але, як відомо, ненадійною, коли виконується мозком мавп. Останню слід використовувати лише для речей, які комп'ютер не може зробити, як знайти ті хитрі роздуми та eval-дзвінки.
Йоганнес Хан

1
Знову ж таки, пропустивши суть. Навіть якщо інструменти не є досконалими, оскільки їх написали мавпи мавп (і я навіть не впевнений, чи варто це дозволити! Обчислити статичні ієрархії викликів не так складно), вони все ще набагато перевершують виконання ручного завдання. Це не зовсім або нічого подібного. 99% надійний інструмент все ще кращий для мозку, який, можливо, починається з 99%, але швидко падає до значно нижчих показників після першої тисячі рядків коду.
Йоханнес Хан

-1

Дві можливості:

  1. У вас 99% + покриття тесту : Видаліть код і виконайте його.
  2. Ви не маєте надійного покриття тесту. Тоді відповідь - додати попередження про депресію . Тобто, ви додаєте до цього місця якийсь код, який робить щось розумним (запишіть попередження на якесь легко помітне місце, яке не суперечить, наприклад, щоденному використанню вашої програми). Потім дайте йому варитися кілька місяців / років. Якщо ви ніколи не виявляли його виникнення, замініть депресію на щось, що кидає виняток. Нехай це деякий час стоїть. Нарешті, видаліть все повністю.

2
це, мабуть, не пропонує нічого суттєвого щодо питань, викладених та пояснених у попередніх 17 відповідях. І охорона, і попередження про припинення роботи обговорювались там
марта

@gnat, ти маєш рацію. Коли я вперше просканував відповіді, я чомусь подумав, що побачив кілька таких, які вгорі не скоро і стисло дісталися до цих двох точок. У середині відповідей є деякі подібні.
AnoE
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.