Как правило, разделение и упаковка модулей - это вопрос практичности развертывания и разработки.Кому еще понадобится код?Если я хочу изменить функциональность Y, все ли в пакете X?
Предупреждение: образец приложения упакован в одно приложение, чтобы его было легко использовать в качестве инструмента обучения,Но вот некоторые рекомендации, использующие его в качестве примера и делающие вид, что он реальный. Я сделаю некоторые предположения об этом в вакууме в иллюстративных целях, но ответственный специалист DDD схватит эксперта по домену и проведет интервью с разработчиком.команда для проверки любых предположений о домене, границах контекста и взаимосвязи между этими контекстами. Вы не можете использовать DDD в одиночку.
Правильное моделирование
Первым шагом будет сосредоточение на правильном моделировании и определении границ контекста.Я бы не беспокоился об уровнях инфраструктуры так же, как о различных контекстах и их моделях в домене.Критическими различиями в Примере приложения являются различия между этими различными контекстами, в этом приложении есть три контекста
- Бронирование
- Маршрутизация
- Сторонние поставщики / Порты /Корабли и т. Д.
Если вы заметили, что они четко отделены от корневых пакетов Java
- se.citerus.dddsample
- com.pathfinder
- com.aggregator
Уровни в основном предназначены для облегчения связи между этими контекстами и для отделения проблем инфраструктуры от работы в домене, что делает тестирование проще и обязанности домена более простыми.Инфраструктура важна, но тот факт, что пример приложения использует XML здесь и JMS там и в спящем режиме, есть второстепенные проблемы для моделирования домена.
В примере приложения это разделение становится очень ясным, легко увидеть, где Совокупные корни :
- Грузовые
- HandlingEvent
- Местоположение
- Рейс
Разбивать java-пакеты Aggegrate Roots - это хорошая практика.Leg не означает ничего за пределами агрегата Cargo, расписание - ничего за пределами агрегата Voyage, HandlingHistory - ничего за пределами агрегата HandingEvent.Хорошей практикой является сохранение доменной модели изолированной и тестируемой без инфраструктуры.Но вы, вероятно, не расширили бы эту развязку до уровня модуля.Не будет правилом говорить, что все ваши доменные объекты находятся в одном банке, а вся ваша инфраструктура - в другом.Бремя разработки и версии может стать болезненным.
Определение ограниченного контекста
Ключ в том, как модели различных контекстов разделены / не разделены .В контексте бронирования маршрут - это маршрут с набором ног.В области маршрутизации это «График» в реальном понимании этого слова, так что домен может решать задачи маршрутизации с помощью хорошо изученных алгоритмов обхода графа прямо из вашего класса Algorithms из колледжа.
Два контекста Booking иМаршрутизация осуществляется в тесном партнерстве , где они поддерживают общий интерфейс между двумя моделями ребер и узлов, а также маршрутами и ногами.Этот перевод поддерживается между моделями, которые управляются в ExternalRoutingService, где TransitPath становится маршрутом.Очевидно, что это очень важная точка интеграции, которая должна быть хорошо проработана в тестах и управляться с помощью Непрерывная интеграция
Другой контекст - это сторонняя интеграция, которая сообщает HandingEvents приложению о состоянии груза.Это достигается с помощью шаблона под названием Опубликованный язык .Короче говоря, нам все равно, как выглядят модели грузов третьих сторон, если они сообщают нам о событиях обработки в соответствии с нашей спецификацией публикации XML HandlingReport.
Взаимосвязь между сторонним контекстом и доменом бронирования называется Conformist , они предоставляют данные в соответствии с нашей определенной спецификацией, мы не изменяем наши модели, чтобы им было проще.Бремя на них, чтобы соответствовать нам.Тем не менее, я догадываюсь о ситуации, возможно, существует очень важный поставщик, и они фактически определяют модель XML, а не нас.Только интервью с вымышленной командой может действительно характеризовать это.
Так что в итоговой группе все классы тесно связаны с Агрегатом (возможно, тот же пакет).Четко определите границы контекста и убедитесь, что есть четкая точка интеграции, определите взаимосвязь контекстов Партнерство, Общее ядро, Опубликованный язык, Open Host Service, Conformist и т. Д.
На основании этого в примере мы, вероятно, могли бы упаковатьразличные контексты в отдельных модулях maven для бронирования грузов, поиска маршрута и агрегации обработки событий.Если это имело смысл с учетом практических методов методологии разработки и организации команды, и только если это имело место.
Ищите модули в ограниченном контексте
Получите права на границы контекста.Определите ваши агрегаты правильно в хорошие вертикали.Уменьшите связь, чтобы очистить четко определенные интерфейсы.
Ищите модули в вашем контексте.Они являются наиболее естественными кандидатами для отдельных модулей, и разделение может помочь более строго соблюдать и документировать границы контекста.Однако, как и многие другие разработки программного обеспечения, это не сложное и быстрое правило, которое будет зависеть от конкретного случая.Я могу себе представить и видел / писал приложения, которые имеют разные модели записи и модели чтения (думаю, нормализованные и денормализованные для, скажем, отчетности) и контексты для каждого из них, которые по практическим соображениям все еще могут быть упакованы в один модуль.
Еще один момент - опасайтесь совместного использования Агрегированных Корней между контекстами , это шаблон общего ядра DDD, и его следует использовать очень экономно, так как он может быстро скатиться в модель большого беспорядочного домена, которая не удовлетворяет потребностям любогоконтекст хорошо.Обратите внимание, что пример приложения не разделяет модели между RoutingService и BookingService.Помещение всех корней агрегатов домена в один модуль может непреднамеренно стимулировать эту практику.