gurateku
29 min readAug 2, 2018

GitHubがGraphQLを採用した理由とは?

初投稿です。稚拙な文章で至らぬところも多いですがよろしくお願いします; ;

私なりに原文(https://githubengineering.com/the-github-graphql-api/)を読み進めて日本語にしてみました。間違いやおかしいところがあればドンドン指摘をいただけるとうれしいです!

GitHub announced a public API one month after the site launched. We’ve evolved this platform through three versions, adhering to RFC standards and embracing new design patterns to provide a clear and consistent interface. We’ve often heard that our REST API was an inspiration for other companies; countless tutorials refer to our endpoints. Today, we’re excited to announce our biggest change to the API since we snubbed XML in favor of JSON: we’re making the GitHub API available through GraphQL.

GitHubはサイト(https://blog.github.com/2008-03-12-the-api/)開設の一か月後にパブリックAPIを発表した。私たちははっきりして一貫したインターフェイスを提供するために、このプラットフォームをRFC標準に準拠させ、新たなデザインパターンを受け入れ、三つのバージョンを通じて進化させてきました。

私たちはよく、REST APIが他の企業にとってインスピレーションになりうると耳に聞く。(無数のチュートリアルはエンドポイントを参照しています。)

今日、私たちがXMLを嫌い、JSONに賛成してからAPIの最大の変更を発表できたことをうれしく思います。GitHub APIをGraphQLで利用できるよう現在取り組んでいます。

GraphQL is, at its core, a specification for a data querying language. We’d like to talk a bit about GraphQL, including the problems we believe it solves and the opportunities it provides to integrators.

GraphQLはクエリ言語(問い合わせ言語)のデータの明細を表します。

ここからはGraphQLについて、解決できるはずの現在抱えてる問題点とインテグレータに与える機会について話していきます。

Why?

●なぜ始めたか

You may be wondering why we chose to start supporting GraphQL. Our API was designed to be RESTful and hypermedia-driven. We’re fortunate to have dozens of different open-source clients written in a plethora of languages. Businesses grew around these endpoints.

GraphQLのサポートを開始した理由を不思議に思う人がいるかもしれません。私たちのAPIはRESTfulでハイパーメディア主導になるよう設計されています。私たちは幸運にも多くの言語で書かれた数十種類のオープンソース クライアント(https://developer.github.com/v3/libraries/)を所有しています。ビジネスはこれらのエンドポイントを軸に成長しました。

Like most technology, REST is not perfect and has some drawbacks. Our ambition to change our API focused on solving two problems.

多くのテクノロジーと同じように、REST APIも完ぺきではなく、複数の欠点があります。

APIを変えるという私たちの野望は2つの問題の解決に注目しました。

The first was scalability. The REST API is responsible for over 60% of the requests made to our database tier. This is partly because, by its nature, hypermedia navigation requires a client to repeatedly communicate with a server so that it can get all the information it needs. Our responses were bloated and filled with all sorts of *_url hints in the JSON responses to help people continue to navigate through the API to get what they needed. Despite all the information we provided, we heard from integrators that our REST API also wasn’t very flexible. It sometimes required two or three separate calls to assemble a complete view of a resource. It seemed like our responses simultaneously sent too much data and didn’t include data that consumers needed.

① 一つ目はscalabilityです。REST APIはデータベース層に対して行われたリクエストの60%以上を処理します。これは性質上ハイパーメディアナビゲーションでは、クライアントが必要なすべての情報を所得できるように、サーバーと繰り返し通信する必要があるためです。人が必要なものをえるためにAPIを通じてナビゲート続けるためにレスポンスが膨大にになり、JSONリスポンスの*_urlヒントで埋まってしまいます。

全ての情報が与えられたにも関わらず、インテグレータはREST APIには柔軟性がないといいました。リソースの完ぺきなview(展望)を組み立てるために、2.3回の別々の呼び出しが必要ななることがありました。リスポンスが同時に大量に送信され、消費者が必要としているデータを含んでないことがったようです。

As we began to audit our endpoints in preparation for an APIv4, we encountered our second problem. We wanted to collect some meta-information about our endpoints. For example, we wanted to identify the OAuth scopes required for each endpoint. We wanted to be smarter about how our resources were paginated. We wanted assurances of type-safety for user-supplied parameters. We wanted to generate documentation from our code. We wanted to generate clients instead of manually supplying patches to our Octokit suite. We studied a variety of API specifications built to make some of this easier, but we found that none of the standards totally matched our requirements.

② APIv4に備えてエンドポイントを監査し始めると、私たちは二つ目の問題に遭遇しました。私たちはエンドポイントに関するメタデータを集めることを望んでいました。

例えば、各エンドポイントに必要なOAuth Scopeを特定する必要がありました。

私たちはリソースをどのようにページネーションするかもっとスマートになる必要があったのです。私たちはユーザー提供のパラメータのための安全性の保障が必要でした。私たちはコードからドキュメンテーションを作りたかったのです。私たちはOctokit suiteに手動でパッチを提供するのではなくクライアントを作成したかったのです。これを簡単にするために様々な構築されたAPI specification(明細)を検討しましたが、どのスタンダードも私たちの要求にはマッチしませんでした。

And then we learned about GraphQL.

そこでGraph QLを学び始めたのです。

●切り替え

GraphQL is a querying language developed by Facebook over the course of several years. In essence, you construct your request by defining the resources you want. You send this via a POST to a server, and the response matches the format of your request.

Graph QLは数年でFace bookに開発されたクエリ言語です。要するに、必要なリソースを定義してリクエストを構築します。あなたがこれをPOSTを通じてサーバーに送信すると、レスポンスはリクエストのフォーマットと一致します。

For example, say you wanted to fetch just a few attributes off of a user. Your GraphQL query might look like this:

例えば、ユーザーからほんのわずかな属性を取り出したいとすると、GraphQLはこうなります。

{
viewer{
login
bio
location
isBountyHunter
}
}

And the response back might look like this:

それで、レスポンスはこうなります。

{
"data":{
"viewer":{
"login":"octocat",
"bio":"I've been around the world , from to the Bay .",
"location":"San Francisco, CA",
"isBountryHunter":true
}
}
}

JSONリスポンスのキーと値が、クエリ文字列内の用語と一致することがわかります。

もっと複雑なことを望むならこんなことはどうでしょう。

あなたがスターを押したレポジトリの数を知りたいとしましょう。

あなたがスターの総数と同様に、フォークの総数、ウオッチャーの総数、open issueの総数、レポジトリの名前を得たいとしましょう。クエリはこうなるでしょう。

{
viewer {
login
starredRepositories{
totalCount
}
repositories(first:3){
edges{
node{
name
stargazers{
totalCount
}
forks{
totalCount
}
watchers{
totalCount
}
issues(states:[open]){
totalCount
}
}
}
}
}
}

APIからのレスポンスはこうなるでしょう

{
"data":{
"viewer":{
"login":"octocat",
"starrerRepositories":{
"totalCount":131
},
"repositories":{
"edges":[
{
"node":{
"name":"octokit.rb",
"stargazers":{
"totalCount":17
},
"forks":{
"totalCount":3
},
"watchers":{
"totalCount":3
},
"issues":{
"totalCount":1
}
}
},
{
"node":{
"name":octokit.objc",
"stargazers":{
"totalCount":2
},
"forks":{
"totalCount":0
},
"watchers":{
"totalCount":1
},
"issues":{
"totalCount":10
}
}
},
{
"node":{
"name":"octokit.net",
"stargazers":{
"totalCount":19
},
"forks":{
"totalCount":7
},
"watchers":{
"totalCount":3
},
"issues"{
"totalCount"4
}
}
}
]
}
}
}
}

You just made one request to fetch all the data you wanted.

This type of design enables clients where smaller payload sizes are essential. For example, a mobile app could simplify its requests by only asking for the data it needs. This enables new possibilities and workflows that are freed from the limitations of downloading and parsing massive JSON blobs.

Query analysis is something that we’re also exploring with. Based on the resources that are requested, we can start providing more intelligent information to clients. For example, say you’ve made the following request:

必要なすべてのデータを所得するリクエストを一回作成しました。

このタイプのデザインは、より小さいpayload サイズが必要なクライアントを有効にします。例えば、必要なデータを尋ねるだけでリクエストを簡略化できます。これは大規模なJSON BLOBのダウンロードと構文解析の制限から解放される新たな可能性とワークフローの可能性を導きます。

クエリ解析は、私たちが探すときにつかうものです。リクエストされたリソースに基づいて、より、スマートな情報をクライアントに提供できます。例えば、次のようにリクエストしたとします。

{
viewer{
login
email
}
}

Before executing the request, the GraphQL server notes that you’re trying to get the email field. If your client is misconfigured, a response back from our server might look like this:

リクエストを実行する前に、GraphQLサーバーはemai領域(フィールド)を所得しようとしていることに気が付きます。クライアントが間違って設定されていると、レスポンスは次のようになります。

{
"data":{
"viewer":{
"login":"octocat"
}
},
"errors":[
{
"message": "Your token has not been granted the required scopes to execute this query . The 'email' field requires one of the following scopes:['user'],but your token has only been granted the:['gist'] scopes . Please modify your token's scopes at http://github.com/settings/tokens."

This could be beneficial for users concerned about the OAuth scopes required by integrators. Insight into the scopes required could ensure that only the appropriate types are being requested.

これはインテグレーターに要求されているOAuth scopesに関心があるユーザーにとって有益なものです。Scopeが要求されているかへの洞察は適切なタイプのみがリクエストされているか確認できます。

●その他の機能

There are several other features of GraphQL that we hope to make available to clients, such as:

・The ability to batch requests, where you can define dependencies between two separate queries and fetch data efficiently.

・The ability to create subscriptions, where your client can receive new data when it becomes available.

・The ability to defer data, where you choose to mark a part of your response as time-insensitive.

他にもクライアントを便利にする他の機能がGraphQLにはあります。

・二つの別々のクエリ間の依存関係を定義し、効率的にデータを所得できる要求をバッチ処理する能力

・クライアントが利用可能になった時に新しいデータを受け取るサブスクリプションを作成する能力

・レスポンスの一部を time incentives(時間誘因?)としてマークする、データを遅延させる能力

●schemaの定義

In order to determine if GraphQL really was a technology we wanted to embrace, we formed a small team within the broader Platform organization and went looking for a feature on the site we wanted to build using GraphQL. We decided that implementing emoji reactions on comments was concise enough to try and port to GraphQL. Choosing a subset of the site to power with GraphQL required us to model a complete workflow and focus on building the new objects and types that defined our GraphQL schema. For example, we started by constructing a user in our schema, moved on to a repository, and then expanded to issues within a repository. Over time, we grew the schema to encapsulate all the actions necessary for modeling reactions.

We found implementing a GraphQL server to be very straightforward. The Spec is clearly written and succinctly describes the behaviors of various parts of a schema. GraphQL has a type system that forces the server to be unambiguous about requests it receives and responses it produces. You define a schema, describing the objects that represent your resources, fields on those objects, and the connections between various objects. For example, a Repository object has a non-null String field for the name. A repository also has watchers, which is a connection to another non-nullable object, User.

Although the initial team exploring GraphQL worked mostly on the backend, we had several allies on the frontend who were also interested in GraphQL, and, specifically, moving parts of GitHub to use Relay. They too were seeking better ways to access user data and present it more efficiently on the website. We began to work together to continue finding portions of the site that would be easy to communicate with via our nascent GraphQL schema. We decided to begin transforming some of our social features, such as the profile page, the stars counter, and the ability to watch repositories. These initial explorations paved the way to placing GraphQL in production. (That’s right! We’ve been running GraphQL in production for some time now.) As time went on, we began to get a bit more ambitious: we ported over some of the Git commit history pages to GraphQL and used Scientist to identify any potential discrepancies.

Drawing off our experiences in supporting the REST API, we worked quickly to implement our existing services to work with GraphQL. This included setting up logging requests and reporting exceptions, OAuth and AuthZ access, rate limiting, and providing helpful error responses. We tested our schema to ensure that every part of was documented and we wrote linters to ensure that our naming structure was standardized.

GraphQLが本当に我々に必要なテクノロジーか決めるために、幅広いプラットフォーム組織の中で小さいチームを作り、GraphQLを用いて作りたいサイトの特徴を調べました。コメントに絵文字を実装することはGrapahQLにトライするには簡単すぎると思いました。GraphQLを活用するサイトのサブセットを選択するには、完全なワークフローをモデル化し、GraphQL schemaを定義した新しいオブジェクトとタイプを構築することに焦点を当てる必要がありました。たとえば、まずschemaでユーザーを作成し、リポジトリに移動した後、リポジトリ内の問題を展開します。時間が経つと、モデル化のリアクションに必要なすべてのアクションをカプセル化(要約)するschemaに成長しました。

私たちは、GraphQLサーバの実装が非常に簡単であることを発見しました。Spec(https://facebook.github.io/graphql/)は、schemaのさまざまな部分の動作を明確に記述し、簡潔に記述しています。GraphQLには、受け取った要求とそれが生成する応答についてサーバーに明白な情報を与える型のシステムがあります。schemaを定義して、リソースを表すオブジェクト、それらのオブジェクトのフィールド、およびさまざまなオブジェクト間の接続を記述します。たとえば、レポジトリオブジェクトはnameとしてnon-null string領域(field)を 持っています。レポジトリはまたもう一つのnon-nullable オブジェクトであるuserに関係があるwatchersも持っています。

GraphQLを研究している最初のチームは主にバックエンドで働いていましたが、フロントエンドにはGraphQLにも興味があった数名の仲間がいました。具体的にはRelay(https://facebook.github.io/relay/)を使用するGitHubの可動部分に興味があったようです。彼らも、ユーザーデータにアクセスしてより効果的にWebサイトに提示するためのより良い方法を模索していました。我々は、私たちの初期GraphQL schemaを介して通信しやすいサイトの部分を見つけるために協力し始めました。プロファイルページ、スターカウンター、リポジトリを見る機能など、ソーシャル機能の一部を変え始めることにしました。これらの初期の調査は、GraphQLを稼働させる方法を築きました。(これは間違いありません)今度はGraphQLを当面の間運用しています。時間が経つにつれ、私たちはもう少し野心的になり始めました。Gitのコミット履歴ページの一部をGraphQLに移植し、Scientist(https://githubengineering.com/scientist/)を使って潜在的な不一致を特定しました。

REST APIをサポートした経験を活かし、GraphQLを動く既存のサービスを実装するために迅速に働きました。これには、ログの設定と例外の報告、OAuthとAuthZアクセス、レート制限、および有用なエラー応答の提供が含まれていました。私たちはschemaをテストして、すべての部分が文書化されていることを確認し、私たちのnaming structure(命名構造)が標準化されていることを確認するためにlintersを書きました。

●オープンソース

We work primarily in Ruby, and we were grateful for the existing gems supporting GraphQL. We used the rmosolgo/graphql-ruby gem to implement the entirety of our schema. We also incorporated the Shopify/graphql-batch gem to ensure that multiple records and relationships were fetched efficiently.

Our frontend and backend engineers were also able to contribute to these gems as we experimented with them. We’re thankful to the maintainers for their very quick work in accepting our patches. To that end, we’d like to humbly offer a couple of our own open source projects:

・github/graphql-client, a client that can be integrated into Rails for rendering GraphQL-backed views.

・github/github-graphql-rails-example, a small app built with Rails that demonstrates how you might interact with our GraphQL schema.

We’re going to continue to extract more parts of our system that we’ve developed internally and release them as open source software, such as our loaders that efficiently batch ActiveRecord requests.

私たちは主にRubyで作業しており、GraphQLをサポートする既存のgemに感謝しています。rmosolgo / graphql-ruby(https://github.com/rmosolgo/graphql-ruby) gem を使用して、schema全体を実装しました。また、Shopify / graphql-batch(https://github.com/Shopify/graphql-batch)gemを組み込んで、複数のレコードと関係が効率的に取得されるようにしました。

フロントエンドとバックエンドのエンジニアは、これらのgemを実験的に貢献しました。我々は、パッチを適用する際の非常に迅速な作業をしてくれるメンテナーに感謝しています。そのために、私たち自身のオープンソースプロジェクトのいくつかを謙虚に提供したいと思います。

・github / graphql-client(https://github.com/github/graphql-client) .Railsに統合され、GraphQLに裏付けされたビューをレンダリング(描画?)するクライアント。

・github / github-graphql-rails-example(https://github.com/github/github-graphql-rails-example)は、Railsで構築され、GraphQL schemaとのかかわり方を示す小さなアプリケーションです。

ActiveRecordのリクエストを効率的にバッチ処理する(loder)ローダーなど、オープンソースソフトウェアとして内部で開発したシステムの多くを引き続き展開します。

●展望

The move to GraphQL marks a larger shift in our Platform strategy to be more transparent and more flexible. Over the next year, we’re going to keep iterating on our schema to bring it out of Early Access and into a wider production readiness.

Since our application engineers are using the same GraphQL platform that we’re making available to our integrators, this provides us with the opportunity to ship UI features in conjunction with API access. Our new Projects feature is a good example of this: the UI on the site is powered by GraphQL, and you can already use the feature programmatically. Using GraphQL on the frontend and backend eliminates the gap between what we release and what you can consume. We really look forward to making more of these simultaneous releases.

GraphQL represents a massive leap forward for API development. Type safety, introspection, generated documentation, and predictable responses benefit both the maintainers and consumers of our platform. We’re looking forward to our new era of a GraphQL-backed platform, and we hope that you do, too!

If you’d like to get started with GraphQL — including our new GraphQL Explorer that lets you make :sparkles:live queries:sparkles:, check out our developer documentation!

GraphQLへの移行は、より透明性と柔軟性を高めるために、当社のプラットフォーム戦略に大きな転換をもたらしました。翌年には、早期アクセスからより幅広い生産準備態勢へと移行するために、schemaに取り組み続けます。

アプリケーションエンジニアは、インテグレータが利用できるGraphQLプラットフォームと同じものを使用しているため、APIアクセスと連携して UI機能を提供する機会があります。私たちの新しいプロジェクト機能は良い例です:サイト上のUIはGraphQLによって動いており、既にこの機能をプログラムで使用することができます。フロントエンドとバックエンドでGraphQLを使用すると、リリースしたものと消費するものとの間のギャップがなくなります。我々は、これらの同時体験が増えることを楽しみにしています。

GraphQLは、API開発の大きな飛躍を表しています。安全性、introspection(イントロスペクション)、生成されたドキュメント、予測可能なレスポンスは、私たちのプラットフォームのメンテナーとコンシューマーの両方に利益をもたらします。私たちは、GraphQLに裏打ちされたプラットフォームの新しい時代を楽しみにしています。

GraphQL Explorerを含むGraphQLを使い始める場合は、開発者のドキュメントをチェックしてください!(https://developer.github.com/v4/)

以上が翻訳になります。

ここまで読んでいただきありがとうございました!!

gurateku

英語の記事を翻訳したり、ゲームの記事を書いたり。世界大会に出るほどのゲーム好きでした。