はじめに
先日インターンに参加し、Gitを用いたチーム開発を経験しました。
今まで開発といったら個人開発だったので、色々学ぶことが多かったです。
今回はそれらをまとめ、開発の各段階で意識しておくべきことを書いていきたいと思います。
要件定義・基本設計
まずは要件定義が必要です。今回のインターンではざっくり「入力データを取得し、宣伝用のドキュメントを生成するWebアプリ」という要件が示されました。
そこからは「データを入力する」「データを成型する」「ドキュメントを生成する」といった要件が考えられましたが、他にもあったほうが良い機能などが考えられたので、それらを一覧としました。この辺はブレインストーミングみたいな感じですね。
その後、それらの要件をどのように実現するかを考えました。これが基本設計です。開発すべきものを機能単位で分割し、それぞれの機能をどのように開発していくのかを考えました。
また、WebアプリだったのでGUIで動作します。そのため、デザインも考える必要がありました。これについては、まずFigmaでデザインを作成し、それを元にCSSを書いていくという流れにしました。
これらの作業をまとめて「上流工程」というらしいです。
役割分担
次に役割分担を行います。実装する機能などは基本設計のフェーズで決めているので、具体的にどの機能を
また、ある機能が完成しないと次の機能が進められない場合もあるので、その辺りも考慮して役割分担を行いました。
例えば、データを成型する機能はデータを取得する機能が完成していないと進められないので後回しにする、などといった感じです。
全体のデザインなどは他を待たずにすぐに始められるといった印象でした。
コンフリクトを避けるため、誰がどのファイルを編集するか、という観点で役割を分担するとよいです。
ブランチ分け
基本的に、「各ブランチでの作業は他のブランチに影響しない」という方針を取ると良いと思います。
例えば、デザイン関係のブランチ、データ取得関係のブランチ、データ成型関係のブランチなどに分けるといいかもしれません。
インターンではReactを用いたので、コンポーネントごとにブランチを分けていました。
本当はまずdevelop
ブランチを作り、そこから各ブランチを切って作業を行い、最終的にmain
ブランチにマージするという流れが一般的だと思います。今回はいきなりmain
ブランチからブランチを切って作業を行っていました。
ブランチの命名規則
ブランチの名前を適当に決めると、何をやっているブランチなのかが分かりづらいです。そのため、適切な命名規則をチーム内で決めておくと良いと思います。
今回は5daysインターンで、アプリを作るだけだったので、専らfeature/
で始まるブランチ名を使っていました。これは、そのブランチが新しい機能を追加するブランチであることを示しています。
他には、fix/
のようにバグ修正を行うブランチ、hotfix/
のように緊急のバグ修正を行うブランチ、release/
のようにリリースを行うブランチ、review/
のようにレビューを行うブランチなどがあると思います。
変数名、関数名、ファイル名の命名規則
変数名、関数名、ファイル名なども適切な命名規則を決めておく必要があります。これはそれぞれの役割を明確にし、コードを読みやすくするために重要です。また、他の人がメンテナンスをする際にも役立ちます。
開発フレームワークにもよりますが、例えばReactの場合、以下のような命名規則があります。
- コンポーネント名
- UpperCamelCase(PascalCase)
- 毎単語の先頭を大文字にする
- 例:
MyComponent
- ファイル名
- コンポーネント名と同じ
- 例:
MyComponent.tsx
- 基本的に、コンポーネントは1ファイルに1つだけ
- 関数名、変数名
- camelCase
- 先頭は小文字、それ以降の単語の先頭は大文字にする
- 例:
myFunction
- A(Action)/HC(High Context)/LC(Low Context)Patternというものもある
- 基本的に、「何をする-何を-どのように」みたいな感じ
- 例:
fetchDataFromAPI
- 定数名
- 全て大文字
- 単語間はアンダースコアでつなぐ
- 例:
MY_CONSTANT
また、複雑な動作をしている関数などにはコメントアウトで入出力例などを示しておく、といったことも重要です。
コミットメッセージの書き方
コミットはこまめに行うようにしていました。これによって変更を細かく記録し、何かあったときに追跡しやすくなります。
コミットの際はコミットメッセージなどを書く必要がありますが、その際も適切な書き方を意識することが重要です。
自分は以下のような書き方をしていました。コミットのタイプを書き、そのあとにやったことを簡単に書いておく、といった感じです。
<type>: <message>
詳しくは以前の記事に書いてあるので参照してください。
プルリクエスト・コードレビュー
自分の担当するブランチでの作業が終わったら、それをmain
ブランチ(master
かも)にマージし、変更を反映させますが、いきなりマージすると問題が起きる可能性があるので、まずプルリクエストを作成し、レビューを受け、問題がないことを確認してからマージします。
Slack等がある場合、プルリクエストのページのURLをメンション付きでレビュワーに共有するといいみたいです。これ、自動化できたら便利そうですね。
レビューをもらったら、該当のブランチをmain
ブランチにマージし、変更を反映します。
この時、差し支えがなければ混乱を避けるためにも反映したブランチは削除するといいです。
git branch -d <branch-name>
でローカルのブランチを削除し、git push origin --delete <branch-name>
でリモートのブランチを削除できます。
また、GitHub上でリモートブランチを削除し、それをローカルで反映するにはgit fetch --prune
を使います。この操作により、他の人がリモートブランチを削除した際にそれがローカルに残ってしまうということを防げます。いちいちコマンドを打つのが面倒な場合は、git config --global fetch.prune true
を打ち込んでおくと、この作業が自動で行われるようになります。
コンフリクトの解消
複数人で同じファイルを編集してしまうとコンフリクトが発生します。その場合、それを解消しなくてはなりません。
基本的にはコンフリクト解決ツールをGit上で行い、残す変更と消す変更を分類する作業を行いますが、複雑なコンフリクトに関してはいったんローカル上で解決しなければなりません。
基本的にコンフリクトを発生しないようにすることが重要なので、役割分担の時点で同じファイルを編集しないようにしたり、同じファイルを編集しなくてはならない場合は相談しながら進める、などといったことが大切になるかなと思います。
待ちの解消
ある人の作業が終わらないと別の人の作業が進められない、という状況もよくあります。実際自分は自らのタスクが終わった後他の人の実装待ちになりました。
そんな時は、他の人の作業を手伝ったり、仮の実装を行うなどをして、とにかく手を止めないことが大切だと感じました。
この辺りは役割分担や作業計画の段階で考えておくべきだと感じました。
コミュニケーション
コードの意図が伝わっていなかったり、連絡をしているもののプルリクエストのレビューをしてくれなかったりといったこともありました。
そういう時は、直接話すことが大切だと感じました。対面でのインターンだったので、積極的に声かけや相談をしていました。
もしオンラインだったらコミュニケーションも多少難しくなるのかな、と思います。
また、オンラインの場合は即レスが重要になるでしょう。通知を入れておいたり、定期的にチャンネルを確認したりなど、何かあったらすぐに返事ができるような体制づくりが必要になります。
おわりに
Gitを用いたチーム開発は非常にやりがいがありましたが、様々な注意事項があるんだなと感じました。
個人開発では気にしなくてよいことも、やはりチームで開発するときには大きな問題になってくるんだなと感じました。
将来働くとき、個人で開発してそれをどこかに売り込むってことはおそらく少ないと思うので、今のうちからチーム開発の経験が出来たことは非常に良かったと思います。
普段個人開発する際にもチーム開発を意識したGitの運用をすると良い練習になるのではないでしょうか。
ではまた、次の記事でお会いしましょう。
参考文献
要件定義とは?決定までのプロセスや要件定義書の進め方について