2

Я пытаюсь структурировать приложение с использованием DDD и луковой/гексагональной/чистой архитектуры (с использованием Java и Spring). Мне легче найти руководство по самим понятиям, чем на самом деле, как их реализовать. DDD, в частности, кажется довольно сложным, чтобы найти примеры, которые поучительны, потому что каждая проблема уникальна. Я видел многочисленные примеры SO, которые были полезны, но у меня все еще есть вопросы. Интересно, сможет ли мой пример помочь мне и всем остальным.Пример структуры DDD

Надеюсь, вы можете простить меня, задав здесь несколько вопросов. Пример кажется слишком большим, чтобы я мог повторить его в нескольких вопросах.

Контекст:

У нас есть приложение, которое должно отображать информацию о статистике футбола и имеет следующие понятия (для простоты я не включал все атрибуты):

  • Team, которая имеет много Игроки.
  • Игрок.
  • Светильник, в котором две команды и 2 половины.
  • Половина, которая имеет 2 образованияPlayed и много комбинаций.
  • FormationPlayed, который имеет много PositionsPlayed.
  • PositionPlayed, в котором есть 1 Player и объект значения позиции.
  • Комбинация, которая может быть двух типов и имеет много перемещений.
  • Перемещение, которое может быть двух типов, имеет 1 игрока и объект значения события.

Как вы можете себе представить, попытка выяснить, какие вещи являются совокупными корнями, здесь сложна.

  • Команда может существовать независимо, а именно AR.
  • Игрок может существовать независимо, поэтому AR.
  • Светильник, при удалении, должен также удалить его половинки, так что это AR.
  • Половина должна быть сущностью в Приспособлении.
  • FormationPlayed должен быть удален, если половина удалена, поэтому, возможно, это должно быть подразделение в Half.
  • PositionPlayed должен быть удален, когда формация удалена, поэтому верьте, что это должно быть лицо в FormationPlayed.
  • Комбинация в определенном смысле может существовать независимо, хотя и привязана к определенной половине игры. Возможно, это может быть AR, связанный в конечном итоге.
  • Перемещение должно быть удалено при удалении комбинации, поэтому верьте, что это должно быть сущность в комбинации.

Вопросы:

  1. Видите ли вы какие-либо ошибки в приведенной выше конструкции? Если да, то что бы вы изменили?
  2. Светильник - Half-FormationPlayed - PositionPlayed aggregate кажется слишком большим, поэтому я задаюсь вопросом, согласитесь ли вы, что это можно разделить на Fixture - Half и FormationPlayed - PositionPlayed, используя возможную последовательность.Я не могу найти пример того, как это реализовано на Java? Если Fixture были удалены, вы можете запустить событие FixtureDeleted, которое также приведет к удалению его соответствующих объектов FormationPlayed?
  3. Я хочу построить модель домена, которая не понимает, как она будет сохраняться (согласно архитектуре лука). Мое понимание заключается в том, что объекты домена здесь не должны иметь суррогатных ключей, поскольку это относится к упорству. Я также считаю, что объекты должны ссылаться только на объекты в других агрегатах с помощью идентификаторов. Как тогда, например, был бы PositionPlayed reference Player в модели домена?
  4. Первоначально целью является только разрешение клиенту получать данные и отображать их. В конечном итоге я хочу, чтобы клиенты могли выполнять сами CRUD, и я хочу, чтобы все инварианты удерживались вместе моделью домена, когда это происходит. Будет ли упрощено (и вы можете показать мне или указать мне пример, объясняющий, как) иметь две модели домена, одну для поиска данных и одну богатую для операций, которые будут выполняться позже? Два БК, как это было. Причина, по которой я спрашиваю, заключается в том, что модель с богатым доменом кажется довольно трудоемкой, когда мы сначала хотим отображать статистику в базе данных, но я также не хочу создавать проблемы для себя по линии, если лучше создайте одну богатую доменную модель в настоящее время с учетом предполагаемых позже. Интересно, если бы я создал только упрощенную модель для извлечения данных, какие концепции в DDD можно было бы игнорировать (мне бы, например, пришлось разбить большие агрегаты?)

Я надеюсь, что все это имеет смысл , Очевидно, рад объяснить, если потребуется. Поймите, я прошу много здесь, и я, возможно, путал некоторые идеи. Любые ответы и мудрость, которые вы можете дать этому, будут очень признательны!

+0

«Могут существовать независимо», как правило, превзойдены более сложными инвариантами домена, транзакционным анализом и вопросами производительности в реальных ситуациях. Объекты домена не являются статическими объектами, большая часть логики домена связана с более подробными сведениями о том, как они могут быть переведены из одного состояния в другое. Синхронизация между сущностями также является большим вопросом, который влияет на дизайн. Я предлагаю прочитать/посмотреть что-нибудь в Vaughn Vernon на предмет совокупного дизайна. – guillaume31

+0

Спасибо @ guillaume31. Ясно, что вы хорошо разбираетесь в этом вопросе. Да, я рассмотрел ряд переговоров Вон Вернона по этому вопросу - которые являются блестящими, но поскольку каждая проблема уникальна, я все еще немного смущен, как реально реализовать то, что он говорит. У меня очень мало рекомендаций по этому вопросу, кроме книг, переговоров, репозиториев и ответов, которые я могу найти в Интернете. То, что я имею в виду под этим, - это общий разговор или пример, найденный поиском, может только зайти так далеко в решении конкретной проблемы. –

