Я использую следующие линии на песке:
- Код, который в конечном итоге находится в разных развертываемых компонентах, находится в разных папках в одном и том же репозитории в рамках зонтичного проекта — то, что SBT называет многопроектная сборка (я использую maven, а не SBT, но концепции очень похожи). Он будет построен/развернут в разных банках.
Я стараюсь учитывать окончательные возможности развертывания при создании дивизий, которые имеют смысл. Например, если в моей системе foosys есть развертываемые компоненты foosys-frontend
и foosys-backend
, где foosys-frontend
создает HTML-шаблоны, а foosys-backend
общается с базой данных, а оба обмениваются данными через REST API, то я буду использовать их как отдельные проекты и проект foosys-core
для общего кода. . foosys-core
не может зависеть ни от библиотеки шаблонов html (потому что foosys-backend
этого не хочет), ни от библиотеки ORM (потому что foosys-frontend
этого не хочет). Но я не беспокоюсь об отделении кода, работающего с библиотекой REST, от «основных объектов предметной области», потому что и foosys-frontend
, и foosys-backend
используют код REST.
Теперь предположим, что я добавляю новый развертываемый объект foosys-reports
, который обращается к базе данных для создания некоторых отчетов. Затем я, вероятно, создам проект foosys-database
, зависящий от foosys-core
, для хранения общего кода, используемого как foosys-backend
, так и foosys-reports
. И поскольку foosys-reports
не использует библиотеку REST, мне, вероятно, следует также отделить foosys-rest
от foosys-core
. Таким образом, я получаю библиотеку foosys-core
, еще два проекта библиотек, зависящих от нее (foosys-database
и foosys-rest
), и три развертываемых проекта (foosys-reports
в зависимости от foosys-database
, foosys-frontend
в зависимости от foosys-rest
и foosys-backend
в зависимости от обоих).
Вы заметите, что это означает наличие одного проекта кода для каждой комбинации развертываемых компонентов, в которых может использоваться этот код. Код, который входит во все три развертываемых компонента, находится в foosys-core
. Код, который входит только в один развертываемый компонент, входит в проект этого развертываемого компонента. Код, который находится в двух из трех развертываемых компонентов, находится в foosys-rest
или foosys-database
. Если бы мы хотели иметь некоторый код, который был частью развертываемых модулей foosys-frontend
и foosys-reports
, но не развертываемых компонентов foosys-backend
, нам пришлось бы создать другой проект для этого кода. Теоретически это означает экспоненциальный рост количества проектов по мере добавления дополнительных развертываемых компонентов. На практике я обнаружил, что это не слишком проблематично — большинство теоретически возможных комбинаций на самом деле не имеют смысла, поэтому пока мы создаем новые проекты только тогда, когда у нас действительно есть код для их добавления, все в порядке. И если мы закончим с парой классов в foosys-core
, которые на самом деле не используются в каждом отдельном развертываемом, это не конец света.
С этой точки зрения тесты лучше всего понимать как еще один вид развертываемых средств. Поэтому у меня был бы отдельный проект foosys-test
, содержащий общий код, который использовался для тестов для всех трех развертываемых проектов (в зависимости от foosys-core
), и, возможно, проект foosys-database-test
(в зависимости от foosys-test
и foosys-database
) для вспомогательного кода теста (например, код настройки теста интеграции базы данных). ), что было общим между foosys-backend
и foosys-reports
. В конечном итоге мы можем получить полную параллельную иерархию из -test
проектов.
- Перемещайте проекты в отдельные репозитории git (и в то же время отдельные сборки в целом) только в том случае, если у них разные жизненные циклы выпуска.
Код в разных репозиториях обязательно версионируется независимо, поэтому в некотором смысле это бессодержательное определение. Но я думаю, что вам следует переходить на отдельные репозитории git только тогда, когда это необходимо (аналогия с этот пост): вы должны использовать Hadoop только тогда, когда ваши данные слишком велики, чтобы использовать что-то более удобное). Как только ваш код находится в нескольких репозиториях git, вам нужно вручную обновить зависимости между ними (на машине разработки вы можете использовать зависимости -SNAPSHOT и поддержку IDE, чтобы работать так, как если бы версии все еще были синхронизированы, но вы должны вручную обновить это каждый раз, когда вы выполняете повторную синхронизацию с мастером, что добавляет трения в разработку). Поскольку вы делаете релизы и обновляете зависимость асинхронно, вам нужно принять и внедрить что-то вроде семантического управления версиями, чтобы люди знали, когда безопасно обновлять зависимость от foocorp-utils
, а когда нет. Вы должны публиковать журналы изменений, иметь сборку CI с ранним предупреждением и более тщательный процесс проверки кода. Все это потому, что цикл обратной связи намного длиннее; если вы сломаете что-то в нижестоящем проекте, вы не узнаете об этом, пока они не обновят свою зависимость от foocorp-utils
, спустя месяцы или даже годы (да, годы - я был свидетелем этого, и в стартапе из 80 человек, а не мегакорпорации ). Поэтому вам нужен процесс, чтобы предотвратить это, и все становится соответственно менее гибким.
К уважительным причинам для этого относятся:
- Полная сборка вашего проекта занимает слишком много времени, замедляя интеграцию кода, над которым вы работаете, — хотя сначала попытайтесь ускорить ее.
- Развертывание всех ваших развертываемых компонентов занимает слишком много времени — хотя, опять же, попробуйте автоматизировать это и ускорить. Есть реальное преимущество в том, чтобы синхронизировать все, вы не хотите отказываться от этого, пока вам это не понадобится.
- Отдельные команды должны работать над кодом. Если вы не находитесь в постоянном общении друг с другом, вам в любом случае понадобятся накладные расходы процесса (семантическое управление версиями и т. д.), поэтому вы также можете получить более быстрое время сборки. (Чтобы было ясно, я думаю, что у каждого репозитория git должна быть одна команда, которая владеет им и несет за него ответственность, и когда команды разделяются, они должны разделять репозитории. У меня есть дополнительные мысли о процессах выпуска и обязанностях, но этот ответ уже довольно длинный) .
Я бы использовал репозиторий команды maven, возможно, Nexus. На самом деле я бы рекомендовал это еще до того, как вы перейдете к стадии нескольких проектов. Его очень легко запустить (просто приложение Java), и вы можете проксировать свои внешние зависимости через него, что означает, что у вас есть надежный источник для ваших зависимостей jar, и ваши сборки будут воспроизводимы, даже если одна из ваших исходных зависимостей исчезнет.
Я намерен описать свои способы командной работы в блоге, а пока буду рад ответить на любые дополнительные вопросы.
person
lmm
schedule
21.10.2014
sbt
. - person Nader Ghanbari   schedule 21.10.2014classpath dependency
, или это также означает, что компиляция одного всегда компилирует другой? - person matanster   schedule 05.11.2014test
отtest
иcompile
отtest
илиcompile
отcompile
или дажеcompile
отtest
, что очень полезно. Итак, вкратце, это означает, что когда проектA
зависит отB
по.dependsOn(B)
, по умолчанию вы можете использовать все классы в проектеB
в проектеA
. - person Nader Ghanbari   schedule 05.11.2014A
агрегирует проектыB
иC
(независимо от того, зависит от них или нет), при сборкеA
,B
иC
будут собираться автоматически. Это также может быть очень полезно, когда вы хотите протестировать или скомпилировать их все вместе. - person Nader Ghanbari   schedule 05.11.2014multi-project
, вы получаете хорошую гибкость при управлении версиями всего этого... - person matanster   schedule 05.11.2014