Доменные объекты и сервисы - PullRequest
22 голосов
/ 13 января 2009

В на этот вопрос кто-то отвечает"Вы никогда не позволите реализациям объекта домена сами по себе вызывать службы!". Является ли это утверждение жестким правилом DDD или зависит от вашего собственного приложения и архитектуры?

Придуманный пример:

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

public IThumbPrintService {
    Guid FindMatch(Bitmap image);
}

public class UserImage {
    public Bitmap Image {get; set;} 
    public Guid ThumbPrintId {get; set;}
    public bool FindThumbPrintMatch() {
       // Would you call the service from here?
       ThumbPrintId = _thumbPrintService.FindMatch(this.Image);
       return ! ThumbPrintId.CompareTo(Guid.Empty);
    }
}

public class RoboCopUserImageService : IUserImageService {
     // Or move the call to a service method 
     // since it depends on calling a separate service interface
     public bool FindThumbPrintMatch(UserImage userImage) {
        userImage.ThumbPrintId = _thumbPrintService.FindMatch(userImage.Image);
        return !userImage.ThumbPrintId.CompareTo(Guid.Empty);            
     }
}

Чего можно избежать или получить, не позволяя объектам домена самим вызывать службы?

РЕДАКТИРОВАТЬ: Есть ли хорошие онлайн-статьи, которые обсуждают эту конкретную тему?

Ответы [ 4 ]

45 голосов
/ 13 января 2009

Это загадка Spreadsheet : , набирает ли телефон номер телефона, или телефон набирает номер на телефоне ?

Возможно, вам будет интересно прочитать Double Dispatch , хотя излишне в вашей ситуации, я считаю .

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

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

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

Я думаю, что допустимо, чтобы domainObject.moveToNextState () (предполагая, что этот код «имеет смысл» на вашем вездесущем языке) вызывал службу, которая общается с вашим сервером, поскольку сервер рабочих процессов управляет частью модели домена.

Я добавлю, что DDD очень заинтересован в следовании языку домена. Слышите ли вы, что эксперты домена говорят: «Пользовательское изображение находит, совпадает ли его отпечаток с изображением в службе поставщиков XYZ»? Или они говорят: «Служба поставщика XYZ, учитывая отпечаток большого пальца, указывает, существует ли этот отпечаток большого пальца»? Выберите тот, который больше всего подходит для вашего домена.

Еще несколько мыслей (я много думал об этой проблеме, потому что она занимает центральное место в дизайне):

  • В книге DDD Эванса есть учетная запись сущность имеет такие методы, как кредит (Сумма), дебет (Сумма), перевод на (Счет, Сумма) и accrue (), но у FundsTransferService есть метод переноса (Account, Account, Amount). Метод TransferTo не вызывает никакой службы, а просто обрабатывает логику, которая включает в себя учетные записи, такие как зачисление и списание правильных сумм.

    FundsTransferService, помимо координации, имеет свои собственные правила для проверки, правила, которые не вписываются в Учетные записи. Точная сумма кредита или дебета может быть связана с внешними сторонами. Это усложняет для TransferTo вызов службы.

  • Для простых объектов, таких как UserImage, существенная доменная логика, которая может вписаться в сам объект, может быть недостаточной, потому что это, насколько я могу сказать, Агрегат. Я думаю, что агрегаты предоставляют больше возможностей для размещения логики предметной области. Пример учетной записи, вероятно, является совокупным.
2 голосов
/ 13 января 2009

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

0 голосов
/ 04 августа 2017

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

0 голосов
/ 13 января 2009

Если вы позволяете объекту сущности вызывать службу, он выполняет две роли: объект данных и объект службы. Как правило, каждый объект должен нести ответственность не только за реализацию, но и за использование.

В вашем случае скромный UserImage выглядит как Image и распознаватель ThumbPrint.

...