いかにして正気を保ちながらREST APIサーバを書いたか

# REST API サーバを書く
**アジャイル開発()** で REST API サーバ書いて見よう！みたいな授業に巻き込まれてしまったから頑張って書く話です。 ~~二度とやりたくない~~

# どうして正気を失ったか
要件定義がめちゃくちゃ難しかったためです。
<img width="20%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147520/07eb3cdf-0b8f-83fe-1b66-e8377ca4be73.png">


基本的にこの手のサーバを書く時には、ある程度DBやAPIの仕様があって、それを元にして crud 操作なりを組みてたていくのが定石ですが(というか **そうしなさい(must)**)、

**開発方針** のせいか、ほぼ 0 から、適当に(仕様なしに)作って、とりあえず動かして、なんかよくわからない要求が出てきて、... という繰り返しをさせられるために基盤仕様がコロコロ変わるという **地獄絵図** が繰り広げられることになっていました。(アジャイルのサイクル中にユーザテーブルを0から作ろう！とかマジでやめたほうが良いと思います。)

さらに技術選定についてもガバガバのガバで、この手のサービスを開発するにあたって必要な知識の補完が緩い (JWTとかOauth2.0 OpenID Connect などのセキュリ周りの話とかNull) かつ **ナビゲーターの居ないモブプロ** を始めようとしたりするなど大分無茶が過ぎていたことも要因の一つでした。

また本番実装主義のくせにドメイン取得、SSL証明、本番サーバ運用コストを負担しないなどはあまり高印象ではありませんでした。(~~OpenSSL で証明書発行して SoftetherVPN Server を通すという裏技があります~~ ~~Heroku で全部完結させればいいじゃないとかいう指摘があるとかないとか~~)

実際、私が一番時間を食ったのは、REST APIを用いたログイン処理(いわゆるセッション管理)で、

- session base  
    REST API でなければ採用していた。ステートフルなサーバが求められる。
- JWT base    
    これを採用しようとした開発者は余程のアホか、めちゃくちゃ優秀なチームのリーダーのどっちか。魔境
- Token base    
    丸い。とりあえずこれを使うのが楽。セキュリティ的に正しいかは知らん。    
    (Authorization ヘッダを用いる手法全般を指すものとする。つまり OAuth 2.0 とかもここに含める)

**全部実装するはめになりました。(結局使ったのは Token base だけですが)**
# 開発方針
## マイクロサービスの集合 vs クソデカサービス単体
マイクロサービスの集合が楽です。実装を切り分けられるので精神衛生上幸せになります。

例えば cron で定期発火な WebPush をすることと、REST API をすることは切り離して考えることが出来て、それぞれを別のサービスとして実装することがマイクロサービスの集合として挙げられます。
(みんなで一つのレポジトリ！みたいな最近の(?)ジャパニーズ開発方針だとこっちはあんまり好かれないのかもしれない)


> 頭からケツの毛まで Django があれば解決？まあ、そういう意見もあるでしょう。

## 開発段階の切り分け方
開発段階の切り分け方はおおよそ2つくらいあると思います。

### 機能型
細いワイヤーを束ねるイメージ。
特定のAPIのエンドポイントの入り口からDB、DBから出口までを作るを繰り返す感じ。
アジャイルなんかで作る

### 階層型 (横)
DB 周りのレイヤー、エンドポイント・ルーティング を作るレイヤー、ハンドラの内部処理を作るためのレイヤー、データのバリデーションを行うためのレイヤー、といった風に分けて実装する型です。

極めて粗結合に実装ができるために、どこで事故を起こしているのか、どこの実装が甘いのかが比較的にわかりやすいと思っています。
~~そもそもクライアント-サーバに分ける一般的な開発方針自体がこの階層型に近いということを考えると、こっちのほうが楽なんじゃないかな hogehoge~~

今回私はレポジトリも分離して開発をして、(tcs はプロジェクト名)

- tcs-db データベースの接続、SQL文の処理
- tcs-handler APIのエンドポイント・ルーティング、パラメーター、ヘッダ情報など
- tcs-spec 内部で用いるデータの制約(バリデーション)
- tcs-service 内部ロジック (DB<->handler)   
(今回は tcs-service で他すべてのプロジェクトをまとめ上げています)

という感じに開発をしました(しています)。それぞれで実装・テストを行って、問題があればお互いに報告して修正を加えていきます。

結局統合するので **ブランチ分割** も視野に入れていましたが、例えばクライアントに endpoint のテスト環境を渡す際に、データベースの設定方法や docker-compose をした時の無駄なリソースを割いてもらったりするのが嫌だったたのでレポジトリごと分けました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147520/4f1d62dd-8c02-01f5-3308-1b9cc9826954.png)

