Подтвердить что ты не робот

Устаревший код Кошмар

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

У меня есть библиотека гибких книг разработки в пределах досягаемости в любой момент:

  • Эффективная работа с устаревшим кодом
  • Рефакторинг
  • Код завершен.
  • Шаблоны и практики Agile Principles на С#
  • и др.

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

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

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

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

4b9b3361

Ответ 1

Похоже, ты правильно его решаешь.

  • Тест
  • Refactor
  • Тест снова

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

Одна книга, которую я могу порекомендовать (если вы еще ее не подали под "и т.д." ), Рефакторинг для шаблонов. Он ориентирован на людей, которые находятся в вашей конкретной ситуации.

Ответ 2

Я работаю в аналогичной ситуации.

Если это не небольшая утилита, а большой проект предприятия, это:

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

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

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

EDIT: всякий раз, когда я пытаюсь решить вопрос об истинной архитектуре и делать все правильно, я обычно получаю LOL на моем лице непосредственно от ответственных менеджеров, которые говорят что-то вроде "Мне наплевать на хорошую архитектуру" (попытка перевода с немецкого языка). Я лично привел один очень плохой компонент в категорию не-hackability, хотя, разумеется, дав предварительные предупреждения за несколько месяцев вперед. Затем им пришлось отменить некоторые обещанные функции для клиентов, потому что они больше не выполнялись. Никто больше не трогает его...

Ответ 3

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

В первую очередь - получите исключение в приложении, если оно еще не существует. Мы использовали FogBugz, и потребовалось около месяца, чтобы получить отчет, интегрированный в наше приложение; он был не совсем совершенным, но он автоматически сообщал об ошибках. Обычно довольно безопасно реализовывать блоки try-catch во всех ваших событиях, и это будет охватывать большинство ваших ошибок.

Оттуда исправить ошибки, которые входят в первую очередь. Затем сражайтесь с небольшими битвами, особенно с багами. Если вы исправите ошибку, которая неожиданно влияет на что-то еще, рефакторинг, который блокируется, чтобы он был отделен от остальной части кода.

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

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

Ответ 4

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

В большинстве случаев это неизбежно выполнимо, просто сложно. Прочтите эту книгу рефакторинга.

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

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

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

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

Ответ 5

В основном, это звучит довольно плохо. Но я не понимаю эту часть:

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

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

Ответ 7

Никакая книга не сможет охватить все возможные сценарии. Это также зависит от того, что вы ожидаете от проекта, и есть ли какая-либо внешняя спецификация.

  • Если вам понадобятся только небольшие изменения, просто сделайте это и не начните рефакторинг.
  • Если есть спецификация (или вы можете заставить ее написать ее), рассмотрите полную переписку, если она может быть оправдана в обозримом объеме изменений в проекте.
  • Если "реализация - это спецификация" и, запланировано много изменений, то вы довольно сильно зажаты. Напишите LOTS модульные тесты и начните рефакторинг небольшими шагами.

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

Ответ 8

Если ваши рефакторинги нарушают код, в частности код, который, как представляется, не связан, вы пытаетесь сделать слишком много за раз.

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

После этого подумайте о разрыве зависимостей, замене синглтонов, консолидации.

Ответ 9

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

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

И запустите пакет unit test после каждого рефакторинга или набора рефакторинга. Я бы сказал, запустите их все, пока не получите уверенность в том, какие тесты нужно будет повторять каждый раз.

Ответ 10

Удачи, это трудная часть того, чтобы быть разработчиком.

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

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

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

Ответ 11

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

То есть все это либо "неприятный старый материал", либо "хороший новый материал". Одна сторона линии или другая.

Линия зазубрена, потому что вы перемещаете разные части системы с разной скоростью.

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

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

Ответ 12

Вы можете найти следующее сообщение полезным: http://refactoringin.net/?p=36

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

Ответ 13

Вы можете извлечь, а затем реорганизовать часть его, разбить зависимости и выделить слои в разные модули, библиотеки, сборки, каталоги. Затем вы повторно вводите очищенные части в приложение с помощью strangler application. Намочите, промойте, повторите.