DDD: подклассы и корневые сущности

предположим, у меня есть типичная сущность автомобиль

class Car : Entity
{
    public double MaxSpeed { get; set; }
    public Color Color { get; set; }
    /* ... */
}

эта сущность в моей модели домена будет корневой объект на совокупность.

Теперь предположим, что я специализируюсь на автомобилях. Я создаю Феррари, а счастливые владельцы Феррари любят называть их по прозвищу:

class Ferrari : Car
{
    public string Nickname { get; set; }
}

предположим, у меня есть другая сущность,компанию сущности. Это будет корневой объект другой совокупность. Есть много людей, работающих на компанию, представленную субъектом человек. Люди могут иметь автомобили. Но ... --4-->президент компании обычно очень богатые и такого рода люди, у них есть Ferrari:

class President : Person
{
    public Ferrari Ferrari { get; set; }
}

в этой ситуации у меня есть президент сущности, который внутри на Компанию Aggregate, это держит ссылку на Ferrari, специализация корневой сущности другого агрегата.

правильно ли это с учетом DDD? могу ли / должен ли я рассматривать специализацию самих корневых сущностей как корневые сущности одной и той же совокупности? Я имею в виду, в домен я описал, является лицом, Ferrari также корневая сущность совокупного автомобиля (с Феррари тоже машина)?


Теперь предположим, что я должен сохраните эту модель в базе данных. Я думаю, что мой вопрос не зависит от структуры OR/M, которую я буду использовать.

как я должен построить таблица с автомобилями? Должен ли я построить одну таблицу Cars, со столбцом "CarType" (возможные значения: "Car", "Ferrari") и столбцом Nullable Nickname?

или я должен построить таблицу для автомобилей и таблицу для Ferraris, последняя имеет свой ПК FK автомобилей?

спасибо!

3 ответов


Я думаю, вы начинаете терять гибкость системы, создавая конкретные типы этих объектов. Тип отношений, на который вы намекаете, - это то, что я обычно передаю сущности "типа". Например, у вас есть машина. Ferrari-это тип автомобиля. Двух сущностей, которые несут из автомобиля и CarType.

то, как вы говорите об этом, вам придется добавлять новые сущности каждый раз, когда вводится новый тип. Если все это ты ... пытаются захватить это "прозвище" автомобиля, я бы подумал, что это просто еще одна часть данных, а не другая сущность. Если у вас нет разных данных (т. е. разных имен свойств) и/или различий в поведении объектов Car для разных типов, вы не получите много с этим подходом. Я бы предпочел иметь методы репозитория, такие как FindCarByType() и иметь дело с одним типом сущности, чтобы уменьшить риск.

Я никоим образом не эксперт DDD, и я борюсь с некоторыми концепциями (или больше похоже на борьбу с множественными интерпретациями некоторых концепций). Я нахожу, что нет 100% чистой реализации и что есть нюансы в каждой реализации, которые я видел.

Изменить Следующим Образом

Я вижу, что я неправильно понял часть того, что вы написали. Я вижу, что прозвище не для всех автомобилей, а только для Ferrari : Car. Я думаю, что ответ действительно "это зависит". Сколько специализации домена у вас есть в остальной части ваша модель? Наличие прозвища может быть распространено среди субъектов Ferrari, но является ли оно эксклюзивным? Речь идет не только о фактических данных, но и о требованиях. В основном это сводится к тому, сколько специализации вы ожидаете в этих сущностях.


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

президент-это просто роль человека, и человек может иметь несколько ролей. Может быть, президент получил только одну роль, но это просто случайно, выбрав неправильный пример.

Ferrari не должен быть унаследован от автомобиля. Это не очевидно на примере Ferrari, потому что они делают только один тип автомобилей, но считают, что компания делает много типов как фургоны, седаны, хэтчбеки, грузовики и так далее. Вероятно,вы захотите сделать классы для каждого типа, который унаследует класс car. И что потом?.. вы собираетесь сделать пять классов Toyota, которые будут наследовать от каждого типа? Такие как...

Car -> Sedan -> ToyotaSedan
Car -> Truck -> ToyotaTruck
Car -> Hatchback -> ToyotaHatchback

Это было бы смешно.

отказ от ответственности: я ничего не знаю о машинах. Однако...

не используйте наследование для моделирования вашего домена. Когда-либо.

попробуйте без наследования и также станет очевидно, как сохранить свой домен.


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

таким образом, в вашем случае вы хотели бы, чтобы президент имел идентификатор автомобиля, и если вам когда-либо нужно было что-то сделать с автомобилем президента, вы бы использовали идентификатор автомобиля, чтобы пойти в хранилище, чтобы получить автомобиль. У президента не будет упоминания о самой машине.

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