DoorKeeper
https://rubychildren.doorkeeper.jp/events/39034
Togetter
http://togetter.com/li/942251
場所は高円寺のヴァル研究所さんです。
参加者は30人くらいでしょうか。
毎回、以下の書籍をターゲットに読書会やら、特別ゲストによる講演やら、ワークショップなどが催されます。
Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)
posted with amazlet at 16.02.24
山本 陽平
技術評論社
売り上げランキング: 7,978
技術評論社
売り上げランキング: 7,978
今回は読書会形式ではなく、AWSJの西谷 圭介さんを特別ゲストとして迎え、プラットフォームにAWSを使用しているサービス「駅すぱあとWebサービス」のAPIやドキュメントを題材に、公開レビューという観点で学ぶ、という位置づけの勉強会でした。
RESTプロフェッショナル川村さんが書いてくださった、この日のポイントです。
#RESTudy RESTful#とは勉強会13 今日のポイントです https://t.co/LNbODhK2Hi
— Toru KAWAMURA (@tkawa) 2016, 2月 23
グループワーク
最初に4~5人ずつのグループに分かれ、「駅すぱあとWebサービス」を題材に、どこがRESTfulか、どうしたらRESTの規約に近づけるかなどグループで話し合う時間が1時間ほど設けられました。
ウチのグループは「駅すぱあとWebサービス」のAPIソリューション 無償提供版 ドキュメントを題材に話し合いました。
その中で出た意見は以下のとおり。
- レスポンスデータの名称の先頭が大文字だったり小文字だったりと、統一感が無い。
- レスポンスデータの要素が複数を想定しているのに、名称が複数形でなく単数形になっている。
- APIのURLが予約語と被ってる。例えば/railとかは、Rails使いだとハマるかも。
- レスポンスデータに必ずengineVersionがあるが、APIを叩く側のユーザにはこの情報はいらないんじゃないか。
- エラー時に、404のようなHTTPステータスコード以外にも、エラーレスポンス内に「内部エラーコード」を持っているのが興味深い。
- 存在しないクエリパラメータを指定すると、「もしかして XXX」のようにサジェストしてくれるのが面白い。
- URI: http://api.ekispert.jp/v1/json/station/info?code=22828&type=rail:nearrail:exit:welfare&key=XXX&test=abc
- レスポンス: {"ResultSet":{"apiVersion":"1.26.0.0","engineVersion":"201602_03a","Error":{"code":"W400","Message":"指定されたパラメータ(test)の名前が間違っています。 もしかして: type"}}}
「駅すぱあと」のWeb APIがC言語で作られている理由
グループワークの後、ヴァル研究所の見川さんより、「駅すぱあとWebサービス(API技術)がC言語で作られている理由」について紹介がありました。
それによると、
- 「駅すぱあと」のエンジンがC言語で開発されているので、エンジンを直接コールするのにWebサービス(API技術)もC言語にしているため
- Webサービスをバイナリ提供するため
という理由があるそうです。
エンジンがC言語なのは、顧客が増えた時にでも使えるよう性能面を考慮してのことだそうで、それが今のWebサービスに至ったとのこと。
Rubyの実装部分は薄くし、基本機能はC言語で再実装し、Webサービスの本質的な機能はXML-RPCに寄せているそうです。
ちなみに「駅すぱあと」のAPIはRestfulではなく、Restfu(≒Rest風)なんだそうなw
西谷さんによる公開レビュー
お次はグループワークのお題に沿って、AWSJの西谷 圭介さんによる「駅すぱあとWebサービス」の公開
西谷さんは自称「REST原理主義者」なんだそうな。API設計に深いこだわりがありそうです。
まず最初、そもそも「Restfulとは?」という問題提起から入りました。西谷さんは、Restfulとは
- リソース指向なURI設計をする。つまり、リソースという観点でパスを切ってURIを設計する。
その上で、ディスカッションを交えながらレビューを進めて、以下の様な意見が出てきました。
■ APIドキュメントの見やすさ
- 「Webサービスドキュメント - API」が見にくい。それは、ドキュメントの並びがリソース単位じゃないから。
- /courceとか/stationという文字列が、あちこちのカテゴリに入っている。
- Restfulの原則として、「リソースに対してCRUDしていく」というのがあるが、その観点では見づらい。
- 一方で、カテゴリ毎に纏まっているので、それはそれで見やすい。目的ごとに探しやすい。
- リソース毎に分けたAPIドキュメントと、カテゴリ(目的)毎に分けたAPIドキュメントの、両方が提供されていれば良かったのでは。
■ 単語の区切り
- /passStationで、単語区切りのSが大文字になっており、キャメル形式になっている。
- URIで、大文字はあまり使われない。単語の区切りはハイフンを使うパターンが多い。passStationでなく、pass-station。
■ * (アスタリスク)
- API仕様のURIすべてに*が含まれているが、初見には謎すぎる。誰もがそう思うはず。
- *にはフォーマットを指定するらしいが、普通は入れないよね。
- ⇒ 最近の設計だとHTTPヘッダに書いたりするが、いろいろあってこういう設計になっている。こだわりは無い。 by 見川さん
■ バージョン指定
- API仕様のURIすべてに /v1 というバージョン番号が含まれている。
- v1が公開されてから6~7年経っている。v2が出る予定は今のところ無い。 by 見川さん
- バージョン番号をURIに含めるかは諸説ある。
- バージョン番号はリソースじゃないからURIに入れないという考え方もあり、その場合はクエリパラメータとして付けるか、リクエストヘッダに入れるかすることが多い。
- バージョンによってAPIを切り替えられるようにするならURIに載せてしまったほうが良いのでは。
- バージョン番号がURIにある方が、ヘッダやクエリパラメータにあるより人間にとってはわかりやすい。
■ 単数形
- リソースがすべて単数形で表現されている。基本的には複数形を使っていくのが良い。
- GETメソッドで複数取得できるなら複数形にし、単数も取れるならURIの後ろに /?id=3 みたいに指定して取得するのが良い。
- 運行情報路線のリストを取得するのに /service/list とするのはあまり良くない。
- /service とし、GETメソッドでアクセスするとリスト構造が取得できるようなURI設計が良い。
■ CRUD
- 提供しているAPIはすべてGETメソッドを想定しているのに、URIに /create や /editという単語は不自然。
- CRUDはHTTPメソッドに対応させるのが大原則。
- createならPOSTメソッドだし、editならPUTメソッドを使う。createやeditという単語はURIに含めない。
- 経路(cource)を更新(edit)したい場合は、URIで /course/id=xx と更新対象を指定し、更新内容はリクエストボディに持たせて投げるのが普通。
■ 敢えて /create とした理由 by 見川さん
- /course/create としたのは、「パラメータに与えた経路を作り出す」という意味を込めて設計した。
- 「駅すぱあと」は経路探索がウリなので、一部のお客様のニッチなニーズに対応するために用意した再検索用のAPIである。
- 経路の生成コストが大きいので、組み合わせの情報だけ保存しておけば経路を再現できるような仕組み。
■ 敢えて /edit とした理由 by 見川さん
- 探索した結果の経路に対して特定の操作をするAPIである。
- 特急料金、グリーン席料金、自由席料金、それぞれ計算する必要があるので、それを指すのがedit。(???)
■ APIのアクセスキー
- 「駅すぱあと」のAPIアクセスキーはWebで申請できるが、お客さんには紙で送付するビックリな運用になっている。
- 課金を含めてすべてをWebで回すまでには至っておらず、会社の諸事情もある。
- URIのクエリパラメータにkeyを含めてアクセスすることはセキュリティ上ありえない。
- 一般的には、リクエストの認証ヘッダ(Authorizationヘッダ)にkeyは格納する。
■ リソースの相関関係
- リソースの相関関係が人間にとって理解できないと意味が無い。
- 特定のリソースがあるリソースにぶらさがっているという構成が理解できないといけない。
- 「駅すぱあと」は「鉄道」というドメインに偏っているので、URIの表現の仕方が難しい。日本語の説明を見ても、違いとかよくわからない。
■ 時刻表(timetable)
- /plane/timetable と、飛行機の下に時刻表がぶら下がっているが、この上下関係以外にも別の表現がありえるのでは。
- APIはGETメソッドしか許容していないので、時刻表(timetable)の更新用のAPIは無い。 by 見川さん
- 時刻表ファイルの切り替えで更新を実現している。 by 見川さん
- 時刻表の更新は1~2週間毎くらいで更新が頻繁に入っている。 by 見川さん
■ /dataversion
- dataversionって何?
- このサービスが持ってる鉄道とかバスの更新情報を示している。 by 見川さん
- このWebサービス自体のバージョンとかも返している。(apiVersion) by 見川さん
- APIを使う側にとっては、いつのAPIの情報を使っているのかを知るためのもの。 by 見川さん
- dataversionって冗長じゃない?という声も。
■ /station/info
- あえて /info を用意しているのは?
- /station に比べ、 /station/info は付属的な情報(あまり必要とされない、微妙な情報)を提供する。 by 見川さん
- その用途の違いがあるので/stationと/station/infoを分けている。
■ /search
- searchって名詞じゃなく動詞のようだけど、リソース名としてどうなの?
- 「探索結果」という名詞の位置づけ。 by 見川さん
■ APIドキュメントのメンテナンス
- ドキュメントはぬくもりを感じたが、メンテナンスどうしているか?
- APIドキュメントはもともと自動生成していたが、最近はGitHubで管理して複数人でレビューする手動管理にしている。デプロイは自動。
■ リソース名が日本語
- /teiki って、「定期」という日本語が混じっているのが気になる。
- ⇒ 日本の定期券は独特の事情があるので、あえて日本語のリソース名を付けている。
■ コンテキスト依存
- クエリパラメータの名前は同じだけど、コンテキストによって意味が変わるものがあった。
■ APIへのリンク
- APIのレスポンスにリンクが無い。次に取り得る状態をリンクとしてレスポンスに含めるのが良い、という指針に沿ってない。
- /stationを呼び出した時に、レスポンスで/station/infoを含めて返したほうが良いのでは。
- APIドキュメントのリンクも合わせてレスポンスに入れてしまえばいいのでは。
■ http://schema.org/
- リソースや要素の名称を考えるときに役立つサイトとして schema.org というのがある。
- 共通の語彙を纏めており、標準的に使われる可能性が高い語彙が登録されている。
- 標準的なボキャブラリはこのサイトから選択すれば良いのでは。
- 鉄道情報のボキャブラリも、 https://schema.org/TrainStation や https://schema.org/TrainTrip が参考になるかも。
- teiki(定期)もschema.orgに登録してもらえば良いかも。
■ ResultSet
- レスポンスデータのルート要素が必ずResultSetになっているのが気になった。
- 必ず同一のリソースで括る、という思想で、抽象的な階層を1段設けたかったのでそうした。 by 見川さん
- とにかくResultSetを取得すれば、そこに何かが入っている、という状態を作っておきたかった。 by 見川さん
■ light / full / extreme
- fullがデフォルトで、デフォルトから足したらextreme、デフォルトから引いたらlight、という思想だったが、今は微妙になってる。
- extemeはベータ段階で適当に付けた名称で、後で直す予定だったが、リリース直前に疲弊して直せなかったままになっている・・・ by 見川さん
- light/full/extreme は、構造が同じならクエリパラメータで指定するの良いのでは。構造が別ならURIを分けて別リソースとした方がいい。
■ AWSのAPI
- 本当に糞・・・。Rest APIと謳っているのに、全然そんなことはない。
■ 駅すぱあとのAPI
- 全体的に綺麗なAPI設計になっている。
- 昔からあるAPIなのに、最近のAPI設計のあるべき論からも外れていないし、ちゃんと昔から設計やってたんだな、と感じる。
■ 時刻表の秒
- 鉄道の時刻表って秒単位で列車情報を持っていると思うが、秒単位をデータとして保存するのはどう考えているか?
- 秒単位でデータを持っているが、現状は公開していない。分単位のデータを公開している。 by 見川さん
■ 緯度経度の情報
- 緯度経度、DEG形式とPOT形式の両方返すのは、使う側の利便性を考慮し、計算の手間を省くために2つ持っている。
Q.「緯度経度、DEG形式とPOT形式を両方返すなら測地系(gcs, Tokyo)も返してもいいんじゃない?」A.「それもできるが、煩雑になるためユーザーが使いたい型式を全体で指定できるようにした」ユースケースとしては確かに混在する必要ないか #RESTudy
— 出禁 (@chiastolite) 2016, 2月 23
■ SDK
- AWSなどはSDKが提供されているが、駅すぱあとはSDKは用意されていないのか?
- 特定言語に向けたSDKを用意するのは必要だと思ってるが、そこまでおいつけてない。 by 見川さん
■ リソースモデリングパターン
- 川村さんがRESTfulなURL・リソース設計のパターンとして、「リソースモデリングパターン」というブログを書いている。
勉強会終了後の西谷さんのブログ
はてなブログに投稿しました #はてなブログ
— Keisuke Nishitani (@Keisuke69) 2016, 2月 24
RESTful#とは勉強会で公開レビューしてきました - Sweet Escapehttps://t.co/ZxfN8lkCzh pic.twitter.com/mvMkt9Enz7
とても勉強になるレビューでした。ありがとうございました。
勉強会終了後の川村さんのブログ
ブログ記事書きました
— Toru KAWAMURA (@tkawa) 2016年2月27日
RESTful#とは勉強会13 を開催しました #RESTudy - tkawaのはてぶろ。https://t.co/zVN2REm47z pic.twitter.com/s4KqQwyrGV
いつも事前準備と丁寧なフォローありがとうございます。
感想
とても学びの多い勉強会でした。
実際のAPIを題材に、実際に頭を使ってみんなで考えた後、有識者の見解も聞く。この理想的なサイクル。
とても実用的で、多くの気づきを得ることができました。こーゆうのは良いですね。
毎回の勉強会で欠席率が非常に低いという点は、こーゆう充実した内容と運営、そして穏やかな雰囲気があるからこそだと思います。
次回の勉強会も楽しみにしています。
関係者の皆様、ありがとうございました。
PS:
帰り際にスマホ紛失疑惑でお騒がせし、スミマセンでした・・・&お気遣いありがとうございました。
@makopi23 了解です。良かったですね。主催者・懇親会会場にも伝えておきます。
— Takeshi Arai (新井 剛) (@araratakeshi) 2016, 2月 23
- 関連記事