DDD: подклассы и корневые объекты - PullRequest
9 голосов
/ 27 августа 2009

Допустим, у меня есть типичная сущность Автомобиль

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

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

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

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

Допустим, у меня есть другая сущность, Компания . Это будет корневая сущность другого Совокупного . В компании работает много людей, представленных субъектом Лицо . У людей могут быть машины. Но Президент компании обычно очень богат, и у таких людей есть Ferrari:

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

В этой ситуации у меня есть Президент организации, который находится внутри Агрегата компании , который содержит ссылку на Ferrari, специализацию корневого объекта другого агрегата. .

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


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

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

Или я должен построить стол для автомобилей и стол для Ferrari, последний из которых имеет свой ПК - ФК автомобилей?

Спасибо!

Ответы [ 3 ]

4 голосов
/ 30 августа 2009

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

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

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

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

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

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

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

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

3 голосов
/ 30 августа 2009

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

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

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

2 голосов
/ 29 августа 2009

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

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

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

Редактировать подписки

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

...