InsideFrontEnd 参加レポート2(JsonSchema編)

InsideFrontEnd 参加レポート2(JsonSchema編)

はじめに。

2017/02/25に開催されたInsideFrontEndの参加レポートになります。
本当投稿で2つ目となります。
前回の投稿はこちらの記事を参照下さい。
http://takahiro-fujii.hatenablog.com/entry/2017/02/28/222958

レポート : JSON Schema in Web Frontend

www.slideshare.net

今回はYahooの穴井さんのセッションのレポートをさせていただきます。

お題はJson Schemaの話です。今回、Json Schemaのケーススタディが聞けたのは非常に収穫でした。
Json Schemaの話はあちこちで出ていますが、
実は"実際にこういう風に使っている"というケーススタディの共有は、まだあまりないように感じます。

今回のセッションでは、リッチラボというyahooからスピンアウトした
リッチ広告を提供する企業(リッチラボ)におけるJson Schemaの活用法についてです。

richlab.co.jp

主なトピックについて

Json Schema / Json Hyper Schemaの活用
FrontEndとBackEnd APIの意思疎通
入力フォームについて
(他にもシステム構成についての説明などもありました。)

Json Schema / Json Hyper Schemaの活用について

FroneEnd App <-> BackEnd App 間で、Json Hyper Schemaを活用しているということでした。

Json Hyper Schemaって??

こちらをみて頂くと記載がありますが、
http://json-schema.org/documentation.html

The latest Internet-Draft at the IETF is v5, published 2016-10-13. (Due to a change in authorship the I-D numbering has been reset). The specification is split into three parts, Core, Validation, and Hyper-Schema

Json Schemaの3つある仕様のうちの1つ。Hyperはhyper-mediaのhyperです。

Json

{
	"id" : "b94318c0-cc7f-11e3-9c1a-094jkd00c9a66"
	"name" : "Takahiro Fujii",
	"email" : "hogehoge@***.com"
}

Json Schema Core

{
	"$schema": "http://json-schema.org/draft-04/hyper-schema",
	"type" : "object",
	"difinitions" : {
		"id" : {
			"type" : "string",
			"format": "uuid"
		},
		"name" : {
		 "type" : "string"
		},
		"email" : {
			"type" : "string",
			"format" : "email"
		}
	},
	"properties" : {
		"name" : {
			"$ref" : "#/definitions/name"
		},
		"age" : {
			"$ref" : "#/definitions/age"
		},
		"email" : {
			"$ref" : "#/definitions/email"
		}
	}
}

Json Hyper-SchemaはURIの紐付けの部分の定義が記載されています。
英語で、ぱっと見読むのめんどくさそうな感じですが、そもそもそんなに難しい話ではないので、
一度腰を据えて読んでみるのがいいと思います。
http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.5

Json Schema Core + Hyper-Schema

{
	"$schema": "http://json-schema.org/draft-04/hyper-schema",
	"type" : "object",
	"difinitions" : { ... },
	"properties" : { ... },
	"links": [{
		"title": "Get User infomation",
		"description": "Get users resource information by id",
		"href": "/users/:id",
		"method": "GET",
		"rel": "self"
	},{
		"title": "Create User infomation",
		"description": "Create users resource",
		"href": "/users",
		"method": "POST",
		"rel": "create",
		"schema": {
			"type": "object",
			"properties": { ... }
		}		
	}]
}

linksの中の各要素については、公式ドキュメントを読んでみてください。
24スライド目を見たらわかると思いますが、
1つ目のオブジェクトがRest apiのgetの仕様にあたる部分、
2つ目がcreateの仕様にあたる部分になります。

このセッションでは、あるアプリのFrontEndとBackEndを作成する際に、
Json Hyper-Schemaを定義し、それを元に、

  • APIドキュメントの自動生成
  • HTTPクライアントの自動生成
  • モックの自動生成

を行い、お互いが(FrontEndとBackEnd)がお違いを気にせずに(疎な関係で)開発を進めることができる。
という実例を紹介されていました。

APIドキュメントの自動生成

APIドキュメントの自動生成(+多分json schemaの作成)
GitHub - interagent/prmd: JSON Schema tools and doc generation for HTTP APIsを使っているそうです。
有名ですね。が、使っていないので、使って見ました笑

 mkdir -p schemata
 prmd init user > schemata/user.json

これで、user resourceのrestful apiのサンプルjson schemaが生成されます。
最初からこれを例にして話をしてもよかったかもしれません。笑


あとはgithubのusageにそって進めていくと、、

markdownを生成

  prmd doc schema.json > schema.md

schema.mdが簡単に作れます。

f:id:takahiro-f:20170302020504p:plain

f:id:takahiro-f:20170302020519p:plain

開いてみると、こんな感じでapiドキュメントが生成されます。
非常に簡単です。

モックの自動生成

モックの生成は、自作のライブラリを使っているようです。

https://github.com/richlab-corp/schema-to-db-json

さっそく、先ほど作ったschema.jsonを食わせてみます。

  # Generate db.json from JSON Hyper-Schema
  schema-to-db-json schema.json > db.json

