0

Grails でコントローラーを生成すると、コントローラーはドメイン層のメソッドを直接呼び出します。これはまったく理解できません。バックエンドとフロントエンドを緊密に結合しているため、これは一種の間違いだと私はいつも言っています。これはサービス層に属すると思います。

ドメイン オブジェクトで定義されたすべてのメソッドに対して、サービス レイヤーで同等のメソッド セットを作成するのはかなり見苦しいので、これを作成してAbstractService、サービス レイヤーからドメイン レイヤーにすべての (不足している) メソッド呼び出しを委譲します。

abstract class AbstractService {
    def entityType

    /**
     * By default, this method takes the name of the service that extends this
     * class, removes the suffix 'Service' and tries to create the Class object
     * from the resulting name. Override at will.
     */
    protected Class getEntityType() {
        if (!entityType) {
            try {
                entityType = Class.forName(this.class.name[0..-8], false, Thread.currentThread().contextClassLoader)
            } catch (ClassNotFoundException e) {
                throw new ClassNotFoundException("Class ${this.class.name[0..-8]} could not be found. Please "
                                + "override AbstractService#getEntityType() for ${this.class}.")
            }
        }
        entityType
    }

    def methodMissing(String name, args) {
        try {
            if (getEntityType()?.metaClass?.getStaticMetaMethod(name)) {
                getEntityType().invokeMethod(name, args)
            } else if (args?.last()?.metaClass?.getMetaMethod(name)) {
                args.last().invokeMethod(name, args.take(args.size() - 1))
            } else {
                throw new MissingMethodException(name, this.class, args)
            }
        } catch (MissingMethodException e) {
            throw new MissingMethodException(name, this.class, args)
        }
    }
}

次に、このサービスを次のように拡張します。

class UserService extends AbstractService {
}

そして、私のコントローラーは、たとえば次のようになります。

class UserController {
    def userService

    def create() {
        userService.save(new User(params))
    }

    def list() {
        userService.list(params)
    }

    // et cetera...
}

このほうがいいと思いませんか?依存性注入のおかげで、たとえば、コントローラーのコードを変更する必要なく、ビジネス レイヤー全体を書き直すことができます。

ご回答ありがとうございます。できるだけ多くの意見をお聞きしたいと思います。

4

2 に答える 2

0

スキャフォールディングされたコントローラー コードは、理想的なアプリケーション アーキテクチャを実際には表していません。生成されたスキャフォールド コードは、アプリケーションの CRUD 部分を生成するための出発点に過ぎないことに注意してください。

コントローラーはフロントエンドと対話するためのものであるため、一般に、GORMクエリのほとんどをコントローラーに配置したくないというのは正しいことです。確かに、クエリ/ビジネス ロジックをサービスに配置するか、クエリをドメイン クラスに直接配置することができます。そのため、Grails サービスは宣言型トランザクション処理をサポートしています。

于 2012-10-21T18:08:37.813 に答える
0

このモデルは、Java Web アプリケーションなどでよく使用されます。Rails (および Grails がそれに続いた) コミュニティは、ここでパラダイムを打ち破り、より単純なままにしようとしました。つまり、このエンティティが単に仕事をすることができるのに、エンティティを操作するためにサービス クラスを委譲するのはなぜでしょうか? エンティティがその仕事をするのが自然である場合は、他の誰かにその仕事をさせるべきではありません。そうすれば、オブジェクトはデータ ホルダーであるだけでなく、独自のビジネスを運営する方法も知っているため、 Anemic モデルを回避できます。

そうは言っても、サービス クラスを使用してエンティティを操作した方がよい場合もあります。たとえば、同時に異なる種類のエンティティが含まれる場合など...したがって、エンティティ自体が操作を処理するのが「自然」ではない場合(そして、強制的に機能させる必要がある場合)の場合は、サービス クラスが最適です。Rails に基づくこの記事では、サービス クラスの使用に関するヒントをいくつか紹介します。

そして、コントローラーをモデルと緊密に結合していません(バックエンドとフロントエンドと言いましたが、それがあなたの言いたいことだと思います)。コントローラは、最終的にはモデルを使用する必要があります。これは、エンティティ自体であろうと、それを操作するサービス クラス (モデルでもある) であろうとです。

于 2012-10-19T21:01:10.230 に答える