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

Как сделать большой проект рефакторинга?

Я собираюсь начать планирование основного рефакторинга нашей кодовой базы, и я хотел бы получить некоторые мнения и ответы на некоторые вопросы (я видел довольно много дискуссий по подобным темам, например https://stackoverflow.com/info/108141/how-do-i-work-effectively-with-very-messy-legacy-code, Стратегия для масштабного рефакторинга, но у меня есть некоторые конкретные вопросы (внизу):

Мы разрабатываем сложное приложение. Есть 25 разработчиков, работающих с кодовой базой. Всего человеко лет, введенных в продукт на сегодняшний день, составляет примерно 150. Текущая кодовая база представляет собой единый проект, построенный с помощью ant. Целью высокого уровня проекта, который я приступаю, является модуляция базы кода в ее различных инфраструктурах и аппликативных компонентах. В настоящее время нет хорошего разделения между различными логическими компонентами, поэтому ясно, что любые усилия по модуляции должны включать некоторые определения API и серьезные распутывания, чтобы обеспечить разделение. Стандарты качества являются низкими - тестов практически нет, и, безусловно, нет тестов, выполняемых как часть процесса сборки.

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

Цели проекта:

  • позволяют повторно использовать компоненты в разных проектах
  • отдельное приложение из инфраструктуры и позволяет им развиваться независимо
  • улучшить тестируемость (путем создания API-интерфейсов)
  • упростить dev env разработчиков (меньше кода проверено и скомпилировано)

Мои мысли и вопросы:

  • Каковы ваши мысли относительно целей проекта? Что бы вы ни изменили?
  • У вас есть опыт работы с такими проектами? Какие рекомендации?
  • Я очень обеспокоен отсутствием тестов - отсюда и отсутствие контроля над тем, чтобы узнать, что процесс рефакторинга не нарушает ничего, поскольку я иду. Это уловка 22, потому что одна из целей этого проекта - сделать наш код более надежным...
  • На меня очень повлиял Майкл Фейрс Эффективная работа с устаревшим кодом. Согласно этому, подход "снизу вверх" - это способ решить мою проблему - не прыгайте головой сначала в кодовую базу и не пытайтесь ее исправить, а скорее начинайте с малого, добавляя единичные тесты вокруг нового кода в течение нескольких месяцев, и посмотрите, как код (и команда) становятся намного лучше, до тех пор, пока не появятся абстракции, API-интерфейсы будут всплывать и т.д., и, по существу, модуляция начнется сама по себе. Есть ли у кого-нибудь опыт в таком направлении? Как видно из многих других вопросов по этой теме, главной проблемой здесь является управленческое недоверие. "Как тестирует класс по классу (и тратит много времени на это), мы приведем нас к стабильной системе? Это хорошая теория, которая не работает в реальной жизни". Любые советы по продаже этого?
4b9b3361

Ответ 1

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

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

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

Итак, мы подумали, что мы попытаемся исправить ошибки в нашем новом коде. Затем мы обнаружили, что эти ошибки в исходном коде заставили работать другой код, так что на самом деле это были "концептуальные ошибки", а не "функциональные ошибки". Ну, может быть. В исходном программном обеспечении, которое никогда не отслеживалось, случались прерывистые спазмы.

Итак, мы изменили курс и решили сохранить ошибки на месте, как это должен сделать настоящий рефакторинг. Легко непреднамеренно ввести ошибки, гораздо труднее сделать это намеренно!

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

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

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

Ответ 2

Очевидно, что отсутствие тестов заставит людей нервничать при попытке реорганизовать код. Где кто-нибудь получит какую-либо веру в то, что ваш рефакторинг не нарушит заявку? Большинство ответов, которые вы получите, я думаю, будет "это будет очень тяжело и не очень успешно", и это во многом потому, что вы столкнулись с огромной ручной задачей и не верите в ответ.

Есть только два выхода.

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

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

Не так много людей делают последнее; где вы получаете инструменты, которые могут делать такие вещи?

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

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

Я знаю только 3 таких инструмента, которые имеют шанс работать с реальным кодом: TXL, Stratego/XT и наш инструмент, DMS Software Reengineering Toolkit. Первые два являются академическими продуктами (хотя TXL используется для коммерческой деятельности в прошлом); DMS является коммерческой.

DMS используется для широкого спектра крупномасштабных программных анусей и массивных задач трансформации. Одна из задач заключалась в автоматическом переводе между языками для B-2 Stealth Bomber. Другим, гораздо более близким к вашей проблеме рефакторинга, была автоматическая архивирование крупномасштабной компонентной системы С++ для компонентов, от устаревшей собственной RTOS с ее индивидуальными правилами о том, как организованы компоненты, в CORBA/RT, в которой API-интерфейсы компонентов которые должны быть изменены из специальных структур на интерфейсы фасет и сосудов в стиле CORBA, а также с использованием услуг CORBA/RT вместо устаревших служб RTOS. (Эти задачи были выполнены с 1-2 человеко-годами фактических усилий, довольно умными и умными парнями с DMS).

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

Есть что-то, что вы делаете, что значительно менее амбициозно: идентифицируйте повторно используемые части кода, узнав, что было повторно использовано в коде. Большинство программных систем содержат много клонированного кода (наш опыт составляет 10-20% [и меня удивляет отчет PHP меньших чисел в другом ответе, я подозреваю, что они используют слабый детектор клонов). Клонированный код - это намек на отсутствие абстракции в прикладном программном обеспечении. Если вы можете найти клоны и посмотреть, как они меняются, вы можете легко увидеть, как их абстрагировать на функции (или что-то еще), чтобы сделать их явными и многоразовыми.

Salion Inc. выполнял обнаружение и абзац клонов. В статье не рассматривается деятельность по абстракции; что на самом деле сделал Салион, был периодический обзор обнаруженных клонов и ручная реабилитация egregrious или тех, которые имели смысл в (часто библиотечные) методы. Конечным результатом была кодовая база, фактически уменьшенная по размеру, и программисты стали более эффективными, потому что у них были лучшие ( "более многоразовые" ) библиотеки.

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

Что касается "малого процента клона" для проекта PHP, обсуждаемого в другом ответе: я не знаю, что было использовано для детекторов клонов. Единственный детектор клона, сфокусированный на PHP, который, как я знаю, PHPCPD, IMHO - ужасный детектор клонов; он находит только точные клоны, если я понимаю заявленную реализацию. См. Пример PHP на нашем сайте для сравнительных целей.

Ответ 3

Это именно то, что мы делали для web2project за последние пару лет.. мы разветвлялись из существующей системы (dotproject), которая имела ужасные показатели, такие как высокая циклическая сложность (малая: 17, средняя: 27, высокая: 195M), много повторяющегося кода (8% общего кода) и нулевые тесты.

С момента расщепления мы сократили дубликат кода (на 2.1% в целом), уменьшили общий код (200kloc до 155kloc), добавили почти 500 модульных тестов и улучшили циклическую сложность (малая: 1, средняя: 11, высокая: 145м). Да, у нас все еще есть способы пойти.

Наша стратегия подробно описана в моих слайдах: http://caseysoftware.com/blog/phpbenelux-2011-recap - Project Triage and Recovery; и здесь: http://www.phparch.com/2010/11/codeworks-2010-slides/ - Стратегии тестирования единиц; и в различных сообщениях, подобных этой: http://caseysoftware.com/blog/technical-debt-doesn039t-disappear

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

Удачи.