次のようなdb.jsonが作られました。

tf:tmp fujiitakahiro$ cat db.json
{
  "apps": [
    {
      "created_at": "2017-01-01T00:00:00+09:00",
      "id": "01234567-0123-0123-0123-0123456789ab",
      "name": "ABCDEFGHIJ",
      "updated_at": "2017-01-01T00:00:00+09:00"
    }
  ],
  "users": [
    {
      "created_at": "2017-01-01T00:00:00+09:00",
      "id": "01234567-0123-0123-0123-0123456789ab",
      "name": "ABCDEFGHIJ",
      "updated_at": "2017-01-01T00:00:00+09:00"
    }
  ]
}

次にjson-serverを立ち上げます。

tf:tmp fujiitakahiro$ json-server --watch db.json

  \{^_^}/ hi!

  Loading db.json
  Done

  Resources
  http://localhost:3000/apps
  http://localhost:3000/users

  Home
  http://localhost:3000

  Type s + enter at any time to create a snapshot of the database
  Watching...

mockを返してくれるAPIが立ち上がりました!

f:id:takahiro-f:20170302020459p:plain

簡単。
これでFrontEndはこのmock apiを使って開発が進められますね。

HTTPクライアントの自動生成

golangはherokuが作っているやつを使っているみたいです。
github.com


jsは自作中とのこと。
個人的にはクライアントライブラリはあったら便利かなぁ位なので、いいかなと。
クライアントライブラリの管理はbackend側がやるんでしょうか。
それか、一緒にメンテしていく感じなのかな。小さい規模なら特に問題なさそう。

ということで、簡単にmock apiを立ち上げて開発を進めていることがわかります。
さらに、仕様のドキュメントを作る過程が開発の過程の一部になることで、
プレゼンでもおっしゃってましたが、

仕様と実装がシンクする

というメリットがでてきますね…!いけてる。

FrontEndとBackEnd APIの意思疎通

プレゼンの中で、"合意"という言葉を使われていたのが気になりました。
おそらく、CDCのようなことなのかな、と思いました。
実際にはどのように合意をするのか結構気になります。
(自分に時間がなくあまりここらへんは聞けませんでした、、
(Pull requestのapproveが合意ってことなのかな

CDC
https://martinfowler.com/articles/consumerDrivenContracts.html


pull requestのapproveが合意だとすると、規模が大きくなってきたときに、
修正の妥当性をどのように担保していくのか、というのが気になりました。
お互いがjson schemaを元にテストを書く感じなのかな。
それか、pactやspring cloud contractのような仕組みを使うのか。

pact
techlife.cookpad.com


spring cloud contract
Spring Cloud Contract

入力フォームについて

リッチ広告は設定項目が非常に多く、複雑なフォームが多いらしい。
設定値が複雑だったり、入力値の検証だったり、動的に入力項目が変わったり、、
大変そう・・

react-jsonschema-form

というmozillaが作っているReact Componentを利用しているとのこと
知らなかった。。。

  • validationをjson schemaベースでやってくれる
  • カスタマイズが柔軟

というメリットがあげられていました。
バリデーションがjson schemaでやってくれるのいいし、
あとはreact componentはカスタマイズが本当に大事だと思う。
どんなにバリデーションの所がいけてても、出したいUIに変えられなかったら使えないですし。

react-jsonschema-formはここで試せます。
validationはかなりいけているので、どれくらい柔軟にカスタマイズできるのか、
近いうちに試してみようと思います。

react-jsonschema-form playground

まとめ

まずは、Json Schemaを使われている事例を聞けたのが何よりも参考になりました。
早く、課題をクリアして、Json SchemaをFrontEndとBackEndをつなぐのに使いたいなと思いました。
また、質問したところ、Json Schemaを直接BackEnd側のバリデーションで使っていないということでしたが、
ここは是非実現したいところです。
特に、自分が今携わっている環境だと、APIのConsumerが複数いることが多かったり、フロントエンド意外にAPIを直接呼ぶような(Gateway API経由とかで)が割とあります。
そうすると、validationを複数の箇所でそれぞれ実装してしまうと、何かのタイミングでvalidationがずれて、後で問題になる、、
みたいなことが起きやすいイメージがあります。

Json Schemaは少なくともFrontEnd / BackEndを疎にして開発を高速化するのに役立ちますが、
それだけではなく、1ResourceのValidationの定義を一箇所にまとめることができれば、特に中規模、大規模の開発においては大きな威力を発揮する、、と思います。(実現するにあたっての課題はあると思いますが

f:id:takahiro-f:20170302021049j:plain

あとは、更新する場合は穴井さんもおっしゃってましたが、versioningするのが開発のスピード落とさない為にはいい、、と思いますが、
これも同じくおっしゃっていたように、あまり多段でversion管理しまくるのも厳しいので、そういうのを防ぐ仕組みの元でしか出来ない方法なのかな、、とも思います。

schema-to-db-jsonは便利だった!個人的な開発でまずは使ってみたい。

課題があるけど使って見たい、、と思わせるJson Schema。
事例が聴けてよかった。次は自分達の事例が話せるといいな。