## 開発の進め方と役に立つツールなど
### Swagger / OpenAPI 3.0
<img width="20%" src="https://static1.smartbear.co/swagger/media/assets/images/swagger_logo.svg">

あると便利です。特にサーバ、クライアントで分かれて開発をするとき、REST API的な雰囲気で開発をしたいときには、誰か一人はこれを使えるようになると良いです。

Swagger の利点はクライアント側、サーバ側、どちらの人が書いても構わない、という点です。

クライアント側ならば [Swagger Editor](https://editor.swagger.io/) で欲しいデータについてのエンドポイントを書いてそれをサーバ側へ手渡すのが良いと思います。

サーバ側ならば、例えば [Reitit](https://github.com/metosin/reitit) や [swagger-node](https://github.com/swagger-api/swagger-node) などいくつかのライブラリでは Swagger データの自動生成をしてくれます。

但し OAuth 2.0 を実装する際には旧来の Swagger ではなく OpenAPI 3.0 を用いると良いです。

### 必要技術をテーブル・リストにして調査する
例えば REST APIのログイン処理、などのようなものは何も知らないで Google 検索をして適当に実装できるものではありません。**英語検索をしたから確かな情報だ！などとのたまう愚か者は焼却炉にでも放り込んでしまいなさい**

**使えそうな技術はできる限りリスト** にして、それを実装している例、セキュリティに関する情報などを調査、一覧にしてそれらを比較すると結果的に良いプロダクトが開発できると思います。

そういった意味では、行き当りばったり開発(~~アジャイル開発~~) は私には肌に合いませんでした（実際慌てて JWT でのログイン実装をして痛い目をみました）。

### できる限り知っている人を頼る
<img width="20%" src="https://a.slack-edge.com/4a5c4/marketing/img/icons/icon_slack.svg">

例えば Clojure なんかは。日本語の Slack、(英語ですが)全体のSlack が存在しており、ライブラリなどの利用方法がわからなければ気軽に相談できる環境が整っています。

困ったときは彼らを頼れたため、精神的に大分楽になりました。

### 日記をつける
<img width="20%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147520/9be5b2bd-14ce-7b2d-68a1-50785c16436b.png">

割と大事なことで、**精神的に駄目** になってくると本当に動けなくなり、自分が何をしているのかすらわからなくなります。

**物事の優先順位** もガバガバになりますし(食事より実装を優先する、シンポジウムの原稿よりも実装を優先する、修論よりも実装を優先する etc.)

どのくらい進捗を産んだのか、ではなく **何がしんどかったのか** / **それでどのくらい時間を無駄にしてしまったのか** あたりを中心に日記を書くと良いでしょう。
そして翌日、来週振り返り、どうして無理になっているのかをわかるようにすると良いと思います。


## 使用言語・フレームワークの選定
### CI/CD を使いたい！キラキラしたい！
とにかくデカイフレームワークで人気の言語を使うといいんじゃないっすかね。詳しくは知りません。
とりあえずみんなが使っていればこの手のサービスはサポートしているので、「Qiita Rest API」みたいにして調べて上位にあるフレームワークを選べば良いと思います。
Google トレンドで比較しても良いかもしれません。

### 低みの実装をして柔軟にしたい
ドキュメントを探せる(API docs がしっかりあるライブラリ) or その実装について詳しく聞ける人が近く (Slack とかで聞ける)ものを選ぶと良いと思います。
間違ってもバージョンごとにガッツリ仕様が変わってドキュメントを調べても古いものばかりが出てくるフレームワークとかは使ってはいけない。

# アジャイル開発について思うこと
1週間〜2週間で開発を行い、リリース、フィードバックを受けて再開発、というようなサイクルが素晴らしい！という利点を持った素晴らしい開発手法！

という風に言われていますが、例えば **実務経験や知識の乏しい授業の詰まった大学生・大学院生** にこのサイクルを適用させて上手く回らせようとするのは、ブラックそのものな気がしますね。

あの手の方々はホワイトイケイケスタバMacなイメージがあったんですが、かなり体育会系だな、と思いました。（なるほど、確かにスクラムとか用語に使うわけです）

また、プロジェクトの基盤は **あくまで基盤** なので、そこを盤石にしておかないと、ものすごくコストのかかる修正があとから生まれたりするので、そこを高速サイクル開発するのはどうなんだろうなぁって思いました。もちろんウォーターフォールで徹頭徹尾やれ、というわけではないですが、初期段階の大事な基盤に関してはじっくり仕様を決めてから作ったほうが、その後アジャイルを導入するにせよ、より柔軟な開発ができそうな気がしています。

# 感想
精神とスケジュール、そして体調を著しく壊すので、二度とやりません。