久々の更新。RESTfulつらいって話の続き。
久しぶりの更新です。
今年の4月から働き始めたこともあって、この時期になりました。
更新しない間にあったことと言えば、
普段使ってるSNSのMisskeyにカスタムテーマの昨日が実装されて喜んでたり、
Misskeyでわいわいお話をしたり、
Frost-APIの設計を考えたり、
そんな感じでした。平和というか平凡というか。
さて、以前の更新で書いたRESTfulなAPIがつらいって話の続きを書きたいと思います。
RESTがシンプルで美しいのはそうなんですが、いくつかつらい部分もあり、最近はRESTに変わるようなHTTP APIのエンドポイント設計を試行錯誤しています。
今考えてるのは次のようなスタイルです。
1. 基本的にエンドポイントは全てPOSTメソッド固定
2. URLパスの一番最後の部分を動詞にする(例: /user/relation/get)
このスタイルにはいくつかのメリットがあります。
その1つ目は、全てのエンドポイントでリクエストbodyを使えるという点です。
GETメソッドはbodyにパラメータを付加することができないため、JSONなどの構造化されたデータをパラメータとして渡すには適していません。無理やりする場合は、クエリ文字列としてJSONを渡したり、クエリ文字列に何らかの工夫をする必要が出てきます。
常にPOSTを使うことによって全てのエンドポイントでbodyを使うことが出来るため、上記の問題を解消できます。
2つ目のメリットは、リソースに対する操作を自由に命名できるという点です。
HTTPのメソッドで操作を表そうとすると、HTTPメソッドのGET、POST、PUT、PATCH、DELETE等で全ての操作を表す必要があり、少し表現力が乏しいと感じます。
実際、RESTfulなAPIを作っていたりすると、検索をするエンドポイントのHTTPメソッドは何を使おう...ユーザーをフォローするときのHTTPメソッドは何を使おう...というような感じで、やりたいこととは直接関係ない部分で考え込むことがよくあります。
何らかの単一のデータを取得する操作には「get」、
コレクションのデータを取得する操作には「list」、
データの作成には「create」、更新には「update」、削除には「remove」(もしくはdelete)。
この5つを基本として、必要であれば「follow」「unfollow」「validate」「search」「check」「filter」など..自由に用意できるので、リソースへの操作を自由に表現することができ、その操作の意味も伝わりやすくなることが期待できます。
これについては賛否あると思いますが、HTTPのつらさを補う1つの方法として参考にしてみてはどうでしょうか。
GitHubのissuesで試行錯誤の様子を見れます:
エンドポイントの形式をリニューアルしたい · Issue #118 · Frost-Dev/Frost-API · GitHub
過去にTwitterでやったアンケート:
RESTより扱いやすい、新しいHTTP APIの設計を考えています。
— まりはち (@mr8Alice) August 4, 2018
どの形式のエンドポイント設計がすき?
A. POST /users?method=show (body: id=abc123)
B. POST /users/show (body: id=abc123)
C. POST /users (body: method=show&id=abc123)
D. それ以外(リプください。ただし、RESTは含まない)
RESTfulなWebAPIが辛くなってきた
久しぶりの更新になります。
大学の卒業研究の最後の追い込みがあり、そっちのプログラムを書いていたりしてなかなか趣味に時間を使えなかったここ最近ですが、ようやく最終の発表が終わりました。
なので、Frostの開発を進めていきたいなと思って、進めていっている所です。
前回の記事ではアーキテクチャ設計の森に迷ったとか、なんとか言っていました。その話は一旦収束(結局自己流でいくことに)しました。
今回はその話とは別の意味でのアーキテクチャについて「RESTfulなWebAPIが辛くなってきた」という話です。
早く未実装部分の実装をしろって感じですが、何かを作る時の考える過程が好きなので仕方ないです。
ことの発端はGraphQLという技術を知った頃でした。これはクライアント側が欲しいデータのみを構造的に記述したクエリをAPIに渡すことによって、選択的にJSONレスポンスを受け取ることができるといった具合の仕組みです。
複数回のHTTPリクエストが必要なくなったり、必要なデータだけを受け取れたりと画期的な仕組みだと思いましたが、ページネーションを実装しようとすると概念的に複雑になるようで辛そうでした。
Frostではタイムラインの取得APIなどでページネーションを実装する必要があり、APIを利用する側からしても複雑な概念なく容易に扱える必要があります。
その辺りを考えて今回は導入を見送ることにしました。
他にも色々調べてみたりしましたが、まだ理想的な技術は見つかっていません。
一旦アーキテクチャスタイルの模索はこの辺にしておいて、今後は中身を作っていこうかな
という感じで、今はとても小さなコミュニティのFrostですが、いつか多くの人に使ってもらえると良いなというモチベーションを持って開発していきます。
アーキテクチャ設計という森
この間、ネットを回っていたらこんなスライドを見つけました
複雑なJavaScriptアプリケーションに立ち向かうためのアーキテクチャ // Speaker Deck
そしてこの中に登場している「レイヤードアーキテクチャ」という手法にとても関心を持ちました。これはMVVMのうちのモデル層をさらに3つの層(アプリ,ドメイン,インフラ)に分割するというようなものです。
そこから関連する考え方やアーキテクチャを調べていき、ドメイン駆動設計(DDD)、ヘキサゴナルアーキテクチャ、オニオンアーキテクチャ、などなど..色々あることを知って最終的にクリーンアーキテクチャが良さそうということになり、それについてもう少し深く調べることにしました。
まだその途中ですが情報が多くて今は迷走気味になっています!
ぼくはこんな感じでアーキテクチャ設計という森に迷い込んでしまったのでした。
オープンソースでTwitter風ソーシャルメディアを開発し始めた話
元々このプロジェクトを始めようと思ったのは、知り合いがTwitter風のSNSを開発していてその影響を受けたのがきっかけでした。
その目的は、勉強になるからということも勿論ですが、その人の技術レベルへの憧れが大きかったと思います。
さて、きっかけについてはこのくらいにしてこのプロジェクトの説明に移ります。
プロジェクト名は「Frost」と名付けました。(TeaTimeというForstの前身プロジェクトも一瞬ありましたが)
リポジトリは現在2つあって、アプリケーションに対して各種リソースの提供を行う「Frost-API」と公式アプリケーションのWebサーバである「Frost-Web」に分かれてあります。
Frost-APIでは一般的なREST APIと、WebSocketを利用したStreaming APIを提供しています。Streaming APIからもREST APIを呼び出すことが可能になっています。
ここで開発しています。
今の時点で利用している技術や環境は、
- APIサーバ/WebサーバにNode.js(JavaScript)
- データベースはMongoDB
- フロントエンドフレームワークにRiot.js
が主になっています。
開発初期の頃はサーバサイドはphpで書いていましたが、phpからだとWebSocketが扱いにくいらしいと聞いて途中でサーバサイドは全てNode.jsに切り替えることにしました。
当時、JavaScriptは旧石器時代レベルのものしか書いてこなかったため、全て書き換えるのには苦労しました。しかしその反面、JavaScriptとphpの書き方の違いが知れたりしたのでphp時代が無駄になったという気持ちは余りありません。
また、php時代では今のようにAPIサーバとWebサーバを分けて考えていなかったため、サードパーティのクライアントアプリにAPIを提供しようとした場合に根本的な部分から大きく変更する必要がありました。
その点、今は公式アプリ(Frost-Web)もサードパーティアプリとほぼ同等な扱いをしてAPIを経由してリソースにアクセスさせることによって、ある意味拡張性を構築できた気がします。
フロントエンドフレームワークにはRiot.jsを使っています。そのクールさコンパクトさに惹かれました。。良いフレームワークなのでみなさんも使いましょう。
最後になりますが、随時コントリビュータを募集しています!
一緒に開発する、または意見をくれるだけでも良いので協力してくれる人はコメント欄twitter、github、frostまで連絡ください!
今後も、Frostの開発について何か思ったことがあれば記事を書いていきたいと思います。
はてなブログ開設しました~
はじめまして!
プログラミングや創作系のゲームを主にやっている「まりはち」と言います。
このブログでは、何か作ったとき、行き詰まった時、思い立った時に記事を書いていこうと思うので、コメント等貰えるととても嬉しいです。
文章が下手くそなので、拙い感じになってしまうかもしれませんが、その際は生暖かく見守ってもらえればと思います。