Crystal 分享一个极简 API 框架——Runcobo

ThxFly · 2020年09月24日 · 最后由 itomato 回复于 2020年10月20日 · 3286 次阅读

开发背景

Crystal 目前最火的有三个框架

  1. Kemal: Sinatra on Crystal
  2. Amber: Rails on Crystal
  3. Lucky:Crystal 活跃程度最高的一门框架,开发思想为“更少的 bug”

我试用了以上三种,分享些个人的感受:

  • Kemal 用来做些小项目可以,但商用的话太难,毕竟 Sinatra 的底子给了它一个黑暗的未来;
  • Amber 用起来行云流水,模仿 Rails 的确很像,应该能吸引一票的 Rails 程序员。但除了 Laravel,其他语言模仿 Rails 的都哑火了,也许是因为 Rails 太过优秀,导致模仿者难以超越前作;
  • Lucky 更多是面向 Web 开发,这个框架提出的概念有些多。作为前后端分离的践行者,个人更想要一款面向 API 开发的微框架,去掉那些涉及网页开发的概念。

对以上框架不太满意,而这时公司又有 KPI 指标,于是乎我散失了几个周末不打机的美好时光,开发了以公司名字"云康宝"命名的Runcobo 框架.

如果你听过买过或用过云康宝体脂秤与共享秤,那你已自动成为本框架的终身 VIP 用户

第一段代码

require "runcobo"

class HelloWorld < BaseAction
  get "/hello_world"

  call do
    render_plain "Hello World"
  end
end

Runcobo.start

先引入库,然后定义一个 Action,在 Action 中声明接口路径,声明需要渲染”Hello World“,最后启动服务器。

乍一看没啥亮眼的,比不上 Sinatra 的三行情书短小精悍。

但故事才刚刚开始......

控制器

  1. 为了避免单个控制器代码过多,采用一个动作一个类的方式(赤裸裸抄袭前文提到的 Lucky 框架)
  2. 本着微框架的初心,路由不应该单独定义在一个文件里,故路由作为声明语句,写在对应的动作中
  3. 本着约定大于配置的准则,与最少惊讶原则,这里只约定了视图所在的目录"src/views/", 布局所在的目录"src/views/layouts/"
  4. 参数先声明,后使用,使用简单且类型安全
  5. 支持过滤器
  6. 支持多种响应格式,纯文本、HTML 与 JSON
  7. 渲染 json 视图采用 jbuilder,Rails 自带的 JSON 引擎,Runcobo 也将它带来了。

稍复杂的代码

class Books::Index < BaseAction
  get "/books"
  query NamedTuple(author: String)
  call do
    books = Book.where(author: params[:author])
    render_jbuilder "books/index"
  end
end
json.array! "books", books do |json, book|
  json.book_id      book.id
  json.author       book.author
  json.name         book.name
  json.published_at book.published_at
end

参数设计

作为一门编译语言搭建的 API 框架,理应参数类型安全。Runcobo 采用参数声明的方式来进行参数解析,从而保证类型安全。与 Kemal、Amber、Lucky 相比,自认为 Runcobo 的参数设计还是比较漂亮的。

URL 类型安全

url NamedTuple(a: String, b: Int32?, c: Bool)

查询参数类型安全

query NamedTuple(a: String, b: Int32?, c: Bool)

表单参数类型安全

form NamedTuple(a: String, b: Int32?, c: Bool)

JSON 参数类型安全

json NamedTuple(a: String, b: Int32?, c: Bool, d: NamedTuple(a: String, b: Int32), e: Array(Int32))

调用方式

params[:a] + params[:b].to_s + params[:d][:a]

如你所见,参数支持嵌套对象、嵌套数组、支持可空,使用上也与 Rails 的参数大致相同,最大的不同便是编译期便确定了参数的类型。Runcobo 采用了宏魔法,使得参数在控制器的展现形式为命名元祖的形式,声明采用命名元组,使用的也是命名元组。(注:命名元组是一种固定大小,不可变的,已知键名及其类型、已知值类型的键值对)

我们公司的使用情况

因为需要保证源码安全,需静态编译,目前我司已在分发给第三方定制客户的服务器 SDK(镜像包)使用了该框架。

总结

  • 如果你喜欢 Crystal 的岁月静好,编译执行与类型安全,那你一定会喜欢 Runcobo;
  • 如果你想像书写接口文档那样书写 API 代码,那你一定会喜欢 Runcobo;
  • 如果你是处女座,享受设计的一致性,那你一定会喜欢 Runcobo;

项目已经发布 1.0.0 版本,如果有想要优化的地方,等你成为贡献者与参与者! 项目地址 https://github.com/runcobo/runcobo/ 欢迎 star

更多文档请查看 https://runcobo.github.io/docs/ ,需科学上网

夜已深,未完待续........

url -> path

另 NamedTuple 可以做一个 alias 如 Param

🆒 crystal 啥时候 1.0

所以 Crystal 都已经已经用于生产了?

crystal 有靠谱的数据库连接池么

pynix 回复

好,晚点处理下

lidashuang 回复

官方已经被好多人催了,目前正在整合 API,我预计到 2021 年 6 月前能有 1.0 preview 版本。对 windows 的支持已确认被放到 1.0 之后实现。

killernova 回复

没,不过毕竟编译语言,改起来也快。Ruby 的底子,阅读代码不会费力。

steve 回复

连接池用官方的库。若说靠谱的 ORM,目前还在群雄逐鹿的状态。

@ThxFly orm 性能都不行,压测一下都获取不到数据库连接

ThxFly 回复

windows 支持不是说要在 1.0 之前的嘛,毕竟 windows 支持可能需要大量抽象必然会导致 API 修改。

pynix 回复

你那说法是 1 月份社区有人发帖建议官方 1.0 之后再支持 windows,核心开发者的说辞。https://forum.crystal-lang.org/t/when-crystal-lang-1-x-will-be-released/1563

3 月份正式的官方文章说了 windows 支持可以等 1.0 之后再实现。https://crystal-lang.org/2020/03/03/towards-crystal-1.0.html

ThxFly 回复

这样 1.0 之后还会有大改动吧。。

@ThxFly 为啥 kemal 有个黑暗的未来?

steve 回复

sinatra 在 Ruby 社区被 Rails 吊打,模仿 sinatra 的 kemal 想来很难超越 rails,且从目前看,kemal 作者都不怎么维护 kemal 了。

@ThxFly 小项目 sinatra 还挺好用的

ThxFly 回复

应该有一个模仿 Roda 的框架

需要 登录 后方可回复, 如果你还没有账号请 注册新账号