DDD реального мира: структурирование уровня домена

Я пытаюсь сделать переход от проектирования и разработки, ориентированного на данные, в DDD и прочитать Evans и Nillson, но у меня по-прежнему возникают проблемы с тем, что я собираюсь структурировать свой доменный слой. Я уверен, что характер моего нынешнего проекта не помогает!

Немного фона

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

Ориентированная на данные сторона

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

enter image description here

Схема, как и следовало ожидать, нормализована и не соответствует тому, как данные обрабатываются в моем приложении. И я оставил таблицы поиска и т.д., Чтобы попытаться свести к минимуму проблему.

Варианты использования

Первый вариант использования - это получение и отображение списка оценок, которые пользователь должен выполнить. Это будет отображаться при первом входе пользователя в приложение, и сначала кажется, что это будет относительно легко, но есть две морщины: 1 - оценки основаны на времени, поэтому они могут потребоваться ежемесячно, ежегодно или каждый "х", количество лет, основанных на дате рождения работника; и, 2 - пользователи могут сохранить результаты оценки и завершить их позже. В результате список должен содержать оценки, которые должны быть выполнены, а также любые, которые находятся в процессе.

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

В-третьих, HR нуждается в способе повторной генерации оценки с ответами, предоставленными супервизором.

Наконец, HR может создавать и изменять оценки - и они версируются. Поэтому всякий раз, когда кто-то изменяет оценку, создается новая версия, и она становится шаблоном для любых НОВЫХ оценок, которые выполняются (любые оценки в ходе выполнения продолжают использовать их исходный шаблон).

Модель домена

Разработка порядка, для меня имеет смысл, что у меня будет объект оценки, который является совокупным корнем для удовлетворения четвертого варианта использования. Он будет иметь дочернюю коллекцию объектов Раздела, которая, в свою очередь, будет иметь дочернюю коллекцию объектов Question. Они - все сущности, потому что у них есть личность (да?). Оценка - это объект, который использует код использования для сохранения, проверки и т.д. (Хотя субъекты раздела и вопроса проверяют себя и сворачивают статус в корневую оценку). Моя цель состоит в том, чтобы сделать абстрагирование версий от потребителя и реализовать его на уровне устойчивости данных (хорошая или плохая идея?)

Это означает, что у меня также будет EventRepository, который обрабатывает настойчивость для меня и, возможно, AssessmentFactory, который при необходимости создает новую Оценку.

Большая проблема связана с другими вариантами использования. Есть ли у меня также Агрегированный корень EmployeeAssessment? Или это просто сущность?

Рассматривая варианты использования, мне нужно использовать эту информацию несколькими способами. Во-первых, когда я создаю список оценок для отображения пользователю, мне приходится не только оценивать список прямых отчетов по частоте оценки, но также мне нужно знать, если я уже начал и/или выполнил оценку для этого сотрудника. И это происходит из таблицы EmployeeAssessments. В другом случае, когда пользователь действительно выполняет оценку, в этом случае я взаимодействую с таблицами EmployeeAssessments и Responses.

С точки зрения пользовательского интерфейса, когда пользователь выполняет оценку, они ничего не знают о внутренней структуре данных и т.д. Мне нужно предоставить пользовательскому интерфейсу список вопросов для этой оценки для отображения и принятия списка ответов на сохраняются. Это приводит ко второму корню с сопроводительным репозиторием и т.д.?

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

Оберните его уже!

Хорошо, я довольно часто болтал и думаю, что я очистил голову от паутины. Я ценю любое направление, предложения, критические замечания и т.д. Как я уже сказал, я пытаюсь сделать прыжок и думаю, что понимаю понятия, теперь это вопрос их применения. Спасибо!!!

Ответ 1

Я сделал тот же прыжок, что и ты, несколько лет назад. Сейчас я делаю прыжок с обычного ванильного DDD на CQRS (см. Cqrsinfo.com/).

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

Вам нужно полностью освободиться от мышления "данные, управляемые". Начните с основного рабочего процесса. Первое и третье использование - это просто операции. Сначала я хотел бы сосредоточиться на вариантах использования, в которых изменяется состояние совокупных корней. Таким образом, использовать случай 2, т.е. "Выполнить оценку", было бы хорошим местом для начала.

  • Как вы правильно указали, совокупным корнем будет оценка. Может быть создан класс "PerformAssessmentService" (эквивалент службы домена), и ваш рабочий процесс оценки будет существовать здесь. Этот рабочий процесс будет полностью протестирован, когда все зависимости, такие как хранилища, просто будут вычеркнуты.

  • Вы можете написать полный рабочий процесс оценки без какой-либо конкретной реализации базы данных /UI и т.д. Вся бизнес-логика организована в этой службе домена, и вся логика существует в вашей сущности оценки и других связанных с ней объектах.

  • Перейдите к следующему варианту использования - возможно, используйте случай 4 - измените оценки (повторите то же, что и выше)

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

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

Ответ 2

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