Что я должен иметь в виду, чтобы реорганизовать огромную базу кода?

Я собираюсь реорганизовать определенные части в огромной базе кода (классы 18000+ Java). Цель состоит в том, чтобы иметь возможность извлекать нижние уровни в качестве независимых библиотек для повторного использования в других проектах, которые в настоящее время используют дубликат этой базы кода. Особенно интересна часть, которая должна быть реорганизована в рамки, не зависящие от бизнес-логики. В конечном итоге я хотел бы, чтобы код имел чистое архитектурное наслаивание.

Я просмотрел код с помощью инструмента Structure 101 для java и нашел много (!) проблем архитектурного расслоения, когда нижние слои ссылаются на верхние слои.

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

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

Любые мысли об этом?

Ответ 1

Вы также должны взглянуть на работу с устаревшим кодом Майкла Перса:

http://www.amazon.com/Working-Effectively-Legacy-Robert-Martin/dp/0131177052/ref=sr_1_1?ie=UTF8& S = книги & QID = 1242430219 & ср = 8-1

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

Ответ 2

18 000 классов действительно направляются к "огромному" концу вещей. Это даст вам определенные проблемы, в том числе время сборки/компиляции и наличие дыма, выходящего из компьютера, когда вы запускаете идеал.

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

Другим возможным источником избыточности являются бесполезно глубокие иерархии классов или груды бессмысленных интерфейсов (пример - там, где я работаю там, каталог из примерно 50 классов, более > 1000 строк (не мой, не мой!). из них реализует интерфейс, который является не более чем его собственным скелетом метода. Других реализаций этих интерфейсов нет. Все 50 могут быть удалены без проблем). Есть также те разработчики, которые только что открыли OO и действительно заинтересованы в этом - вы знаете те, единственную конкретную реализацию, которая расширяет цепочку из 5 абстрактных классов и 3 интерфейса.

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

Ответ 3

На мой взгляд:

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

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

  • подготовить текущую производственную среду и определить текущие ошибки, поскольку параллельные прогоны понадобятся при начале рефакторинга (чтобы убедиться, что вы все еще поддерживаете одни и те же функции), и вы не хотите, чтобы ваши параллельные прогоны быть на 100% совместимым (потому что это означало бы, что вы успешно воспроизвели ошибки!)

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

Ответ 4

Первое: удачи, тебе это понадобится. Это потенциально ОГРОМНАЯ работа, с которой вы столкнулись. Это звучит очень знакомо мне; Я работал над подобными вещами в прошлом.

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

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

После того, как вы это сделали, начните смотреть на потенциально большие блоки функциональности для рефакторинга. Если невозможно получить чистые блоки функциональности для рефакторинга, я бы начал смотреть на маленькие куски; если вы можете найти небольшой (иногда ОЧЕНЬ маленький) фрагмент кода, чтобы извлечь его, unit test и рефакторинг, вы продвигаетесь вперед. Иногда это может показаться очень очень медленным, и это будет, если у вас действительно большой проект, но вы будете делать вмятину.

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

Ответ 5

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

Ответ 6

Попробуйте сделать дерево зависимостей максимально плоским.

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

Ответ 7

Несколько мыслей:

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

Ответ 8

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

Ответ 9

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

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