1

我正在玩 Fantom 的 afBedSheet 框架,在它的文档中,例子是……

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))
  }
}
...

当添加的路由越来越多时,尤其是当路由处理程序来自不同的类时,上面的contributeRoutes 方法开始变得难以阅读和维护。

我这样做的方式不同:在每个 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 定义和处理程序映射更接近实现类。我希望这会使服务/路由更易于维护,但我不确定这是一个好主意还是坏主意。我发现这样做的好处是

  • 如果我向一个类添加路由处理程序方法,我在同一个类上声明路由
  • 由于路由处理程序方法是同一个类的一部分,因此我只需要输入插槽名称(例如#podVersion 而不是 Info#podVersion),这对我来说似乎更容易阅读。

但正如我所说,我只是在玩 afBedSheet,如果有充分的理由在 AppModule 类中声明路由,我想从使用此框架完成实际生产项目的人那里知道,如示例所示.

此外,如果我正在做的事情是好的或好的,我想知道是否有(或者添加是否是一个好主意)方面将我上面的 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 facets 吗?

这两个问题的共同主题是持续清晰和维护。这可能是一件非常私人的“事情”,就像众所周知的猫一样,剥皮的方法不止一种。

无论如何,单独解决它们:


问)。可以使用静态方法声明 BedSheet 路由吗?

一种)。是的,这很好(但请继续阅读......)


问)。可以为 BedSheet 创建 Route facets 吗?

一种)。简而言之,是的。在长...

正如这个(解释的)问题所暗示的那样 - BedSheetIoC都没有任何用于声明服务或路由处理程序方法的方面。这主要是因为人们认为这些方面和相关服务不够“核心”,无法包含在框架中。

保持路由和服务的配置AppModule很容易找到和跟踪 - 特别是对于代码库的新手。

在较大的项目中,通过方面的分散配置可能会导致轻微的维护问题。因为如果使用方面,发现您拥有哪些服务的唯一方法是通过文本搜索。这同样适用于路线。试图理解该项目的新人将不得不浏览搜索结果的各个页面。而仅仅看一眼AppModule就预示着同样的理解。

故意选择“ can ”这个词是因为只要有足够的编码勤奋,无论是类命名还是目录结构,服务和路由都会在逻辑上分组并且很容易找到。

Tales 框架有声明路由的方面,但在Externalizing Routes中有这样的说法 :

将路由和方法定义为构面既酷又快,但它有以下缺点:

  1. 没有明确定义路线的接载顺序
  2. 您无法在一处查看您的应用定义的所有路线。

所以用 facet 声明服务和路由也不错,要小心。也就是说,我一直在考虑实现一个基于方面的 REST API,类似于JAX-RS(用于 RESTful 服务的 Java API)!

顺便说一句,构面配置实现起来很简单。例如,如果您@Service在 IoC 服务类(或 mixins)上放置了一个名为 facet,那么您只需将以下行添加到您的绑定方法中:

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

总结一下:

如果您要单独负责一个代码库,或者正在处理一个较小的项目,那么使用构面就可以了。如果维护是由其他人共享的,或者如果项目是不平凡的,那么我会考虑将配置保存在单个AppModule或多个模块中,如@SubModule方面所定义。

于 2014-03-08T19:55:39.113 回答