エンジニアが開発しやすい環境作り

## はじめに

自分は現在、システム開発会社にて執行役員としてプロジェクトマネジメントやコンサルをしています。

今までのプロジェクトから得た経験を元に、エンジニアが開発しやすい環境作りについて、自分なりにまとめていきます。

## 対象者

- エンジニアチームのモチベーションを上げたい人
- エンジニアチームにとって開発しやすい環境作りを知りたい人

## お断り

- 今回紹介するのは自分が実践してきた一例であり、必ずしも正解というわけではありません
- 「こうしなさい」ではなく「こうするとより良くなるかも」といったモチベで書いています
- GitHubで開発を進める前提

## 目次

- ドキュメント整備
- issueの作成
- 開発環境の整備
- コードレビュー
- プロジェクトの開発進捗の管理について

## ドキュメント整備

まずはじめに、エンジニアが開発に入る際に必ず見る「**README**」の書き方を説明していきます。

自分がREADMEを書く時は「**プロジェクトに新規にアサインされたエンジニアの人が読んでもプロジェクトの概要をつかみ、スムーズに開発作業に入れること**」を目標にドキュメントを書いています。

READMEをしっかり書くことで、無駄なコミニュケーションを無くし、エンジニアとして開発に入りやすい体制を取ることができるので、かなり力を入れてまとめています。

自分が実際に書いているREADMEの内容を紹介していきます。

- 目次
- コーディングルールについて
- 構成図
- 各種リポジトリのリンク
- 使用技術
- 環境構築の手順
- ディレクトリ構造
- コンポーネントの責務早見表
- GitとGitHubの運用方法
- プロジェクトを進める上での参考記事

1つずつ詳しく見ていきます。

### 目次

目次をつけることで、概要の把握及び、ドキュメント内の欲しい情報にかんたんにアクセスすることができます。

マークダウンファイルでは下記のようにタイトルにidを付与すれば目次を作ることができます。

```md
## 目次
- [システム構成について](#system-configuration)
- [各種リポジトリのリンク](#repository)
- [使用技術について](#technology-used)

<h2 id="system-configuration">開発構成の概要</h2>
<h2 id="repository">各種リポジトリのリンク</h2>
<h2 id="technology-used">使用技術について</h2>
```

