冬休み中に個人開発サービスのフロントエンドをフルリニューアルした話と、開発スピードを高める工夫

## 概要
- 個人開発しているマッチングサービス [MatchLab](https://app.match-la.com) の Web フロントエンドが今まで Vue で書かれていたが、 Next.js/TypeScript で書き直すことにした。
- 全25画面のうち、冬休み中の1週間（12/24〜12/31）に20画面を実装しつつ、一部の古いエンドポイント（10箇所）を新しいエンドポイントに置き換えたりした。
- チーム開発をしている普段の業務で「25画面ある新規サービスを開発しよう」となった場合1年程度かかりそうにも思われるが、1週間でできるものに1年かけるほど価値のあることをしているのかどうか考えてみた方が良さそうに思った。
- 個人開発で開発スピードを高めるためにしている工夫と、本業のチーム開発で開発スピードを落としてでもやるべき価値のあることについて考察したい。

## 作ったもの
- トップページ: トップページ、新規登録、通知一覧
- ユーザー関連: ユーザー一覧、ユーザー詳細、検索条件設定
- イイネ関連: イイネ一覧、イイネ詳細
- メッセージ関連: メッセージ一覧、メッセージ詳細
- 本棚関連: タイムライン、本棚新規登録、本棚編集、書籍詳細
- マイページ: マイページ、プロフィール編集、写真編集、プロフィール確認、アプリ設定、退会画面、お問い合わせ、ログアウト
- 管理画面: メッセージ管理画面、マッチング管理画面

※ 開発中のテンションを上げるため、開発環境ではネットで拾った美女画像を転用していることをお許しください。

### トップページ
![top](https://user-images.githubusercontent.com/14773605/148172343-14b855b2-2a9e-459e-b476-219fa95f391e.png)

### 新規登録
![registration](https://user-images.githubusercontent.com/14773605/148172537-89a9ec10-9410-4f5e-8b1b-0c30c40ef768.png)

### ユーザー一覧
![user-list](https://user-images.githubusercontent.com/14773605/148172597-04905164-6962-4c28-87ba-d2d1c64105eb.png)

### ユーザープロフィール
![profile-female-1](https://user-images.githubusercontent.com/14773605/148172617-c0ce26fe-7c3e-455f-b854-b9ebf2ed2d52.png)

### ユーザー検索
![search](https://user-images.githubusercontent.com/14773605/148172627-b4e34aaf-a605-4e56-9484-13ec11a3e2a3.png)

### プロフィール編集
![edit-profile](https://user-images.githubusercontent.com/14773605/148173024-c3e0d967-3935-441f-8496-94ccc5ce156f.png)

### 写真編集
![edit-photos](https://user-images.githubusercontent.com/14773605/148173061-38c71b5a-5edc-49e7-bbf7-83b2aaad6905.png)

### 本棚の新規追加
![new-book](https://user-images.githubusercontent.com/14773605/148173212-73592a88-5525-42a0-85ac-bec8219b9a70.png)

### 本棚の編集
![edit-bookshelf](https://user-images.githubusercontent.com/14773605/148173234-50059abf-7868-44fb-ae80-206169e60cbf.png)

### 書籍の編集
![book-detail](https://user-images.githubusercontent.com/14773605/148173247-58fc99fa-9515-4ecb-915b-6c4fb36e943c.png)

### 通知一覧
![notifications](https://user-images.githubusercontent.com/14773605/148173105-d5aff9c8-ac98-4303-9e2f-404bbd873c74.png)

### イイネ一覧
![like-list](https://user-images.githubusercontent.com/14773605/148173146-15b13c7c-be5e-4f6d-b81e-049fcc3afd48.png)

### イイネ詳細
![like-detail](https://user-images.githubusercontent.com/14773605/148173163-b713a313-5c13-4f5d-9328-c89fcaca8e68.png)

### メッセージルーム一覧
![message-room-list](https://user-images.githubusercontent.com/14773605/148173313-aae62375-64a7-4060-9b98-236e169ad1b0.png)

### メッセージルーム詳細
![messages](https://user-images.githubusercontent.com/14773605/148173355-6668bc4d-7368-4b9c-85b6-d43e7f8b36e6.png)

### タイムライン
![timeline](https://user-images.githubusercontent.com/14773605/148173276-2d9ac08d-1969-4513-93d6-21d5e67a47cb.png)

### マイページ
![mypage](https://user-images.githubusercontent.com/14773605/148173388-a254d93a-3d04-448d-a5dc-4441ead9846c.png)

### お問い合わせ
![contact](https://user-images.githubusercontent.com/14773605/148173477-0cbbdc99-d40a-4bd6-ac0f-ca6da55f0d33.png)

### 設定
![config](https://user-images.githubusercontent.com/14773605/148173496-35fa52f3-0afa-45f7-8b95-228aac4461a6.png)

### 退会
![withdrawal](https://user-images.githubusercontent.com/14773605/148173510-eeebbd7f-825f-4e1f-9cc2-618b1fa82b3a.png)

## 開発スピードを高める工夫
### 仕様を削減する
- ユーザーに最速で価値を届けるために、必要最低限の機能に絞って実装する。
- 各ページ内の要素についても、他ページと共通のパーツを組み合わせて表現できるものを主とし、個別の実装が必要になりそうなものは避ける。
  - 例えば、メッセージ機能とお問い合わせページを同じ UI パーツの組み合わせで実装したり、ボタンは色を変える程度で並び方や大きさ等はどのページでも一緒にする、など
  - こうすることで工数を削減できるだけでなく、ユーザーにとって一貫した体験が得られるので、画面ごとの学習コストが下がってユーザビリティが向上する。

### 再利用性を高める
- 再利用可能な UI パーツは共通コンポーネントとして実装し、できるだけ画面ごとのカスタマイズは控える。
- organisms 以上の要素はできるだけ templates/atoms/molecules の組み合わせで表現し、可能な限り個別の CSS を削減する（[参考](https://qiita.com/takano-h/items/8731d8e7413d7b1f6d7b)）

### 実装をパターン化する
- よくある挙動のパターンをを共通の hooks やコンポーネントに実装しておき、各ページから再利用する。
- 例えば「データをフェッチして表示する」「データ通信中はローディングアイコンを表示する」「フォームに入力された値をバリデーションして送信する」「サーバーから返ってきたエラーを表示する」「処理が成功したらトーストメッセージを表示して次の画面へ遷移する」など。
- Web アプリケーションのよくある挙動パターンをいくつか使い分けるだけで大抵の機能は実装できるので、実装の方針が決まった後は何も考えずにいつもどおり指を動かすだけで機能が完成していく。

弊 Next.js アプリの共通 hooks の例
![スクリーンショット 2022-01-05 17.25.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131942/84313c68-4a05-5af0-eb76-d98fcdde4fc4.png)

## チーム開発で開発スピードを落としてでもやるべきこと
### 自動テストの実装
これは個人開発なら書かなくて良いという話ではない（僕も API 側については全エンドポイントに対する request spec を書いた）が、冒頭に書いた「1週間で20画面」の中でフロントエンドの自動テストは書かなかったので記載した。
開発スピードを落としてでも自動テストを実装すべきと思う理由は、ざっくり下記の2つがあるように思う。

- 新規機能の追加やライブラリのアップデート等が既存の機能に影響した際にすぐに気付くためのアラートの役割を持っている。
- チーム開発という文脈で言えば、他の人が機能を修正する際に、ユーザーに対して保証すべき動作が何なのか、どういう意図の実装なのかを伝える仕様書としての役割も果たしている。

### コードレビュー

チーム開発で最も時間を取られるのがコードレビューではないだろうか。
機能の実装が終わっても「では後続の機能へ」と移行することができず、他者の作業を止めて実装を読んでくれるまで待つことになる。大抵、「今日は切りが良いから終わりにして、明日の午前中はレビューしてもらえるまで自分も他の人のコードをレビューしよ」みたいなことになり、開発スピードという面では大きなロスである。
にも関わらずメンバー間でコードレビューをすべき理由は、大きく分けて4つあると思う。

- プロダクトの品質を保証するため。考慮漏れやセキュリティのリスク、可読性などを複数人の視点からチェックすることで、より安定的で安全なサービスをユーザーに届けることができ、また長期的な変更容易性、保守性を向上させる。
- 実装を複数人で共有することで、その箇所に何か問題が発生した際に実装者がいなくても迅速に対応ができる。実装箇所の知識が個人に依存することを防ぎ、個人がチームから抜けたりしても長期的にプロダクトをメンテナンスしていくことができる。
- コードレビューのための説明が、実装の背景や意図を伝えるドキュメントになる。後で commit 履歴から Pull Request を参照すれば、該当箇所がどのような背景・意図で実装されたのか誰でも知ることができる。
- お互いに改善点を指摘し合うことで、技術力向上の機会になる。特に経験の浅い者は、より良い書き方やリスクなどについて学習する貴重なチャンスとなる。

他にも色々ありそうだけど、一旦ここまでにしておく。何か思いついたら書き足すかも。
逆に「これ1週間でできることを1年かけるほどやる意味ないのでは？」みたいなものも沢山ありそう。