Подтвердить что ты не робот

Доменные объекты и службы

В этом задайте кому-то ответы: "Вы никогда не позволяете реализации объектов домена сами ссылаться на службы!", Является ли это утверждение жестким правилом 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);            
     }
}

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

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

4b9b3361

Ответ 1

Это Envelopet Conundrum: набирает номер телефона по номеру телефона, или номер телефона на телефоне?

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

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

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

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

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

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

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

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

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

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

Ответ 2

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

Ответ 3

Если вы разрешаете объекту Entity Object вызывать службу, он выполняет две роли Data Object и Service Object. Как правило, каждый объект должен нести ответственность не только за реализацию, но и за использование.

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

Ответ 4

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