Уточнение при работе с коллекциями с шаблоном хранилища - PullRequest
4 голосов
/ 27 августа 2010

Если у вас есть два репозитория, имеющих дело с персистентностью реляционной БД, репозиторий person, который имеет дело с объектами «Person», и репозиторий address, который имеет дело с объектами «Address», и объект person имеет коллекцию адресов (возможно, загруженных с отложенным доступом ). Очевидно, что репозиторий person будет использоваться для сохранения изменений в объектах person, а репозиторий address будет использоваться для сохранения изменений в объектах address, но что будет отвечать за сохранение изменений в коллекции адресов person?

Какие стратегии доступны для сохранения изменений в коллекции адресов объектов-персон обратно в базу данных? И где эта ответственность будет лежать в репозиториях (будет ли это репозиторий person, даже если в БД это будут адреса, которые хранят ссылку на человека)?

Я должен отметить, что это не использует ORM.

Спасибо за любую помощь, любые стратегии / разъяснения будут оценены.

Ответы [ 2 ]

5 голосов
/ 28 августа 2010

Немного пищи для размышлений:

Есть действительно два вопроса, на которые нужно ответить, прежде чем вы решите, как решить проблему:

  1. Может ли Адрес существовать без Личности?
  2. Может ли Адрес принадлежать более чем одному человеку?

Если ответ на 1 - нет, а ответ на 2 - нет - у вас не должно быть AddressRepository, а Person должен нести ответственность за сохранение адресов в обычных отношениях 1-ко-многим с внешним ключом в адрес. В противном случае Person внезапно отвечает за удаление адресов - или ему нужна ссылка на AddressRepository - что в IMO приведет к ужасному беспорядку в ответах.

Если ответ на 1. «Нет», а ответ на «2.» - «Да», у вас отношения «многие ко многим», и Человек должен поддерживать эти отношения «многие ко многим» (поскольку это единственное, кто обладает нужно было упорствовать).

Если ответ на 1 - «да», а ответ на «2» - нет - адрес должен отвечать за обновление отношения - и должен иметь свойство Partner, поэтому связь в объектах является однонаправленной.

И, наконец, - если оба - да - у вас снова есть отношение многие ко многим, но на этот раз было бы более разумно разрешить, чтобы Адрес обрабатывал ассоциацию многие ко многим.

Надеюсь, это поможет вам решить:)

3 голосов
/ 29 августа 2010

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

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

Меня это смутило, когда я впервые узнал об этом - я не думал, что это будет так простоидентифицировать эти объекты.Выходом является дополнительная концепция « Ограниченный контекст ».Это, вероятно, самый недооцененный принцип проектирования.

Короче говоря, учтите, что вы решаете следующие две истории пользователей.

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

Итак, у вас есть что-то вроде следующей модели: Person has Addresses and Orders and Order has an Address

Казалось бы, это может быть труднорассекать.Если Person является корнем, тогда, когда пользователь просто меняет свою информацию, мы должны загрузить объект Person с ассоциацией Orders.Если они размещают много заказов (скажем, управляют запасами для своей компании), это может стать огромной проблемой производительности.

Выбор ордера в качестве совокупного корня также не решает проблему.Если в Заказе нет ссылки на Лица, как мы сможем проверить, является ли выбранный Адрес действительным?

В сторону: ответ старой школы на эти проблемы - «ленивая нагрузка» и «двунаправленная ассоциация» соответственно.Однако оба эти метода имеют свои собственные сложности, и я убежден, что они, как правило, доставляют больше хлопот, чем стоят.

Разрешение этого кажущегося конфликта (почему я чувствую, чтоЯ направляю Элияху Голдратт ?), Чтобы признать, что эти две истории существуют в разных контекстах значения.Когда пользователь хранит адрес, он не заботится о заказах, аналогично, когда администратор просматривает адреса, которые ему не нужны, для человека, для которого он предназначен.Существует конфликт определений.Когда два контекста говорят «Адрес», они ссылаются на один и тот же физический объект, но только как пробный камень для двух совершенно разных концепций!Что касается человека, адрес - это просто блок теста, который он сохранил.Что касается менеджера по логистике, то единственное требование к адресу должно соответствовать реальному местоположению.

Так почему же они должны быть одним и тем же объектом?

Person has PreviousAddresses and Order has ShippingAddresses of which one is selected

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

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

...