Какие подходы я могу использовать, чтобы уменьшить вероятность появления новых ошибок в сложном устаревшем приложении?


10

Там, где я работаю, мне часто приходится разрабатывать (и исправлять ошибки) в старой системе (.NET 1), чей код - это спагетти без особого внимания к именам переменных, структуре программы и комментариям.

Из-за этого мне понадобилось много времени, чтобы понять, какие биты нужно изменить, и я часто «ломаю» существующее программное обеспечение, потому что я сделал модификацию. Я действительно очень хочу потратить пару месяцев (с коллегами) на это, чтобы провести рефакторинг, но существующие разработчики не видят необходимости - и не думают, что для этого есть время (система огромна).

Я боюсь работать над его кодом, так как требуются дни, чтобы что-то исправить, только чтобы узнать, что я сломал что-то другое. Это, очевидно, заставляет меня выглядеть некомпетентным - так как я могу справиться с этим?


Ответы:


16

Начните писать тесты для частей, над которыми вы работаете. Вы можете попробовать рабочий процесс, который выглядит примерно так:

  1. Напишите тесты для части, которую вы собираетесь изменить. Это также поможет вам понять, как ведет себя существующий код.
    • Рефакторинг кода для поддержки тестирования, если это необходимо, но вы можете написать не модульные тесты, если времени мало.
  2. Запустите свои тесты, чтобы убедиться, что все работает так, как вы ожидаете.
  3. Внесите свои изменения. Рефакторинг при необходимости в духе постоянного улучшения кода, но не увлекайтесь.
  4. Перезапустите тесты, чтобы убедиться, что вы сохранили ту же функциональность.

Если вы не выбросите свои тесты, вы со временем создадите набор тестов, который должен охватывать наиболее важные (и / или изменчивые) части приложения, и внесение в него изменений станет проще и безопаснее.

Вы также можете найти полезной работу по эффективному использованию устаревшего кода от Michael Feathers.


1
+1 за "... но вы можете написать не юнит-тесты, если времени мало."!
Марси

1
Хороший ответ. @ m.edmondson При рефакторинге вы также можете обнаружить, что определенные части кода «огромны», потому что дублирование везде и что при рефакторинге становится все меньше и проще.
Альб

6

Я хотел бы следовать Дядя Боб Мартин «s Boy Scout Rule :

«Когда у тебя большой грязный наследственный комок, то, что тебе нужно сделать, это… То, что тебе нужно сделать, это прекратить создавать беспорядки и начать убирать их.

Это не означает, что вы вызываете своих менеджеров в конференц-зал и говорите им, что вы не собираетесь предоставлять функции в течение следующих трех месяцев, пока вы реорганизуете код. Не делайте этого! Скорее это означает, что вы собираетесь принять «Бойскаутское правило» и проверить каждый модуль немного чище, чем когда вы его проверили.

От итерации к итерации и от выпуска к выпуску вы собираетесь очистить эту систему, продолжая добавлять в нее новые функции и возможности. Другого пути нет."


2

Вы могли бы объяснить менеджеру, что исправления, которые должны занимать часы, в конечном итоге занимают дни из-за путаницы в кодовой базе. Другие разработчики не будут нуждаться в рефакторинге, если они являются первоначальными разработчиками - они будут знать систему наизнанку, но руководство должно знать, что существует риск, если эти разработчики когда-нибудь уйдут и возьмут свои знания с собой.

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


1
Я согласен - и в прошлом я включал эти «маленькие» рефакторы, как мне было просто необходимо, чтобы понять код - но все же обычно кто-то встречает «вы полностью его сломали» и возвращаю его обратно, как это было ...
billy.bob

@ m.edmondson: Ах. Хорошо, если бы у них был полный набор модульных тестов, то просто запустили бы, чтобы проверить, был ли рефакторинг хорош или нет. Судя по тому, как это звучит, у них этого нет, поэтому вам придется самостоятельно писать модульные тесты. Я знаю, что это нелегко, и нет никакого реального окончательного ответа на эту проблему (по крайней мере, не тот, который я нашел, хотя я буду наблюдать, чтобы увидеть, что другие люди предлагают, поскольку я был там также).
FrustratedWithFormsDesigner

2

Вы действительно должны потратить месяцы на рефакторинг кода? Или вы можете изменить код при внесении изменений. Так, например, если вы решите, что метод Foo необходимо изменить, вы можете воспользоваться возможностью реорганизовать метод Foo. И если вам нужно пройти через дюжину других методов, чтобы выяснить, что проблема в Foo, вы можете оставить комментарии в этих методах, чтобы вы или кто-то еще в будущем знал, что должен делать код. Конечно, это означает, что все еще есть куча спагетти-кода, но вы можете, по крайней мере, переместить кодовую базу в правильном направлении и упростить себе задачу в дальнейшем. Получение нескольких месяцев времени на рефакторинг кода будет большой продажей, потому что это означает, что вы не предоставляете ничего, что конечный пользователь хочет в течение всего этого времени.

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


0

Еще один совет. Когда клопы действительно проявляются и после наложения повязки не останавливайтесь на достигнутом!

Спросите пять почему, возьмите красную таблетку и посмотрите, как глубоко заходит кроличья нора, и устраните основную причину (и путь вниз).

Вы многое узнаете о системе. Это помогает расставить приоритеты, что исправить и рефакторинг. И после нескольких таких поездок у вас есть несколько прочных «опорных балок», чтобы укрепить монолитную кучу спагетти.


0

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

// old code
...

if (!File.ReadAllText("c:\patch_control.txt").Contains("StrangeUIBugFix=0"))
{
    // new code goes here
    ...
}

// old + new code
int someValue = 
    IsEnabled("StrangeUIBugFix") ? a + b :  // new code
    a * b; // old code

0

Одна вещь: Never change any existing code if you are not sure what effect change would have on complete application.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.