+0

@ guillaume31 Считаете ли вы, что в этом случае правильная модель доменов правильная, и знаете ли вы какие-либо другие конкретные ссылки, которые могут быть полезны для этого конкретного случая? –

ответ

3

Вы видите ошибки в приведенном выше дизайне? Если да, то что бы вы изменили?

Может быть большой: ваша система - книга записи? или это просто отслеживание событий, которые происходят в «реальном мире». В некотором смысле, точка агрегатов для того, чтобы книга записи является внутренне непротиворечивой, но если вы не книга записи ....

Для примера того, что я имею в виду

Если Крепеж были удалены, вы бы огонь событие FixtureDeleted, что вызывает его соответствующие FormationPlayed объекты также будут удалены?

Udi Dahan писал (а): Don't Delete, Just Don't. Если у объекта есть жизненный цикл, и этот жизненный цикл имеет конец, то вы его помечаете, но вы не удаляете сущность.

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

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

Мое понимание заключается в том, что объекты домена здесь не должны иметь суррогатных ключей, поскольку это относится к постоянству. Я также считаю, что объекты должны ссылаться только на объекты в других агрегатах с помощью идентификаторов. Как тогда, например, был бы PositionPlayed reference Player в модели домена?

Ah - Хорошо, это весело. Не путайте суррогатные ключи, используемые в уровне персистентности, с идентификаторами в модели домена. Например, когда я смотрю на историю покупок на Amazon, каждый из моих заказов (предположительно, агрегат) имеет связанный с ним ORDER #. Это означает, что уровень домена знает о OrderNumber как тип значения. Решение сохранения на заднем конце может вводить суррогатные ключи при хранении этих данных, но эти ключи не используются моделью.

Отметьте, что я выбрал пример, где совокупность явно является полномочием - порядок действительно существует только в модели. Когда реальный мир книга записи, вы часто не имеете уникальный идентификатор доступный (что PlayerId Лионель Месси?)

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

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

Обнаружение и устранение несоответствий часто проще/дешевле, чем пытаться получить право на право; и может быть удовлетворительным для бизнеса, учитывая затраты. Что-то нужно иметь в виду.

Приложение отслеживает события в реальном мире. В настоящий момент они записываются вручную в базу данных. Можете ли вы объяснить, почему вы считаете, что различие важно?

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

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

Один из видов информационного ресурса, который вы можете создать, - это отчет о целях Месси в сезоне. Поэтому каждый раз, когда сообщается о цели, вы запускаете команду для обновления агрегата отчета. Это не анемия - не совсем, но это не очень интересно. Это действительно просто взгляд (в терминах CQRS, это читаемая модель), которую вы можете воссоздать из истории событий. В нем нет никакого интеллекта.

Агрегаты процентов - это те, которые принимают решения для себя, исходя из информации, которую они предоставляют.

Надуманным примером агрегата будет тот, который, если игрок набирает более 10 голов в сезоне, приказывает, чтобы игроки играли за вас.Обратите внимание, что, хотя «цели» уже есть в потоке событий, в бизнес-правиле этого нет. Это чисто предметная модель домена.

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

Основная идея здесь - цели - это то, о чем сообщается в совокупности. Решение о приобретении трикотажа производится в совокупности и делится с миром.

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

доменная модель согласно архитектуре лука, можете ли вы указать мне на любые хорошие примеры?

Лучшее место для поиска, как это ни странно, относится к функциональным типам программирования. Mark Seemann's blog включает в себя множество важных идей, которые помогут здесь.

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

вы верите общепринятое мнение было бы, что анемия модель должна быть принята для домена такого размера

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

+0

Очень ценю, что вы нашли время, чтобы пройти через это. Спасибо за вашу мудрость по этому поводу. Если бы вы могли вернуться к тем пунктам, которые вы указали, это действительно помогло бы. Приложение отслеживает события в реальном мире. В настоящий момент они записываются вручную в базу данных. Можете ли вы объяснить, почему вы считаете, что различие важно? –

+0

Хороший вопрос об удалении - я читал эту статью раньше. Думаю, мой вопрос был больше о том, как команда будет каскадироваться и обрабатываться в совокупности, которая разбивается на более мелкие части, независимо от типа команды. Основная борьба в моей голове сводит агрегат к управляемым кускам, и поэтому я ищу некоторую проверку того, что то, как я думаю, делает это правильно. Если бы это было обновление, было бы правильным использование событий домена, которые я описал? –

+0

Re-модель домена согласно архитектуре лука, которая, можете ли вы указать мне на любые хорошие примеры? Часто я нахожу примеры, которые либо следуют архитектуре лука, но не ddd, следуют ddd, но не архитектуре лука или следуют за ними, но не поучительны в проблеме, которую я пытаюсь решить. Re ids, это действительно интересно. Создаете ли вы идентификатор везде, где объект должен ссылаться на один в модели домена? –

Смежные вопросы