【发布时间】:2017-08-27 15:20:33
【问题描述】:
我已经对 akka-http 实现感兴趣,但作为一种反模式让我印象深刻的一件事是为所有路由、参数解析、错误处理等创建 DSL。文档中给出的例子极其微不足道。然而,我在市场上看到了一个真实产品的路线,它是一个巨大的 10k 行文件,其中包含许多层次和大量的业务逻辑。现实世界的系统必须处理传递错误参数的用户,没有正确的权限等等,所以简单的 DSL 在现实生活中迅速爆炸。对我来说,最佳解决方案是将路线完成交给演员,每个演员都有相同的 api,然后他们将做完成路线所需的事情。这将分散逻辑并启用可维护的代码,但数小时后我无法管理它。使用低级 API,我可以传递 HttpRequest 并以旧方式处理它,但这使我无法使用 DSL 中的大多数工具。那么有没有一种方法可以将一些东西传递给一个演员,使其能够在那个时候继续 DSL,处理特定于路由的东西? IE。我说的是这样的事情:
class MySlashHandler() extends Actor {
def receive = {
case ctxt: ContextOfSomeKind =>
decodeRequest {
// unmarshal with in-scope unmarshaller
entity(as[Order]) { order =>
sender ! "Order received"
}
context.stop(self)
}
}
val route =
pathEndOrSingleSlash {
get { ctxt =>
val actor = actorSystem.actorOf(Props(classOf[MySlashHandler]))
complete(actor ? ctxt)
}
}
当然,这甚至不会编译。尽管我尽了最大的努力,但我还没有找到 ContextOfSomeKind 的类型,或者一旦我进入演员内部,如何重新输入 DSL。这可能是不可能的。如果不是,我认为我不喜欢 DSL,因为它鼓励了我认为可怕的编程方法。那么低级 API 的唯一问题是访问实体编组器,但我宁愿这样做,然后在单个源文件中创建一个大型应用程序。
【问题讨论】:
-
我个人有将路由拆分为多个特征的习惯,这仅仅是因为在 IntelliJ IDEA 中无法在单个 10k 的路由文件中工作。
-
即使可能,这对我来说也是一种反模式。
-
嗯,我猜这是个人品味的问题 :) 我更喜欢可读性而不是严格遵循模式。但是,如果您找到更好的方法来组织复杂的 akka-http 路由,我将很乐意阅读它:)