GraphQL的推荐
这篇文章是SmartDrive Advent Calendar 2017的第四天的文章。
大家好,我是在SmartDrive担任后端工程师的@ryota-koganezawa。接下来我将会谈谈关于我们即将发布的产品中使用的GraphQL(ruby)和各种插件。
同时,我会尽量简洁地介绍,如果你想了解更多细节,请参考其他文章。
我主要希望谈论以下内容。
-
- GraphQLとは?
-
- GraphQLを採用した理由
-
- GraphQL-rubyのCacheにおけるTips
-
- GraphQL-rubyのN+1対応
-
- GraphQLのAPIドキュメント
-
- インターフェイス
-
- 感想
- おわりに
GraphQL是什么?
-
- 2012年にFacebookが開発、2015年7月にRFCドラフト案を公開
-
- クライアント・サーバアプリケーション向けのデータモデリング記述のためのクエリ言語
- 詳細はこちらをご覧ください。
选择使用GraphQL的原因
很常有提到的引入GraphQL的好处。
-
- 階層構造を備えたクエリ構造
-
- ビュー要求の記述しやすさ
- 強力な型システム…etc
我认为还有其他的原因,而不仅仅是等待。
首先,就我目前的情况来说…
-
- 新規サービス開発において、モデリングだけがFixした
-
- フロント実装(デザイン含め)がなかなか定まらない。且つ変更される可能性大
ステークホルダーが多く、仕様が局所的にFixされていく。
つまり、バックエンド側は柔軟に設計し、それなりの変更要求に耐えられる実装にしなくてはならない
在谈到灵活的设计时,提高抽象度并遵循单一责任原则…反转依赖原则…接口隔离原则…等等等等各种实践,我认为都有一定的存在。但是,在『建模已经相对固定』的情况下,我没有想到适合推进后端开发的设计模式。或者,可以为所有资源准备符合RESTful API的端点…
在这个时候,Graphql是我们命中注定的相遇。我们提供了适用于层次结构化模型集合的终端,让您自由使用,无需担心这边的任务,可以专注于其他任务、项目和团队构建。虽然只是后端,实际上引入的成本(包括学习成本)只需1至2天。另外,因为在同一终端(同一方法)接收query和mutation让我有些犹豫,所以我们这次只采用了query。
GraphQL-ruby缓存的技巧
关于缓存相关的内容,我们参考了GitHub员工Marc-André的文章。
由于解析查询(query)需要一些成本(取决于查询的大小),所以这里提到了应该将其缓存起来。
我们在参考的文章中稍微修改了一下代码,以下是示例代码。
variables = ensure_hash(params[:variables]
result = Schema.execute(document: document, variables: variables)
# Caching GraphQL queries with GraphQL-ruby and Rails.
# @see: github staff(Marc-André) http://mgiroux.me/2016/graphql-query-caching-with-rails/
def document
::Rails.cache.fetch(cache_key, expires_in: EXPIRES_IN) do
GraphQL.parse(params[:query])
end
end
# Handle form data, JSON body, or a blank value.
def ensure_hash(ambiguous_param)
case ambiguous_param
when String
if ambiguous_param.present?
ensure_hash(JSON.parse(ambiguous_param))
else
{}
end
when Hash, ActionController::Parameters
ambiguous_param
when nil
{}
else
raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
end
end
GraphQL-ruby的N+1解决方案
在引入GraphQL时可能会有一个担忧,即N+1问题。
作为解决方法,我们引入了graphql-batch。
在README.md中只列出了一个加载器,但实际上有两种模式可供选择,并且都可以进行自定义。以下是这两种模式的示例。
初期化時にモデルを渡し、perform時にWhere句の条件を渡すパターン
record loader
初期化時にモデルを渡し、perform時にassociationを渡すパターン
association loader
GraphQL的API文档
作为API文档,我认为GraphiQL是唯一选择。它既可用于调试,还可以作为API文档服务器,非常出色。有时也被称为GraphiQL IDE。
按照README.md中的指示挂载GraphiQL,访问http://localhost:8080/graphiql,将显示用于调试执行查询的API控制台。
就模式定义而言,似乎在启动API控制台时从app/graphql/types目录下加载了各种类型,并显示了字段信息等。
只需将此URL告知前端开发人员,就可以参考模式定义并进行调试开发。
界面 (jiè
在Ruby on Rails中,有一种更加DRY(Don’t Repeat Yourself)的编写方式,即通过使用接口(GraphQL::InterfaceType)来实现。通过定义一个接口并通过GraphQL::ObjectType继承该接口,就不再需要重复定义相同的字段了。
实施样本
::Types::ActiveRecordInterface = GraphQL::InterfaceType.define do
name 'ActiveRecordInterface'
description 'ActiveRecordInterface'
field :id, !types.Int
field :updated_at, !types.String
field :created_at, !types.String
end
::Types::HogeType = GraphQL::ObjectType.define do
interfaces [::Types::ActiveRecordInterface] # ここで共通フィールドとして読み込む
name 'Hoge'
description 'Hoge'
field :code, !types.String
field :name, !types.String
end
对于GraphQL::InterfaceType,我认为这篇文章非常有参考价值。
触动
由于学习成本低且有丰富的插件等可供选择,因此实际的导入并不困难。由于即将开始前端开发,我们希望团队能够在总结前端技巧的同时评估GraphQL的可行性。
最后
SmartDrive正在积极开展后端工程师的招聘活动。
此外,我们也正在大力招募其他各类工程师。如果您感兴趣,请务必申请!