Мы пытаемся разделить большую кодовую базу на логические модули. Я хотел бы получить несколько рекомендаций по инструментам, а также узнать, какой у вас был опыт работы с подобными вещами.
Приложение состоит из серверной WAR и нескольких расширенных клиентов, распределенных в JAR-файлах. Проблема в том, что все это в одной большой, запутанной базе кода, в одном дереве исходных текстов войны> 2k файлов. У каждого JAR есть выделенный класс с методом main, но клубок зависимостей быстро попадает в ловушку. Это не так уж и плохо, хорошие практики использовались последовательно, и есть компоненты с конкретными задачами. Просто нужно немного улучшить, чтобы помочь нашей команде масштабироваться по мере ее роста.
Каждый модуль будет в проекте maven, созданном родительским POM. Процесс переноса каждого JAR / WAR в отдельный проект уже начался, но очевидно, что это только коснется поверхности: несколько классов в каждом JAR приложения и гигантский «устаревший» проект со всем остальным. Кроме того, уже есть несколько модульных и интеграционных тестов.
В любом случае, меня интересуют инструменты, методы и общие советы по разделению слишком большой и запутанной базы кода на что-то более управляемое. Предпочтительно бесплатный / открытый исходный код.




Два совета: Первое, что вам нужно, это тестовые наборы. Второй совет - работать маленькими шагами.
Если у вас уже есть надежный набор тестов, то вы в хорошем положении. В противном случае я бы сделал несколько хороших тестов высокого уровня (также известных как системные тесты).
Основное преимущество высокоуровневых тестов состоит в том, что относительно небольшое количество тестов может обеспечить большой охват. Они не помогут вам в выявлении ошибки, но вам это действительно не понадобится: если вы работаете небольшими шагами и обязательно запускаете тесты после каждого изменения, вы сможете быстро обнаружить (случайно введенное) ошибки: корень ошибки заключается в том, что небольшая часть кода изменилась с момента последнего запуска тестов.
Я бы начал с различных задач, которые вам нужно выполнить.
Недавно я столкнулся с аналогичной задачей, учитывая, что кодовая база 15-летней давности была создана рядом разработчиков, которые не общались друг с другом (один работал над проектом, ушел, затем наняли другого и т. , без перекрестных помех). В результате получается полная мешанина самых разных стилей и качества.
Чтобы он заработал, нам пришлось изолировать необходимый функционал, в отличие от декоративного ворса, чтобы все это работало. Например, там много разных классов строк, и один человек потратил, должно быть, много времени на преобразование строки 2k между COleDateTime в const char* и обратно; это была чушь, код для решения задачи, вспомогательной для основной цели (ввод и вывод данных из базы данных).
В конечном итоге нам пришлось определить большую цель, которую достиг этот код, а затем написать для этого базовую логику. Когда нам нужно было выполнить задачу, которая, как мы знаем, была выполнена раньше, мы находили ее и заключали в вызовы библиотек, чтобы она могла существовать сама по себе. Например, один фрагмент кода активирует драйвер USB-устройства для создания образа; этот код не затрагивается текущим проектом, но вызывается при необходимости через вызовы библиотеки. Другой фрагмент кода работает с защитным ключом, а еще один запрашивает данные на удаленных серверах. Это весь необходимый код, который можно инкапсулировать. Однако код рисования создавался более 15 лет и представлял собой такое сооружение до безумия, что переписывание в OpenGL в течение месяца было лучшим использованием времени, чем попытки выяснить, что сделал кто-то другой, а затем как добавить к нему.
Я здесь немного скупердяй, потому что наш проект был от MFC C++ до .NET C#, но основные принципы применимы:
Надеюсь, это поможет...
Посмотрите Строение 101. Он отлично подходит для визуализации зависимостей и демонстрации зависимостей, которые нужно сломать на вашем пути к более чистой структуре.
Проголосуйте за S101. Программное обеспечение Headway добавил 2 дополнительных продукта: Restructure 101 и S101build. Я большой поклонник S101, но только сейчас изучаю их новые продукты.
Недавно мы выполнили аналогичную задачу, то есть проект, который состоял из> 1k исходных файлов с двумя основными классами, которые нужно было разделить. В итоге мы получили четыре отдельных проекта: один для базовых служебных классов, один для клиентской базы данных, один для сервера (проект представляет собой приложение rmi-server-client) и один для клиентского графического интерфейса. Наш проект пришлось разделить, потому что другие приложения использовали клиент только как командную строку, и если вы случайно использовали какой-либо из классов gui, у вас возникали исключения без заголовка, которые возникали только при запуске на сервере развертывания без управления.
Некоторые вещи, о которых следует помнить из нашего опыта:
Чтобы продолжить ответ Итая, я предлагаю прочитать «Эффективная работа с устаревшим кодом» Майкла Фезерса (pdf). Также он рекомендует подкреплять каждый свой шаг тестами. Еще есть Книжная версия.
Maven позволяет создавать небольшие проекты как дочерние по отношению к более крупному. Если вы хотите извлечь часть своего проекта в отдельную библиотеку для других проектов, maven также позволит вам это сделать.
Сказав это, вам определенно нужно задокументировать свои задачи, то, что будет выполнять каждый меньший проект, а затем (как было сказано здесь несколько раз) тестировать, тестировать, тестировать. Вам нужны тесты, которые работают со всем проектом, а затем есть тесты, которые работают с отдельными частями проекта, которые в конечном итоге станут дочерними проектами.
Когда вы начинаете извлекать функциональность, вам нужны дополнительные тесты, чтобы убедиться, что ваша функциональность согласована, и что вы можете имитировать вводимые данные в различные дочерние проекты.
Да ладно, это не мастерская творческого письма. Чем информативнее заголовки, тем лучше.