![](https://storage.googleapis.com/zenn-user-upload/e35c3644aff3-20230418.jpg)

### コーディングルールについて

コーディングルールは量が多くなる可能性が高いので、READMEとは別に.mdファイルを作成してリンクを付与します。

``CONTRIBUTING.md``という名前のファイルを作成します。

``CONTRIBUTING.md``に書いている内容は、

- このドキュメントは何か
- 目次
- 前提
- コーディングルール

``コーディングルール``の見出しには、本プロジェクトにおいて下記のようなルールを定めておきます。

- 命名規則
- propsの記述方法
- styleの設計方法 (BEM記法等)
- importの順番
- メモ化について
等...

このようにコーディングルールを明確化しておくことで、コードの統一性が保たれ、プルリクエストの確認の際も指摘の根拠になります。(コーディングルールに外れてた実装をしていた場合のコメントを入れやすい)

またコーディングルールを記述する際に、GOODとBADの具体例となぜそのコーディングルールを採用しているのかをかんたんに載せるようにしています。

【具体例】
```:CONTRIBUTING.md
### 本プロジェクトにおいては、propsは展開せずに使う
理由: propsから渡ってきた値だと分かりやすいので

【GOOD】
export const MyPage: React.FC = (props) => {
  return <p>{props.title}</p>
}
【BAD】
export const MyPage: React.FC = ({title}) => {
  return <p>{title}</p>
}
```

他にもリーダブルな書き方をしてもらうために下記のような参考記事を載せるようにしています。

https://qiita.com/KNR109/items/3b14e2e8f89a33c0f959

### 構成図

構成図では図を用いて「**どんな技術が使われ、どんな仕組み**」でアプリが動いているのかをまとめていきます。

要点を掴めるように、下記のような簡易的な図を自分のプロジェクトでは作成しています。(あくまで参考例)

![](https://storage.googleapis.com/zenn-user-upload/0a3c6dca819b-20230418.jpg)

これを見た人が「**フロントはNext.jsでサーバー(API)はNest.jsを使い、インフラでは``Verce``lと``Heroku``が使われているのか**」といった開発の概要が掴めれば十分です。

図解の作成ツールとしてKeynoteやパワポ、[diagrams.net](https://app.diagrams.net/)などがあります。AWSなどが絡む場合は``diagrams``を推奨。

構成図を作ることで、新しくプロジェクトに入ってきたエンジニアが「**使われている技術は〇〇で、自分は全体のこの部分の開発をしているんだ**」と大枠を掴むことができます。

### 各種リポジトリのリンク

自分が入っているプロジェクトでは、下記のように3つのリポジトリに分かれているので、各リポジトリにかんたんにアクセスできるようにリンクをREADMEに付与します。
(分かれていない場合はこの章は不要)

- project-name-web (フロント側)
- project-name-app (サーバー側)
- project-name-spec (APIの定義ドキュメント(OpenAPI)やモックデータの検証用)

```md
<h2 id="repository">各種リポジトリのリンク</h2>

- [サーバーサイド (API)](サーバー側のリポジトリのリンク)
- [モックデータ関連](モック関連のリポジトリのリンク)
```

### 使用技術

先ほど紹介した構成図で紹介した使用技術をより詳しくまとめていきます。

```md
### nodeバージョン

- node v19.5.0
- npm v9.3.1

### フロント

- [Next.js](https://nextjs.org/blog/next-13) 12.3.4
- [React](https://ja.reactjs.org/) 18.0.26
- [typescript](https://www.typescriptlang.org/) 4.9.4
- [Storybook](https://storybook.js.org/)
- [Recoil](https://recoiljs.org/) 

### スタイル

- [styled-components](https://styled-components.com/)

### ホスティング

- Vercel

### テスト関連

- [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/)
- [Jest](https://jestjs.io/ja/)
```

### 環境構築の手順

次に環境構築の手順を書いていきます。
今回はフロントエンドの環境を構築する想定でまとめていきます。

```md
# 環境変数ファイルの作成 (.envの中の値は管理者に確認)
$ cp .env.example .env

# パッケージのインストール
$ npm install

# ローカル環境の立ち上げ
$ npm run dev

下記のローカル環境にアクセスできれば OK<br>
http://localhost:3000/<br>

# フロント用のモックサーバーの立ち上げ(Dockerを起動した状態で)
$ npm run mockapi

起動して下記にリクエストを送りレスポンスが返ってくればOK
http://localhost:8080/api/xxx

※ npm install 時にエラーが出る場合

- nodeのバージョンが異なる可能性があるので下記を参考にバージョンを変えてください。

[node.js のバージョンを変更する](https://qiita.com/k3ntar0/items/322e668468716641aa5c)
```

また、初心者が詰まりやすいポイントに関しては、あらかじめ参考記事を載せておくと、より初心者も入りやすいドキュメントになるかなと思います。(質問数が減るのでコミニュケーションコストを削減できる)

### ディレクトリ構造

次にディレクトリ構造をまとめていきます。

初心者は、ディレクトリ構造の理解に時間を費やしてまうことが多いので、できるだけ丁寧に書いておくことを推奨します。

下記のコマンドをディレクトリで実行することでツリーを表示させることができるので、コピペして内容をまとめていきます。

```
tree
```

```md
本プロジェクトは``pages``配下をルーティングとして``bulletproof-react``に基づいて設計されています。

project-name/
    ├─.github         # プルリクテンプレートや自動デプロイの設定(基本いじらない)
    ├─public/
    |   ├─images/      # 画像を格納
    ├─src/
    |   ├─pages/        # ルーティングファイル
    |     ├─todo  
    |        ├─index.tsx  # /todoのパスで表示される画面
    |   ├─components    # ボタンやフォームなど汎用的なコンポーネントを格納する
    |     ├─page.tsx    # ルートファイル
    |   ├─const         # 汎用的な変数を格納
    |   ├─features/     # 機能ごとにロジックやコンポーネント型定義やstore等を管理するディレクトリ(基本ここで作業)
    |     ├─todo/       # todoという機能を追加する場合(以下todoという機能を追加する想定の参考例)
    |        ├─components  # todoで利用するコンポーネントを格納(TodoList, TodoPage等)
    |        ├─pages  # /pagesで読み込ませるページの実体
    |        ├─const  # todo機能で利用する汎用的な変数(stateの固定の初期値など)
    |        ├─hooks  # todo機能で利用するカスタムフック(API通信ロジックやstateを管理する責務を持つ)
    |        ├─stores # todo機能で利用するグローバルなstateを管理 (Recoil)
    |        ├─types  # todo機能で利用する型定義
    ├─hooks             # 汎用的なカスタムフック (トークン等の扱いなど)
    ├─lib               # ライブラリや設定済みのインスタンスをエクスポートするファイルを設置(axiosやreactQueryなど)
    ├─models/           # API通信時のデータ整合性を合わせる型定義ファイル
    ├─repository/       # API通信ロジック(/model配下の型定義を必ず参照する)
    | utils/            # 汎用的な関数を格納(時間の整形ロジックなどを格納)
    ├─stores            # 汎用的グローバルstateを管理 (Recoil)
    ├─.eslintrc.json    # ESlintの設定ファイル(基本いじらない)
    ├─.gitignore        # githubの差分に含まないものを格納
    ├─.prettierrc       # コード整形ツールprettierrcの設定ファイル (基本いじらない)
    ├─next.config.js    # Nextアプリの設定ファイル (基本いじらない)
    ├─package.json      # 設定ファイル (基本いじらない)
    ├─tsconfig.json     # TypeScript設定ファイル
```

### コンポーネントの責務早見表

フロントエンドの場合、コンポーネントの責務をドキュメントに載せておくことで、新しい人も実装方針を立てやすくなります。

また、責務を事前に定義しておくことで、コンポーネントやロジックが持つ責務の肥大化をできるだけ抑えることができます。

自分の場合は下記のようにテーブル形式で責務をまとめています。(あくまで一例)
```md
<h2 id="component-design">コンポーネントの責務早見表</h2>

各コンポーネントに関する責務は下記の通りです。(SOLID原則を参考に設計)

|  | API通信 | グローバルstate (Recoil) | style |
| --- | --- | --- | --- |
| /pages | ○ (基本カスタムフックで) | × | × |
| /feature/pages | △  | ○ | △ |
| /feature/components | × | ○ | ○ |
| /components | × | × | ○ |
```

|  | API通信 | グローバルstate (Recoil) | style |
| --- | --- | --- | --- |
| /pages | ○ (基本カスタムフックで) | × | × |
| /feature/pages | △  | ○ | △ |
| /feature/components | × | ○ | ○ |
| /components | × | × | ○ |

この責務表を見ることで、

- /pagesはルーティングの責務なのでスタイルは与えてはいけない
- component内ではAPI通信を行ってはいけない

などの開発する上での責務を掴むことができます。

### GitとGitHubの運用方法

Gitブランチの運用法とコミットメッセージの書き方を整理していきます。

これを載せておくことでブランチの切り方やコミットメッセージの書き方を統一させることができます。

これに関してはプロジェクトや会社単位で大きく変わってくるものなので一例だけ載せておきます。

```md
### ブランチについて

devlopブランチが開発環境でmasterが本番環境です。

| ブランチ名 | 役割                               | 派生元  | マージ先        |
| ---------- | ---------------------------------- | ------- | --------------- |
| master     | 公開するものを置くブランチ         |         |                 |
| develop    | 開発中のものを置くブランチ         | master  | master          |
| release    | 次にリリースするものを置くブランチ | develop | develop, master |
| feature-\* | 新機能開発中に使うブランチ         | develop | develop         |
| hotfix-\*  | 公開中のもののバグ修正用ブランチ   | master  | develop, master |

### プロジェクトを進める上での参考記事

最後にプロジェクト進める上で参考にしておくべき記事やドキュメントのURLを掲載しておきます。

多く載せすぎると混乱してしまうので最低限(5個程度)に絞って自分は掲載するようにします。

以上でREADMEの整理は終わりです。

## issueの作成

チケット管理はGitHubのissueを採用しています。(Jiraとかもある)

単純な作業(すぐに終わる作業)でも、できる限りissueを作成してタスクを振るようにしています。

issueを明確にすることで作用範囲を定義し、抜け漏れの減少やタスクの進捗状況がよりわかりやすくなります。

issueを作成する上で意識していることは下記です。

- issueテンプレートを利用する
- ラベルを適切につける
- 必要であればマイルストーンやプロジェクトに追加する

### issueテンプレートを利用する

自分は「機能追加」「バグ」の2種類のissueテンプレートをあらかじめ作成します。

テンプレートについては必要になったら都度増やす方針でよいかと思います。

issueテンプレートを作成することで下記のようなメリットがあります。

- 書き方が統一されるのでissue作成の粒度が保たれる
- 作業を伝える際の抜け漏れを減らすことができる
- 作業の完了条件を明確に定義できる

issueテンプレートの作成方法は、project直下の.githubディレクトリにISSUE_TEMPLATEを作成します。

```md
project-name/
    ├─.github 
    |   ├─ISSUE_TEMPLATE/  
         ├─bug.md   # バグ関連のテンプレート
         ├─feature.md # 機能追加関連のテンプレート
```

それぞれのファイル内容は下記の通りです。

**【バグ報告のテンプレート】**
```md:bug.md
---
name: バグ報告テンプレート
about: none
---
## :cyclone: バグの概要

- here

## :cyclone: バグの再現手順と発生環境

- here

## :cyclone: 期待する動作と実際の動作

- here

## :cyclone: 完了条件

- here

## :cyclone: 参考資料

- here
```

**【機能追加のテンプレート】**
```md:feature.md
---
name: 機能追加テンプレート
about: none
---
## :cyclone: やるべきこと

- here

## :cyclone: なぜやるのか

- here

## :cyclone: デザイン(あれば)

- here

## :cyclone: 実装する上での参考資料(あれば)

- here

## :cyclone: 完了条件

- here
```

issueテンプレートを作成することでissue作成画面において、下記のようにかんたんにissueを作成することができます。

![](https://storage.googleapis.com/zenn-user-upload/87925b34a300-20230418.jpg)

![](https://storage.googleapis.com/zenn-user-upload/175475ffc1e9-20230418.jpg)

### ラベルを適切につける

ラベルに関しては既存で用意されているものに加えて、絞り込み検索がしやすくなるように自分は下記のラベルを追加しています。(フロントエンド開発を例としている)

- coding
- api
- component

ラベルを付与しておくことで「この課題はコンポーネントの作成課題か」といった直感的にタスク内容を把握することができます。

他にも、ラベルとして締め切り日やタスクのボリュームや難易度を作成したりしています。

### マイルストーンやプロジェクトに追加する

プロジェクトを作成することで、TODOリストのように看板を作ることができます。

これはプロジェクト規模によっても変わってくると思うので適宜必要であれば作ることを推奨します。

今のGitHubプロジェクトだとガントチャートの作成もできるので、これだけでスケジュール管理もできます。

具体的なガントチャートの作り方に関しては本記事では割愛します。参考記事です。

https://www.seeds-std.co.jp/blog/creators/2023-06-26-175547/

## 開発環境の整備

フロントエンドの場合は``.eslintrc.json``や``.prettierrc``や``tsconfig.json``とコードを書く上の設定ファイルを準備します。

これらの設定ファイル一式を用意しておくことで、コード品質をチーム全体で保つことができます。

設定ファイルの具体的な内容については開発規模や思想によって大幅に変わってくるので適切なものを設定してください。

全部紹介するとキリがないので一部抜粋して自分のプロジェクトでは下記のような設定をしています。

- propsの受け渡し時に波括弧を削除 (eslint)
- 自己修了タグ(</>)の利用 (eslint)
- importの順番 (eslint)
- 未使用変数の削除 (tsconfig)
- コードの自動整形 (prettierrc)
- ダブルコーテーション (prettierrc)
等...

## コードレビュー(プルリクエスト)

コードレビュー関してはissueテンプレート同様にプルリクテンプレートを作成します。

テンプレートの内容としては下記を入れています。

- 関連する課題 (issueリンクを貼る)
- 具体的にやった内容
- 確認前のチェック事項
- 画像や動画 (あれば)
- 課題のうち、やっていないこと（あれば）
- 詰まっている箇所 (あれば)

```md:.github/PULL_REQUEST_TEMPLATE.md

## :cyclone: 関連する課題 (issue 番号と課題名)

- here

## :cyclone: 具体的にやったこと

- here

## :cyclone: 確認前のチェック事項

- [ ] 適切なコーディングルールの下で記述がされているか
- [ ] Vercelのテストは通過しているか(グリーンになっていればOK)
- [ ] ``npm run lint.fix``と``npm run lint``は実行済みか

## :cyclone: 画像や動画 (あれば)

- here

## :cyclone: 課題のうち、やっていないこと（あれば）

- here


## :cyclone: 詰まっている箇所 (あれば)

- here
```

それぞれの内容を詳しく見ていきます。

### 関連する課題 (issueのリンクを貼る)

こちらにissueのリンクを貼ることで、issueと紐づけることができます。
後で作業履歴を遡るときにも便利なのでissueとプルリクエストを紐付けることをおすすめします。

### 具体的にやった内容

具体的な作業内容を箇条書きで書いてきます。

### 確認前のチェック事項

コーディングルールやLintエラー等、レビュー前に確認すべき内容が確認できているかをチェックボックス形式で表示します。

### 画像や動画 (あれば)

コーディングや開発タスクの場合は挙動を載せます。

#### 課題のうち、やっていないこと（あれば）

課題の中で何かしらの影響(例えばAPI側に不備があったので一部の結合が未実装等)でやれていないことがあれば追記しておきます。

#### 詰まっている箇所 (あれば)

実装に詰まってまだ未実装な箇所があったらこちらに相談ベースで内容を記述します。

また出したプルリクエストがレビューから修正フェーズになったら、ドラフトモードやWIPフラグを付与して誤ったマージを防ぐようにしておきます。

## プロジェクトの開発進捗の管理について

プロジェクトの進捗管理について、完了済みのissueをもとに``定量的``に報告するようにします。
​
例えば、今週の進捗は
​
- A機能は完成
- B機能の途中
- C機能は少し進んだ
​
ネクストアクションとしては
​
- BとC機能を作りつつD機能を初めていく予定
​
という表現よりも、数値を使って下記のように表現します。
​
- A機能 (100%)
- B機能 (60%)
- C機能 (10%)
​
ネクストアクション
​
- B機能を完成させ、C機能は80%の進捗にする
- またC機能の進捗に応じてはD機能の開発にも着手する

### 最後に

いかがだったでしょうか。

今回はエンジニアがエンジニアが開発しやすい環境作りについて、個人的に実践していることを整理しました、

チームマネジメントに関してはまだまだ未熟ではあるので、エンジニアが開発しやすいだけでなく、プロジェクト全体において進めやすい環境づくりができればなと思っています。

他にも色々と記事を書いているので読んでいただけると嬉しいです。

https://qiita.com/KNR109/items/d3b6aa8803c62238d990

https://qiita.com/KNR109/items/5d4a1954f3e8fd8eaae7

https://qiita.com/KNR109/items/550b52ff980c0c32bf2a