Що може бути причиною появи нових помилок деінде, коли відомий помилка вирішена?


14

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

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

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

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

Що може допомогти?

  • Одиничні тести (таких немає)?
  • Власна архітектура (я майже впевнений, що база даних коду взагалі не має архітектури і була написана без попереднього роздуму), що вимагає цілого рефакторингу?
  • Парне програмування?
  • Щось ще?

14
Ах, модель дизайну гарних "каскадних хвиль відмови". :-)
Брайан Кноблауш

1
Я порівнюю його з бульбашкою в листі контакту. Натисніть, вона спливе в іншому місці. Чим краще моє кодування стає, тим менше я його бачу
johnc

2
Зі сторони, я мав саме це на вбудованій системі. Я додав виклик функції, щоб вирішити проблему. Цей виклик функції був занадто великим для стека (у мікроконтролера не було виявлення stackoverflow), і тому він записав у пам’ять деякі випадкові речі, які, звичайно, зламали щось десь зовсім інше. Отже, ця річ МОЖЕ відбутися на невеликій кодовій базі з лише одним розробником та хорошою архітектурою.
підйом темноти

... і це був кошмар для налагодження.
піднімається темність

Відповіді:


38

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


15
це поєднується з поганим або відсутнім регресійним тестуванням
Ріаталь

3
Правда, @Ryathal, хоча регресійне тестування не запобіжить таким видам помилок, просто повідомте про них швидше.
Карл Білефельдт

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

14

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

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

Замість виправлення останніх трьох помилок я зробив кілька сильних рефакторингу: розділив компонент на основний клас плюс класи MVC (три додаткові класи). Таким чином мені довелося розділити код на менші, простіші частини та визначити більш чіткі інтерфейси. Після рефакторингу всі помилки були вирішені, і про нові помилки не повідомлялося.


7

Один клоп легко замаскувати інший. Припустимо, помилка "A" призводить до того, що неправильна функція викликається для обробки даних. Коли виправлено помилку "А", раптом викликається правильна функція, яка ніколи не була перевірена.


5

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

Наприклад, припустимо, що функції A і B використовують конвенцію на основі нуля для деякої кількості, тому вони працюють разом правильно, але C використовує один, ви можете "виправити" A для роботи з C, а потім виявити проблему з B.

Більш глибока проблема - відсутність незалежної перевірки правильності окремих деталей. Для вирішення цього питання створені одиничні тести. Вони також виступають як специфікація належних даних. Наприклад, хороший набір тестів дозволить зрозуміти, що функції A і B очікують на вході на основі 0 і на C 1.

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

Гарна архітектура допомагає вирішити проблему розуміння коду, полегшивши це. Парне програмування корисно в першу чергу для уникнення помилок або швидшого їх пошуку.

Сподіваюсь, це допомагає.


5

Жорстке зчеплення, відсутність тестування, це, мабуть, найпоширеніші винуватці. По суті, загальне питання - це просто нерозумні стандарти та процедура. Інша - просто неправильне керування кодом, щоб на деякий час пощастило з правильною поведінкою. Розгляньте memcpyпомилку від Linus Torvalds, коли зміна її реалізації виявила (не викликала) помилок у клієнтів, які використовуються memcpyв місцях, де вони повинні були використовуватись memmoveіз джерелом та пунктом призначення, що перекриваються.


4

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

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


0

Поліпшити ширину автоматизованої схеми тестування. ЗАВЖДИ запускайте повний набір тестів до внесення змін коду. Таким чином ви виявите згубний ефект своїх змін.


0

Я просто стикався з цим, коли тест був неправильним. Тест перевірив заданий стан дозволу, який був! Правильним. Я оновив код і запустив тест на дозвіл. Це спрацювало. Потім я пройшов усі тести. Усі інші тести, які використовували перевірений ресурс, не вдалися. Я виправив тест і перевірку дозволу, але спочатку була трохи паніки.

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


0

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

Отже, ви майже відповіли собі:

  • сипуча муфта
  • відсутність тестів

Просто навчіться адаптувати принцип TDD (принаймні для нових функцій) і спробуйте протестувати кожен можливий стан, який може статися.

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


0

Скажімо, розробник A написав код з помилкою. Код не точно те, що він повинен робити, а щось дещо інше. Розробник B написав код, який покладався на код А, роблячи саме те, що саме робиться, і код B не працює. B досліджує, знаходить неправильну поведінку в коді А та виправляє її.

Тим часом код розробника C працював лише правильно, оскільки він покладався на неправильну поведінку коду А. Код А тепер правильний. І код C перестає працювати. Що означає, коли ви виправляєте код, вам потрібно дуже ретельно перевірити, хто використовує цей код, і як їх поведінка зміниться з фіксованим кодом.

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

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