Рефакторинг с низким уровнем воздействия и очистка кода от небрежного кода в ожидании требований


17

Я унаследовал существующую кодовую базу для продукта, который предосудительно небрежен. Фундаментальный дизайн крайне неадекватен, что, к сожалению, я мало что могу сделать без полного рефакторинга (ВЫСОКАЯ связь, НИЗКОЕ сцепление, безудержное дублирование кода, отсутствие технической проектной документации, интеграционные тесты вместо модульных тестов). Продукт имеет историю, высокую подверженность критически настроенным клиентам «дойной коровы» с минимальной терпимостью к риску, технический долг, который заставит греков покраснеть, ОЧЕНЬ большую кодовую базу и сложность, а также утомленный пораженческий подход к ошибкам со стороны команды до мне.

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

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

Мой вопрос состоит в том, чтобы собрать мнение о рефакторинге с низким уровнем воздействия на подобный проект, когда у вас есть немного свободного времени на этапе сбора функциональных требований. Есть тысячи предупреждений компилятора, почти все они неиспользуемые импорты, непрочитанные локальные переменные, отсутствие проверки типов и небезопасных приведений. Форматирование кода настолько нечитаемо и небрежно, что похоже на то, что кодер страдал болезнью Паркинсона и не мог контролировать количество нажатий клавиши пробела в любой строке. Другие базы данных и файловые ресурсы обычно открываются и никогда не закрываются безопасно. Бессмысленные аргументы метода, дублирующие методы, которые делают то же самое, и т.д ..

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

Можете ли вы вспомнить какие-либо положительные или отрицательные последствия того, что я сделаю это, что вы хотели бы добавить?


1
Спасите то, что стоит спасать, переписать остальное ...
ср.

«Я очень редко сталкиваюсь с неудачей проекта технической некомпетентности, а не с ошибкой управления проектом [...]» Насколько это верно, +1.
Грегори

Ответы:


22

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

Я бы начал работать над предупреждениями компилятора и неиспользуемыми переменными и импортом. Сначала получите чистую сборку. Затем начните писать модульные тесты для документирования текущего поведения, затем начните реальный рефакторинг.

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

Как только требования начинают входить, я бы использовал то, что я называю подходом центра внимания. Сделайте обычную гибкую вещь (расставьте приоритеты, затем отрежьте небольшую пластинку для итерации и проработайте ее) и оставьте немного времени для улучшения кода. Затем рефакторинг, где вы все равно работаете. Со временем это охватит широкие области кодовой базы, и вам никогда не придется рисковать в тех областях, где вам будет сложно объяснить руководству, почему вы работаете над этой частью кода.


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

10

Написание модульных тестов может быть более ценным использованием вашего времени: оно даст вам некоторое представление о текущей работе кодовой базы, и если вы решите начать с того, что у вас есть, а не переписывать все с нуля, у вас будет прочная основа вносить изменения, не принимая слишком большого риска. Скорее всего, при написании модульных тестов вы также внесете изменения в кодовую базу просто для придания ей формы, пригодной для тестирования; это хорошо, потому что модульное тестирование обычно также означает модульное, инкапсулированное и в основном независимое от внешнего состояния. И, прежде всего, хорошо написанные юнит-тесты являются бесценной технической документацией. С помощью модульных тестов вы сможете судить о том, что может и чего не может делать текущая кодовая база, вместо того, чтобы на всякий случай делать догадки или переписывать вещи.


2
Тогда начни с легких и продолжай свой путь?
tdammers

2
По моему опыту, это всегда проблема - подобный код никогда не пишется, чтобы разрешить тестирование, и вам в конечном итоге придется делать огромные рефакторинги, если не просто переписывать код, чтобы вообще разрешить модульные тесты.
Уэйн Молина

2
Если код не предназначен для тестов, это еще одна причина, чтобы обойти его, но безопасно. Прочитайте книгу Майкла Фезерса «Эффективная работа с устаревшим кодом»; у него есть рецепты для создания тестируемого кода.
Джо Уайт

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

1
Это требует некоторого опыта и здравого смысла. Не все можно (или нужно) сделать модульно-тестируемым.
tdammers

1

Смешивание ответов - моя мысль будет смешивать тестирование и очистку - может быть 50/50? Если вы работаете в области, использующей подход TDD - настройте тесты, вам нужно знать, что тестирование модуля и интеграции соответствует требованиям, а затем приступить к исправлению. Двигайтесь, как позволяет время.

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

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

Учитывая, что вы делаете это, ожидая новых требований, я думаю, что все, что вы можете диагностировать, хаос значительно прибавит вам долговременного здравомыслия.

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