Разделение Java-проектов

12

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

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

Мое мышление заключается в следующем:

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

Я немного обеспокоен тем, какое влияние это может оказать на время сборки.

  • Замедляет ли компиляция структуру большого проекта (т. Е. Меньших подпроектов)?

Кроме того, у меня есть небольшое беспокойство о том, как это может повлиять на время редактирования в IDE (в основном мы используем Intellij). Кажется, что Intellij строит каждый проект по очереди через дерево зависимостей - то есть, если C зависит от B, зависит от A, и я меняю A, он не будет пытаться построить B, пока A не скомпилируется, и так далее. Возможно, это выгодно, но я обнаружил, что если - например, я меняю интерфейс в A, который широко используется в B и C, потребуется некоторое время, чтобы исправить все ошибки этого изменения ...

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

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

  • подпроект A - содержит интерфейсы
  • подпроект B - зависит от A для интерфейсов и старого внешнего фляги
  • подпроект C - зависит от B (и, следовательно, A и старого внешнего jar), и содержит класс Factory, который использует реализации интерфейсов B

Если мне нужно изменить внешний сосуд B, я могу:

  • создать подпроект B_ii - снова зависит от A, и теперь новый внешний jar
  • как только он станет полностью функциональным, я могу добавить зависимость C к B_ii и изменить класс Factory, чтобы использовать новые реализации интерфейсов.
  • когда все это работает, я могу удалить зависимость C от исходного B и, если необходимо, удалить подпроект B.

  • Это разумный способ сделать это?

Итак, в общем, мои вопросы:

  • У кого-нибудь есть опыт разрушения крупных проектов? Есть ли какие-нибудь советы / хитрости, которыми вы бы хотели поделиться?
  • Какое влияние это оказало на ваше развитие и время сборки?
  • Какой совет вы могли бы предложить при структурировании такого разделения такого проекта?
amaidment
источник
Обратите внимание, что вы можете создать родительский проект с отдельно выделенными буквами A, B и C. Это позволяет, например, IntelliJ иметь все три в памяти одновременно и выполнять рефакторинг через границы модуля.
Торбьерн Равн Андерсен

Ответы:

10

Я собираюсь сделать первый краткий обзор этого (отличный Q Кстати!):

Замедляет ли компиляция структуру большого проекта (т. Е. Меньших подпроектов)?

Недостаточно того, что это имеет значение, накладные расходы на самом деле в вызовах Maven.

Кроме того, у меня есть небольшое беспокойство о том, как это может повлиять на время редактирования в IDE (в основном мы используем Intellij). Кажется, что Intellij строит каждый проект по очереди через дерево зависимостей - то есть, если C зависит от B, зависит от A, и я меняю A, он не будет пытаться построить B, пока A не скомпилируется, и так далее. Возможно, это выгодно, но я обнаружил, что если - например, я меняю интерфейс в A, который широко используется в B и C, потребуется некоторое время, чтобы исправить все ошибки этого изменения ...

Различные IDE имеют свои сильные стороны в отношении привязок Maven и управления зависимостями. Текущее состояние игры, по-видимому , таково, что в основном он работает только с последними версиями Eclipse, Netbeans и IntelliJ, но вам придется учить своих разработчиков в чрезвычайной ситуации: «Обновлять исходные файлы с диска и перестраивать все связанные проекты maven».

Я считаю, что мне приходится делать это все реже и реже в эти дни. Кстати, наличие SSD-накопителя имеет огромное значение.

отрывать заводские абзацы

Управление зависимостями невероятно важно, независимо от того, какую технологию (Maven / Ivy / что угодно) используют, чтобы помочь вам реализовать ее.

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

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

Итак, в общем, мои вопросы:

У кого-нибудь есть опыт разрушения крупных проектов? Есть ли какие-нибудь> советы / хитрости, которыми вы бы хотели поделиться?

  • Интерфейсы и внедрение зависимостей - ваш друг.
  • Книга Майкла Фезера о том, как эффективно работать с унаследованным кодом, должна быть прочитана.
  • Интеграционные тесты - ваш друг
  • Разделение подпроектов на foo-api (только интерфейсы!) И foo-core, а наличие модулей зависит только от foo-api, очень помогает и обеспечивает разделение
  • Модули Jboss и / или OSGi могут помочь обеспечить чистое разделение

Какое влияние это оказало на ваше развитие и время сборки?

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

Какой совет вы могли бы предложить при структурировании такого разделения такого проекта?

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

Напишите интеграционные тесты до разделения - вы должны более или менее получить тот же результат (ы) после разделения.

Нарисуйте схемы модульности у вас сейчас и где вы хотите добраться. Дизайн промежуточных шагов.

Не сдавайтесь - теперь некоторые способы бритья от Яка создают основу для возможности «быстрого построения и рефакторинга без страха». Бесстыдный плагин -> от Бена и меня - Хорошо обоснованный Java-разработчик .

Удачи!

Мартейн Вербург
источник
0

Мой взгляд на это только отдельно, когда это необходимо. Однако это поднимает следующий вопрос: как определить, необходимо ли это?

  • Когда артефакт отличается (т.е. не собирайте EAR, WAR, JAR, jar интеграции-тестирования в одном проекте).
  • Когда во время разделения вы замечаете, что какой-то код должен существовать в нескольких артефактах, он превращает их в новый.
  • Когда какой-то другой проект за пределами вашей команды хочет использовать то, что есть у вас в вашем проекте.

Одна из причин заключается в том, что разработчикам приходится иметь дело с несколькими проектами и пытаться выяснить, кроме того, к какому пакету Java относится тот или иной проект. Я был в проектах, где это стало действительно анемичным, и у меня был проект, в котором было всего четыре класса, реализующих одну функциональность только потому, что это архитектурное направление. Это также было еще до того, как Maven стал популярным, поэтому пути к классам и то, что не нужно настраивать как в IDE, так и в сценариях Ant.

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

Рефакторинг также проще в рамках проекта, чем в разных проектах.

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

Архимед Траяно
источник