1

私は Fantom の afBedSheet フレームワークで遊んでおり、そのドキュメント hereでは、例は次のようになります...

using afIoc
using afBedSheet

class HelloPage {
  Text hello(Str name, Int iq := 666) {
    return Text.fromPlain("Hello! I'm $name and I have an IQ of $iq!")
  }
}

class AppModule {
  @Contribute { serviceType=Routes# }
  static Void contributeRoutes(OrderedConfig conf) {
    conf.add(Route(`/index`, Text.fromPlain("Welcome to BedSheet!")))
    conf.add(Route(`/hello/**`, HelloPage#hello))
  }
}
...

上記の convertRoutes メソッドは、追加されるルートが増えるにつれて、特にルート ハンドラーが異なるクラスから来る場合に、読み取りと保守が難しくなり始めます。

私はこれを別の方法で行っています: 各 Service クラスで、次の例のように、そのメソッドによって処理されるルートのリストを返す静的メソッドを追加しています。

using afBedSheet

class Info {

    static Route[] routes() {[
        Route(`/info`, #all),
        Route(`/info/pod`, #podAll),
        Route(`/info/pod/name`, #podName),
        Route(`/info/pod/version`, #podVersion),
    ]}

    Text all() {
        Text.fromJson(["This application blah blah blah"])
    }

    Text podAll() {
        pod := Pod.of(this)
        return Text.fromPlain("$pod.name $pod.version.toStr")
    }

    Text podName() {
        Text.fromPlain(Pod.of(this).name)
    }

    Text podVersion() {
        Text.fromPlain(Pod.of(this).version.toStr)
    }

}

次に、私の AppModule は次のようになります

using afIoc
using afBedSheet

class AppModule {

    @Contribute { serviceType=Routes# }
    static Void contributeRoutes(OrderedConfig conf) {
        Info.routes.each { conf.add(it) }
        AnotherService.routes.each { conf.add(it) }
        YetAnotherService.routes.each { conf.add(it) }
        ...
}

私は、AppModule をクリーンに保ち、Route 定義とハンドラー マッピングを実装クラスに近づけようとしています。これにより、サービス/ルートの保守が容易になると期待していますが、それが良いアイデアか悪いアイデアかはわかりません。これを行う利点は次のとおりです。

  • ルート ハンドラー メソッドをクラスに追加する場合、同じクラスでルートを宣言します。
  • ルート ハンドラー メソッドは同じクラスの一部であるため、スロット名を入力するだけで済みます (例: Info#podVersion ではなく #podVersion)。

しかし、私が言ったように、私は afBedSheet で遊んでいるだけです。例が示すように、AppModule クラスでルートを宣言する正当な理由があるかどうか、このフレームワークで実際の生産プロジェクトを行った人から知りたいです。 .

また、私がやっていることが OK または良い場合、上記の Info クラスを次のようなものに変更するためのファセットがあるかどうか (または追加することをお勧めするかどうか) を考えています。

using afBedSheet

@Service // Assuming there is such facet to let afBedSheet discover services
class Info {

    @Route { `/info` }  // <- Route handler facet
    Text all() {
        Text.fromJson(["This application blah blah blah"])
    }

    @Route { `/info/pod` }
    Text podAll() {
        pod := Pod.of(this)
        return Text.fromPlain("$pod.name $pod.version.toStr")
    }

    @Route { `/info/pod/name` }
    Text podName() {
        Text.fromPlain(Pod.of(this).name)
    }

    @Route { `/info/pod/version` }
    Text podVersion() {
        Text.fromPlain(Pod.of(this).version.toStr)
    }

}

このようなファセットが存在しない場合は、ルート宣言を AppModule に保持する正当な理由があるに違いないと思います。それらが何であるかを知りたいと思います。

4

1 に答える 1

1

この(よく表現された質問)で、私は2つの異なるサブ質問を読んでいます:

  1. 静的メソッドを使用して BedSheet ルートを宣言しても問題ありませんか?
  2. BedSheet の Route ファセットを作成しても問題ありませんか?

2 つの質問に共通するテーマは、継続的な明確さと維持です。これは非常に個人的な「もの」になる可能性があり、ことわざの猫のように、皮をむく方法は複数あります。

とにかく、それらに個別に対処するには:


Q)。静的メソッドを使用して BedSheet ルートを宣言しても問題ありませんか?

A)。はい、大丈夫です(ただし、読み進めてください...)


Q)。BedSheet の Route ファセットを作成しても問題ありませんか?

A)。要するに、はい。長いと…

この (言い換えた) 質問が示すように、 BedSheet にIoCにも、サービスまたはルート ハンドラー メソッドを宣言するためのファセットはありません。これは主に、そのようなファセットと関連サービスがフレームワークに含めるのに十分なほど「コア」であると感じられていないためです。

特にコードベースの初心者にとっては、ルートとサービスの構成をAppModule簡単に見つけて追跡することができます。

大規模なプロジェクトでは、ファセットを介した分散型の構成により、マイナーなメンテナンスの問題が発生する可能性があります。ファセットを使用している場合、使用しているサービスを見つける唯一の方法はテキスト検索です。同じことがルートにも当てはまります。プロジェクトを理解しようとする新参者は、検索結果のさまざまなページを歩き回らなければなりません。を一瞥するだけでAppModule、同じ理解が得られます。

「できる」という言葉が意図的に選ばれているのは、クラスの命名であれディレクトリ構造であれ、十分なコーディングを行うことで、サービスとルートが論理的にグループ化され、見つけやすくなるためです。

Tales Framework には、ルートを宣言するためのファセットがありますが、 ルートの外部化 でそれらについて次のように述べています。

メソッドとともにルートをファセットとして定義するのはクールで迅速ですが、次の欠点があります。

  1. ルートがピックアップされる順序を明確に定義していません
  2. アプリが定義するすべてのルートを 1 か所で確認することはできません。

したがって、ファセットを使用してサービスとルートを宣言することは悪くありませんが、注意してください。とはいえ、 JAX-RS (Java API for RESTful Services)に似た、ファセットに基づく REST API を実装することを考えていました。

余談ですが、ファセット構成は簡単に実装できます。たとえば、@ServiceIoC サービス クラス (または mixin) に配置したというファセットがあった場合は、バインド メソッドに次の行を追加するだけです。

const class AppModule {
    static Void bind(ServiceBinder binder) {
        AppModule#.pod.types .findAll { it.hasFacet(Service#) }.each { binder.bind(it) }
    }
}

総括する:

コード ベースを単独で担当する場合、または小規模なプロジェクトに取り組んでいる場合は、ファセットを使用しても問題ありません。メンテナンスが他のユーザーと共有される場合、またはプロジェクトが重要である場合は、 @SubModuleファセットAppModuleで定義されているように、構成を単一または複数のモジュールに保持することを検討します。

于 2014-03-08T19:55:39.113 に答える