12

EDIT
Slow compile times are now largely mitigated by sub project enabled builds, a huge win.

Have switched away from Play's built-in asset generators (i.e. for Coffeescript and LESS) and moved over to 3rd party Grunt JS; now code changes during incremental builds are limited only by scalac compilation time and not also the overhead of Play's relatively slow assets generation.

ORIGINAL
Overall pretty happy with Play 2.1 Scala (the 9/14/2012 release, just prior to switch to Scala 2.10); however, there are some development pain points:

1) routing: on route change, one's entire route-controller structure can be re-compiled: not good.

2) REST appears to not be directly supported since route POST /foo/bar/:id conflicts with DELETE /foo/bar/:id; i.e. route paths must be unique, presumably for reverse routing.

3) views: with a scala.html file per foo action, the file count grows quickly, which means slower build times, more to compile; generics not supported and blind coding due to lack of IDE support (of course no scala template engine has IDE support to-date, AFAIK) are particularly tough areas.

4) incremental builds work, but nothing in the process can be called "snappy", even a simple change to a scala.html file will in reality take @2 seconds, which is a long time when you're wanting that instant code-change browser-refresh feedback cycle.

I know some of the above issues are being worked on by Play devs, and slow-ish build times are also directly related to sbt, scala version, and one's own code structure. Again, overall, Play has been an enjoyable development experience. This is about pain, however, and I want to know what Lift brings to the table in this regard...

Lift seems to take a different approach. Do Lift-ers suffer from the above items? Assume not since MVC, Lift is not, and the xml-style snippets approach may not incur the same compile time hit that some of Play's behind the scenes build machinery does.

What are the pain points in Lift?

4

2 回答 2

24

作为一个已经使用 Lift 大约 2 年的人,我个人的观点:

1)路由:在路由改变时,一个人的整个路由控制器结构可以重新编译:不好

有了 Lift,就没有路由。我认为最接近的相关概念是SiteMap,而且我个人从未遇到过与它的编译相关的任何问题。

2) 似乎不直接支持 REST,因为路由 POST /foo/bar/:id 与 DELETE /foo/bar/:id 冲突;即路由路径必须是唯一的,大概用于反向路由。

用 Lift 做了很多 REST,我可以告诉你,这绝对不是问题。Lift 的 REST 支持非常好,并且基于 Scala 的模式匹配,它为您提供了一种非常强大、类型安全的方式来设计您的 Web 服务

3) 视图:每个 foo 操作都有一个 scala.html 文件,文件数量快速增长,这意味着构建时间更慢,编译更多;不支持泛型和由于缺乏 IDE 支持而导致的盲目编码(当然,迄今为止没有 scala 模板引擎支持 IDE,AFAIK)是特别困难的领域。

使用 Lift,HTML 代码只是 HTML(没有特殊符号),所以它根本不考虑编译时间。HTML,称为模板,由转换 NodeSeq => NodeSeq 的片段处理。这听起来可能很复杂,但 Lift 有一个 DSL 可以让它变得非常简单。想要将用户名添加到跨度?如果它看起来像:

<span id="user-name">User name goes here</span>

您的代码段中会有这样的代码:

"#user-name *" #> user.name

您还可以在模板中重复项目,例如表格或列表:


<table id="table"><tr><td class="name"></td><td class="value"></td></tr></table>

应用了这个:

val tuples = List(("Lift", "Is great"), ("Other web frameworks", "Eh"))
"#table" #> {
  "tr" #> {
     tuples map { case(name, value) =>
       ".name" #> name &
       ".value" #> value
     }
  }
}

将产生一个有 2 行的表,每行代表列表中元素的名称/值。

我认为这确实是 Lift 的最大优势之一。模板只是 HTML,不包含任何符号或标记。您可以按原样使用您的设计师组合的内容,甚至让他们直接访问以进行更新(在某些情况下无论如何)。

另一方面,代码片段是纯 Scala,而不是某种模板语言。无论你用 Scala 能做什么,你都可以在 Snippet 中做,这一切都由编译器检查。

也可以(并且鼓励)在多个页面上使用 Snippet,因此您不必每页都需要一个 Snippet。您甚至可以将站点地图配置为对多个页面使用相同的模板,并根据请求将类型安全参数传递给页面包含的片段。

4)增量构建工作,但过程中没有任何东西可以称为“快速”,即使是对 scala.html 文件的简单更改实际上也需要@2秒,当您想要即时代码时,这是很长时间 -更改浏览器刷新反馈周期。

我不认为 Lift 在这方面会造成伤害,但不幸的是它也没有多大帮助。很高兴听到 Scala 2.10 将包括这方面的一些改进,因为我认为它们必须来自编译器。

为了回答一些电梯批评......

需要高级Scala吗?不,我不相信它是。这有点主观,但您可以从我发布的内容中看到,创建模板并将片段应用到它非常简单。您必须熟悉“地图”之类的概念,但如果您不熟悉,那么使用 Scala Web 框架有什么好处呢?关于您将使用的一些方法的 Scala 文档对于初学者来说可能看起来有点毛骨悚然,但与 Scala 集合非常相似,它的复杂性使库更易于使用。对于刚接触 Scala 的人来说,他们可能最好遵循Wiki the CookbookSimply Lift中的示例,而不是 API 文档,但我认为这是 Scala 的习惯用法,而不是 Lift 的习惯。

您是否必须在“控制器”中混合标记?绝对不。我将回顾一下 Lift 不是 MVC 框架的事实,并假设发帖者正在谈论 Snippets。从 Snippet 输出 HTML 绝不是必要的,而且在大多数情况下是完全反模式。像我发布的 CSS 选择器允许您将所有 HTML 保存在模板文件中,并将所有逻辑保存在 Snippets 中。

Lift 是否需要太多状态?这是我遇到的第一个投诉,而且我从未见过它伴随着现实世界的问题。事实是,使用 Lift,您可以选择是否要成为有状态的。如果您正在使用 Lift 编写 Web 服务,并且您不希望在访问您的 URL 时创建 Session,您可以使用 LiftRules.statelessDispatchTable 注册该服务。这符合 Lift 的哲学,即状态既无好坏之分,但满足某些需求是必要的,而对另一些需求则不是必需的。重要的是要明确何时使用它并让开发人员决定。如果您对此感兴趣,David Pollack 有更好的解释

于 2012-11-15T18:46:22.403 回答
8

首先,我相信解决您的一些观点是公平的:

  • 第 1 点和第 4 点:Scala 2.10 在编译速度上有相关的提升,这应该不再是问题了
  • On 2:从未见过与 GET/POST 有任何冲突,但我没有尝试 DELETE。可能是 Play 或您的代码中的错误(打开一个新问题,包括完整的路线定义,包括方法)
  • 第 3 点:IntelliJ 12 支持 Play 2。AFAIK 模板支持泛型(如果泛型是指传递 X[A] 或 A 类型的泛型参数)

我的电梯经验是几年前的,所以有些观点可能不适用:

  • 代码库和语法(来自 Lift 的源代码)实际上是高级 Scala。这使得刚开始使用 Scala 的人在查看框架代码时很难掌握代码在做什么。
  • 视图优先的方法是一团糟,在“控制器”中混合代码(返回 HTML),它打破了关注点的分离并使后续代码变得更加困难

但最重要的是:

  • 有状态的。自从我离开 Java EE 世界并开始使用无状态服务器以来,已经消失的问题数量之多令人吃惊。不必担心会话和其他混乱似乎无关紧要,但它确实有所作为。特别是在云计算时代:)
于 2012-11-15T10:01:22.000 回答