📗

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

2023/04/19に公開

はじめに

自分は渋谷のWeb系開発会社にて執行役員兼エンジニアをやっています。(新卒入社3年目)

直近では6~8名程のエンジニアがいるプロジェクトで、ディレクトリ設計やissue作成、コードレビュー、スケジュール管理、PMへのUI/UX及び機能提案などを行なっています。

その中で自分が「エンジニアチームにとって開発しやすい環境整備」を色々試し、実践してきたので整理していきます。

この記事の主な対象者

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

おことわり

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

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

5つのセクションに分けて紹介していきます。

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

ドキュメント整備について

エンジニアが開発に入る際に必ず見るドキュメント「README」の書き方を整理をしていきます。

自分がREADMEを作成する時は「プロジェクトに新しくアサインされたエンジニア(初級レベル)の人が読んでもプロジェクトの開発概要をつかみ、スムーズに作業に入れること」を意識しています。

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

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

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

目次

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

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

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

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

コーディングルール

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

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

自分がプロジェクト内でCONTRIBUTING.mdに書いている内容は

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

上の3つに関しては基本情報を載せます。

コーディングルールの章には、本プロジェクトにおいて下記のようなルールを定めておきます。
※ フロントエンド系のプロジェクトを例に紹介しています

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

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

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

CONTRIBUTING
### propsは展開せずに使う
理由: propsから渡ってた値だと区別がつけやすいので

【GOODexport const MyPage: React.FC = (props) => {
  return <p>{props.title}</p>
}BADexport const MyPage: React.FC = ({title}) => {
  return <p>{title}</p>
}

開発構成の概要

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

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

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

図解の作成ツールとしてKeynoteやパワポ、diagrams.netなどがあります。

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

各種リポジトリのリンク

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

  • project-name-web (フロント側)
  • project-name-app (サーバー側)
  • project-name-spec (APIの定義ドキュメント(OpenAPI)やモックデータの検証用)
<h2 id="repository">各種リポジトリのリンク</h2>

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

使用技術

こちらでは、先ほど紹介した開発構成の概要で紹介した使用技術をより詳しく掲載します。

### 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/)

環境構築の手順

ここでようやく環境構築の手順を書いていきます。
フロントエンドの環境を構築する想定でサンプルは書いているので、適宜書き換えてください。

# 環境変数ファイルの作成 (.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)

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

ディレクトリ構造

ディレクトリの構造を書くことで新しくプロジェクトに入った人がスムーズに作業に入れます。

初心者の場合、ディレクトリ構造の理解に時間を費やしてしまうので、可能な限りは丁寧に書いておくことを推奨します。

下記のようにサンプルとして下記ます。

本プロジェクトは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設定ファイル

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

コンポーネント等の責務をドキュメントに載せておくことで、プロジェクトに入りたての人でも実装方針を立てやすくなります。

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

自分の場合は下記のようにテーブル形式で責務をまとめています。(あくまで一例)

<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ブランチの運用法とコミットメッセージの書き方を整理していきます。

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

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

### ブランチについて

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

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

### コミットメッセージの記法

fix:バグ修正
hotfix:クリティカルなバグ修正
add:新規(ファイル)機能追加
update:機能修正(バグではない)
change:仕様変更
clean:整理(リファクタリング等)
disable:無効化(コメントアウト等)
remove:削除(ファイル)
upgrade:バージョンアップ
revert:変更取り消し

また、GitHubは課金することでDraftモードの利用でマージ制限やmainブランチへの直接pushの制限などができるのでおすすめします。

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

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

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

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

issueの作成について

基本的に開発作業についてはGitHubのissueを採用しています。(Jiraとかもある)

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

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

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

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

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

自分は「機能追加」「バグ」の2種類のissueテンプレートをあらかじめ作成します。テンプレートについては必要になったら都度増やす方針でよいかと思います。

issueテンプレートを作成することで下記のようなメリットがあります。(個人的に感じている)

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

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

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

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

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

- here

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

- here

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

- here

## :cyclone: 完了条件

- here

## :cyclone: 参考資料

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

- here

## :cyclone: なぜやるのか

- here

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

- here

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

- here

## :cyclone: 完了条件

- here

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

ラベルを適切につける

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

  • UIの実装
  • APIの結合
  • コンポーネント

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

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

必要であればマイルストーンやプロジェクトに追加する

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

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

開発環境の整備について

.eslintrc.json.prettierrctsconfig.jsonとコードを書く上の設定ファイルを準備します。

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

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

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

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

コードレビューについて

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

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

  • 関連する課題 (issueのリンクを貼る)
  • 具体的にやった内容
  • 確認前のチェック事項
  • 画像や動画 (あれば)
  • 課題のうち、やっていないこと(あれば)
  • 詰まっている箇所 (あれば)
.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エラー等、レビュー前に確認すべき内容が確認できているかをチェックボックス形式で表示します。

画像や動画 (あれば)

UIの開発タスクの場合は動画や挙動を載せます。

課題のうち、やっていないこと(あれば)

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

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

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

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

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

プロジェクトの進捗管理について、完了済みのissueをもとに定量的に報告するようにします。

例えば、今週の進捗は

  • A機能は完成
  • B機能の途中
  • C機能は少し進んだ

ネクストアクションとしては

  • BとC機能を作りつつD機能を初めていく予定

という表現よりも、数値を使って下記のように表現します。

  • A機能 (100%)
  • B機能 (60%)
  • C機能 (10%)

ネクストアクション

  • B機能を完成させ、C機能は80%の進捗にする
  • またC機能の進捗に応じてはD機能の開発にも着手する

余談

自分が新卒1年目だった頃に強強エンジニアの先輩が「壊しても俺が治すから大丈夫だよ。色々試してみて」と言ってくれたおかげで、安心して開発業務に入れたので、自分も初心者には同じことを言ってます。
(まだ壊されたことはない)

最後に

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

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

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

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

https://zenn.dev/sutamac/articles/27246dfe1b5a8e

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

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

Discussion