DDD Агрегаты и объекты стоимости - PullRequest
6 голосов
/ 20 сентября 2011

Я хотел бы задать вопрос об особенностях DDD. Допустим, у нас есть два агрегата, и каждый из них содержит адрес объекта значения. В соответствии с DDD Эрика Эванса, мы должны изолировать агрегаты друг от друга, чтобы корень агрегата первого агрегата не мог иметь ссылку на Address. Честно говоря, это не имеет смысла для меня, поэтому вопрос в том, как разрешить такую ​​ситуацию? Какой агрегат должен содержать адрес?

Спасибо

Ответы [ 3 ]

14 голосов
/ 20 сентября 2011

Вы можете использовать его, используя тот же объект значения. Но делайте это только в том случае, если совокупные корни существуют в одном и том же ограниченном контексте и, следовательно, имеют одинаковое значение для обоих агрегатов. Если агрегаты существуют в разных ограниченных контекстах, то есть 2 отдельных и дубликата. Утечка проблем одного ограниченного контекста в другой - это то, с чем Эрик пытается бороться.

Для большинства проблемы сущности против объекта ценности сводятся к людям, имеющим проблемы с дублированием данных. Мы были так обучены думать в 3-й нормальной форме единой канонической модели. DDD борется с неизбежной сложностью, которая возникает благодаря принудительному дублированию, когда это необходимо, и разрешению концепций, которые когда-то считались одним во многие.

Надеюсь, это поможет

8 голосов
/ 20 сентября 2011

Объект значения - это объект, который описывает некоторую характеристику или атрибут, но не несет понятия идентичности.

Поскольку он не имеет концептуальной идентичности, вы не можете «ссылаться» или «иметь ссылку» на него. Вы можете только «содержать» это. Допустим, у вас есть пользователь, а у пользователя есть возраст. Возраст является ценностным объектом. Если Джону 25 лет, а Джейн 25 лет, они не «ссылаются» на одну и ту же эпоху. Возраст Джона просто равен возрасту Джейн. Таким образом, если ваш Адрес действительно является Объектом Значения, то вы не нарушаете никаких Агрегированных границ. Ваши совокупные корни просто имеют равные адреса. Даже если у вас есть техническая ссылка java / c # на Address, это не имеет значения, потому что Value Object является неизменяемым большую часть времени.

Трудно ответить на ваш вопрос, хотя, не зная, в каком домене вы работаете. Но обычно Address не обязательно должен быть объектом значения. Эрик Эванс упоминает в своей книге , что домены Почтовой службы и Маршрута доставки будут рассматривать Адрес как сущность. Электротехническая компания, которая отправляет технических специалистов, должна понимать, что два звонка в сервисный центр из «123 Elm St» на самом деле поступают с одного и того же адреса, и ей нужно отправить только одного технического специалиста. Адрес или «Жилище» в данном случае является юридическим лицом.

2 голосов
/ 27 марта 2015

Агрегаты имеют дело только с ИЗМЕНЕНИЕ ДАННЫХ .Не должно быть двух агрегатов для изменения одних и тех же данных.Поскольку объект Value является неизменным, он предотвращает возникновение этого сценария.Поэтому вполне допустимо, чтобы два или более агрегатов совместно использовали один и тот же объект значений, так как это структура данных только для чтения, а агрегат не заботится о модели чтения.

Address a = new Address("1111 ABC Ave.");
person.setAddress(a);
letter.setAddress(a);

person.getAddress().change("2222 XYS Ave.") // THIS IS ILLEGAL SINCE Address is a VO (immutable)

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

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

В этом весь смысл Aggregate Roots, он слишком моделирует вещи, ограничивающие побочные эффекты.Если вы определите очень четкие границы изменений, с кодом будет легче работать, и вы предотвратите потенциальный вредный неожиданный эффект.


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

Скажем, для доставки вам нужно:

Address
{
    Number;
    Unit;
    Street;
    State;
    Country;
    PostalCode;
}

Но для местоположения выneed:

Address
{
    Number;
    Unit;
    Latitude;
    Longitude;
}

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

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

...