DAO, репозитории и службы в DDD
Прочитав несколько статей, я начинаю понимать разницу между DAO и репозиториями, но я нахожусь в затруднении, пытаясь понять разницу между репозиториями и службами.
Для краткости в парадигме OO:
-
DAO: класс, содержащий базовый CRUD operations
для одного класса сущности. У этого есть необходимый код, чтобы получить или получить вещи из основной постоянной системы хранения. Вообще говоря, методы принимают объектные сущности в качестве параметров, за исключением метода retrieve
, где используется тип идентификатора.
-
Хранилища. На более высоком уровне абстракции. Как правило, я прочитал это своеобразное место, где помещается код, обрабатывающий операции над совокупными объектами (объекты, у которых есть дочерние объекты). Он использует DAO
для извлечения объектов из базы данных и, в конце концов, предоставляет интерфейс в домене "бизнес". (Но опять же, я думаю, что очень полезно использовать типы данных идентификаторов). Пример: очень простой addSomething
, где something
- дочерний объект родителя, чьи экземпляры, btw, управляются в целом репозиторием.
-
Услуги. Опять же, он находится на более высоком уровне абстракции. С моей скромной точки зрения они являются хорошим местом для подключения двух классов, которые не разделяют отношения между родителями и дочерними элементами, но являются такими же (в абстракционных терминах), как репозиторий. Пример: метод transferCash
между двумя bank accounts
.
Итак, это мои чтения, но я спрашиваю здесь, что эти мысли правильные или нет. Или как я должен думать. Или что-то, что указывает на то, что я действительно понимаю разницу во всех этих понятиях.
Некоторые источники:
Ответы
Ответ 1
Репозитории - как вы говорите - абстракция. Они происходят от Мартина Фаулера Object Query Pattern. Как Хранилища, так и DTO могут упростить сохранение базы данных путем сопоставления сохраненных данных с эквивалентным набором объектов сущностей. Тем не менее, хранилища более крупнозернистые, чем DAO, путем управления целым Aggregate Root (AG), часто скрывающим много внутреннего состояния от клиента. С другой стороны, DAO может быть столь же мелкозернистым, как выделение для одного объекта объекта. Для обеих хранилищ и DAO обычно используется Hibernate или другая структура объектно-реляционного сопоставления (ORM) вместо написания вашей собственной реализации.
Как правило, службы могут находиться на уровне обслуживания и могут действовать как функциональный фасад, уровень защиты от коррупции и координатор для кэширования и транзакции. Они часто являются хорошим местом для ведения лесозаготовок. Услуги грубозернистые и ориентированные на потребителя, например. Service.updateCustomerAdress()
или Service.sendOrder()
. Хранилища могут быть слишком мелкозернистыми для потребления клиентами, например. Customer.add(…)
, Order.modify(…)
.
Репозитории и DAO имеют одинаковую цель - постоянно сохранять данные. Услуги, с другой стороны, должны быть незнакомы с настойчивостью и не знать о вашей базе данных. Они обычно работают плотно вместе с услугами домена, репозиториями, ядром домена.
Ответ 2
Хранилища - это интерфейсы для хранения и извлечения Агрегированных корней (AR), а не отдельных объектов. У вас есть один репозиторий для каждого AR вашей модели домена.
В соответствии с Fowler шаблон хранилища, хранилища действуют как коллекция объектов в памяти, и это одно из основных различий, сравнивающих их с DAO.
Интерфейсы репозиториев являются средством для клиента модели домена (и, следовательно, являются частью модели домена), чтобы начать работу с моделью домена. Клиент должен получить экземпляр AR из репозитория, вызвать на нем некоторый метод, который обычно изменяет его внутреннее состояние, а затем сохраняет его обратно в репозиторий.
Ответ 3
Я не уверен, что такое "DAO". Хранилища - это абстракция для загрузки объектов. Вы должны иметь возможность получить сущность и сохранить один, вот и все. Нет запросов. Если вы хотите запросить некоторые данные, напишите запрос (возможно, даже в рамках метода действия MVC или с простейшими простыми абстракциями, позволяющими выполнять некоторый SQL и возвращать некоторые DTO, которые могут быть отображены прямо в HTML).
Услуги, с другой стороны, сложны. Для начала этот термин перегружен. "Службы приложений", определенные в , существуют потому, что объектам в модели домена не разрешено обращаться к инфраструктурным проблемам, таким как базы данных, обмен сообщениями, кеширование и т.д. Им нужно все это, что было сделано для них, и вручили им на тарелке, а Application Services - именно это. Службы приложений, в свою очередь, не содержат никакой логики. Я бы не ожидал увидеть, что ICustomerService.ChangeAddress()
делает что-то другое, кроме:
- Загрузите объект Customer.
- Вызов
Customer.ChangeAddress(newAddress)
< - это инкапсулирует логику домена
- Сохраните клиента.
- Возможно, опубликуйте некоторые события.
Если у вас есть служба, которая загружает клиента, устанавливая его свойство "Адрес" и сохраняя его, тогда эта услуга фактически является транзакцией Script, а Клиент является DTO. Это означает, что у вас определенно есть нечеткая абстракция и, вероятно, есть модель анемичного домена. Объекты модели домена не должны иметь публичные сеттеры, а когда DDD объединяется с CQRS, ваша модель домена может даже не иметь какого-либо публичного состояния вне значений основного идентификатора объекта.