DDD Один Entity для нескольких агрегатов
Всем привет! Разрабатываю приложение на asp.core для работы с заявками. Пытаюсь применить DDD. Возникает неуверенность в некоторых решениях. Попробую коротко описать сущности.
Есть два основных агрегата User и Ticket
public class User
{
public UserId Id { get; private set; }
public FullName FullName { get; private set; }
public DateTime BirthDate { get; private set; }
public Group Group { get; private set; }
...
}
public class Ticket
{
public TicketId { get; private set; }
public Group Group { get; private set; }
...
}
Group это справочник который хранится в другой БД и изменятся другим приложением. Его я сделал как Entity, содержит Id и Name. В User это поле определяет к какой группе относится пользователь. В Ticket определят на какую группу назначена заявка. В Ticket таких справочников несколько.
Возникли вопросы:
**1.**Правильно ли что Group это Entity? Думал сделать его и другие справочники как ValueObject, но читал что объекты значения не принято хранить в отдельных таблицах. И мне необходимо в агрегатах, фактически (в БД) хранить только GroupId, чтобы после изменения в справочнике Group, в агрегатах получать измененное значение.
**2.**Если Group все таки Entity, то как мне ссылаться на нее в двух агрегатах? Выносить ее в отдельный агрегат, кажется неправильным. Как вариант, думал для Ticket создать Entity TicketGroup, но по факту через репозиторий возвращать одни и те же данный с одной таблицы.
Ответы (2 шт):
**1.**Правильно ли что Group это Entity? Думал сделать его и другие справочники как ValueObject, но читал что объекты значения не принято хранить в отдельных таблицах. И мне необходимо в агрегатах, фактически (в БД) хранить только GroupId, чтобы после изменения в справочнике Group, в агрегатах получать измененное значение.
Вы уходите от архитектуры к деталям. Архитектура нечто более абстрактное чем таблицы, значения, СУБД и прочее. Все это прочее это детали. Вы определитесь с политикой. что вам и где нужно и что оно будет в себе содержать. А сохранение, изменение и прочие это как вы заложите. К примеру у вас возможно в модели хранится булевая переменная в базе , а в модели у вас "Yes", "No", "Nothing". или другой пример Payment Status (Accepted, Canceled, Paied, ...) для которой у вас заготовлен Enum PaymentStatus (ACCEPTED("Accepted"), CANSELED("Canceled"), PAID("Paied"), ...). Понятно что в базе будут хранится только PaymentStatusCode и нет необходимости хранить PaymentStatus в базе. Но вот с группами и если вы всё же храните не GroupCode а GroupID намекая что это отдельная сущьность, а не ref то следовало бы хранить в таблице.
**2.**Если Group все таки Entity, то как мне ссылаться на нее в двух агрегатах? Выносить ее в отдельный агрегат, кажется неправильным. Как вариант, думал для Ticket создать Entity TicketGroup, но по факту через репозиторий возвращать одни и те же данный с одной таблицы.
В случае если вы храните Group в отдельной таблице как сущьность, то возьмите пример попонятнее вам.
User {
Address address { ...}
}
Company {
Address address { ...}
}
понятно что у компании и у пользователя есть адрес, который сам по себе ни от кого из них не зависит т.е отдельная сущьность. Если по каким то причинам так случилось что адрес изменился (переименовали страну, город, улицу, ...). То логично что все сущьности ссылавшиеся на этот адрес также также оставались актуальными.
Если у группы есть идентификатор то это сущность, но тебе не нужна вся сущность группы в пользователе и тикете, тебе достаточно только ссылки на группу, по этому достаточно хранить groupId, в целом желательно всегда использовать ид, а не подгружать все целиком, если же в рамках пользователя тебе нужны данные группы, то надо пересматривать границы, глобально сущности-агрегаты приводят к большой связанности, надо создавать агрегаты отталкиваясь от инвариантов в первую очередь и группировать данные вместе не по причине, вроде относится к юзеру положу в юзера, а больше со стороны функциональной, используются ли данные в тех же флоу например, что бы лучше понять надо копать в сторону coupling и cohesion, также как правильно находить границы своих сервисов