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

Является ли плохой дизайн для вызова сервисов Grails из объектов домена?

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

class Purchase {

    // Injected
    def paymentService

    String captureTransactionId
    Boolean captured

    // ...

    def capture() {
        captureTransactionId = paymentService.capturePurchase( this )
        captured = captureTransactionId != null
    }

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

4b9b3361

Ответ 1

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

Но Grails заменяет необходимость в DAO путем проводки в методах GORM в классах доменов, а также заменяет необходимость в валидаторах, помещая проверку в классы домена. Таким образом, это создает проблемы при принятии решения о том, какая бизнес-логика должна идти в классе домена и что должно быть в сервисе или других вспомогательных сервисах - отличное место для размещения бизнес-логики, которая может потребоваться в методе класса домена или валидаторе.

Да, это не OO-чистый, да, вы создаете цикл (служба вызывает класс домена, а класс домена вызывает службу), нет, это не "путь

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

Ответ 2

Я не думаю, что классы домена/модели должны вызывать сервисы. Это должно быть наоборот.

Служба может организовать другие службы для выполнения прецедента. Я думаю, что правильный путь.

Ответ 3

Я только даю свое личное мнение. Поскольку grails автоматически поддерживает инъекционные услуги в классах доменов (в отличие от, например, инъекционных услуг в стандартные классы groovy, которые вы должны настроить самостоятельно), я бы предположил, что он предназначен для использования таким образом и, следовательно, не является плохой практикой.

Также он делает код более читаемым с чем-то вроде "myDomainInstance.someUsefulMethod()", чем "someService.someUsefulMethod(myDomainInstance)" (надеюсь, вы знаете, что я имею в виду).

Ответ 4

Я не уверен, правильно это или нет.

В таких случаях, как пример, как насчет того или иного пути: либо поставить код paymentService.capturePurchase() внутри класса Purchase, либо вы можете поместить всю логику в службу?