Как разделить большой Java-проект на более мелкие компоненты

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

Приложение состоит из серверной WAR и нескольких расширенных клиентов, распределенных в JAR-файлах. Проблема в том, что все это в одной большой, запутанной базе кода, в одном дереве исходных текстов войны> 2k файлов. У каждого JAR есть выделенный класс с методом main, но клубок зависимостей быстро попадает в ловушку. Это не так уж и плохо, хорошие практики использовались последовательно, и есть компоненты с конкретными задачами. Просто нужно немного улучшить, чтобы помочь нашей команде масштабироваться по мере ее роста.

Каждый модуль будет в проекте maven, созданном родительским POM. Процесс переноса каждого JAR / WAR в отдельный проект уже начался, но очевидно, что это только коснется поверхности: несколько классов в каждом JAR приложения и гигантский «устаревший» проект со всем остальным. Кроме того, уже есть несколько модульных и интеграционных тестов.

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

Да ладно, это не мастерская творческого письма. Чем информативнее заголовки, тем лучше.

zoul 17.11.2008 10:07
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
9
1
8 382
6

Ответы 6

Два совета: Первое, что вам нужно, это тестовые наборы. Второй совет - работать маленькими шагами.

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

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

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

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

Чтобы он заработал, нам пришлось изолировать необходимый функционал, в отличие от декоративного ворса, чтобы все это работало. Например, там много разных классов строк, и один человек потратил, должно быть, много времени на преобразование строки 2k между COleDateTime в const char* и обратно; это была чушь, код для решения задачи, вспомогательной для основной цели (ввод и вывод данных из базы данных).

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

Я здесь немного скупердяй, потому что наш проект был от MFC C++ до .NET C#, но основные принципы применимы:

  1. найти главную цель
  2. определить все маленькие цели, которые делают возможной главную цель
  3. Изолируйте уже инкапсулированные части кода, если таковые имеются, для использования в качестве библиотечных вызовов.
  4. выяснить логику, чтобы собрать все воедино.

Надеюсь, это поможет...

Посмотрите Строение 101. Он отлично подходит для визуализации зависимостей и демонстрации зависимостей, которые нужно сломать на вашем пути к более чистой структуре.

Проголосуйте за S101. Программное обеспечение Headway добавил 2 дополнительных продукта: Restructure 101 и S101build. Я большой поклонник S101, но только сейчас изучаю их новые продукты.

Tony R 01.12.2012 18:14

Недавно мы выполнили аналогичную задачу, то есть проект, который состоял из> 1k исходных файлов с двумя основными классами, которые нужно было разделить. В итоге мы получили четыре отдельных проекта: один для базовых служебных классов, один для клиентской базы данных, один для сервера (проект представляет собой приложение rmi-server-client) и один для клиентского графического интерфейса. Наш проект пришлось разделить, потому что другие приложения использовали клиент только как командную строку, и если вы случайно использовали какой-либо из классов gui, у вас возникали исключения без заголовка, которые возникали только при запуске на сервере развертывания без управления.

Некоторые вещи, о которых следует помнить из нашего опыта:

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

Чтобы продолжить ответ Итая, я предлагаю прочитать «Эффективная работа с устаревшим кодом» Майкла Фезерса (pdf). Также он рекомендует подкреплять каждый свой шаг тестами. Еще есть Книжная версия.

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

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

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

Другие вопросы по теме