失敗しないチーム開発のプロセス

[株式会社Never](https://neverjp.com/)のshoheiです。

株式会社Neverは「NEVER STOP CREATE 作りつづけること」をビジョンに掲げ、理想を実現するためにプロダクトを作り続ける組織です。モバイルアプリケーションの受託開発、技術支援、コンサルティングを行っております。アプリ開発のご依頼や開発面でのお困りの際はお気楽にお問合せください。

https://neverjp.com/service/

# 概要

弊社で実施しているチーム開発の進め方を紹介します。

開発プロセスのベースとして `要件定義 → デザイン → 設計 → 実装 → テスト（単体・結合・受け入れ） → リリース` で進めています。

本記事では、要件定義とデザインを終え、タスク起票後の <b>「設計 → 実装」</b> プロセスの内容を取り上げます。なお、バックエンドの作業は割愛し、Flutterアプリ開発チームに必要な作業に着目して説明します。

# 開発の進め方

アプリの設計をした後に実装へ移っていきます。それぞれの作業を順番に説明します。

## 設計プロセス

設計プロセスの作業順です。

`データソースの設計 → 技術選定 → 内部設計 → ディレクトリ構成`

|作業|詳細|備考|
|---|---|---|
|データソースの設計|DB設計<br>ファイルストレージの設計| アプリ内で永続化する情報を整理する |
|技術選定|状態管理| BLoC, Provider, Riverpod |
||画面遷移|Navigator 1.0, go_router, auto_route |
||静的解析|pedantic_mono, very_good_analysis |
||外部パッケージ|画像キャッシュ、APIクライアント、DBクライアントなど実装に必要なパッケージを選定 |
||SDKバージョン管理|fvm, asdf |
||Xcodeバージョン管理|xcodes |
||OSバージョン|Android 9, iOS 15以上などのバージョンを選定 |
|内部設計|Presentation + Domain + Infrastructureの3層を軸とした軽量な設計| [株式会社Neverの設計指針 - 設計](https://www.notion.so/Never-0ee09657e5744cc8bb3c99cf9cdb2cff?pvs=4#c2f8b3e570c84ffbadaba7911dc86245) |
|ディレクトリ構成選定 |LayerFirst<br>FeatureFirst| [株式会社Neverの設計指針 - ディレクトリ構成](https://www.notion.so/Never-0ee09657e5744cc8bb3c99cf9cdb2cff?pvs=4#4854a8bb9b76496e9c2fc08a7c31f617) |

設計プロセスでは要件に耐えれる事とチームメンバーが円滑に作業できるよう技術選定や設計をします。チャレンジしたい技術があれば提案し、要件的に問題なければ決定します。


最初は時間がかかると思いますが、1回やっておけば2回目以降のアプリ開発では同じ設計プロセスで開発した実績があるので、それをベースにスムーズに作業できます。

なお、実装プロセスの際に選定した技術が要件的に耐えれないとわかった場合は技術選定 → 設計をしなおします。その場合は開発コストを見積もってチーム内で相談して決めましょう。

## 実装プロセス

実装プロセスの作業順です。

`雛形作成 → 実装タスク → 開発効率化タスク（余裕があれば）`

|作業|詳細|備考|
|---|---|---|
|雛形作成|設計で決まったものを導入| 決まった設計とディレクトリ構成で雛形を実装する。ファイルがない場合は`.gitkeep`を入れたディレクトリを作成する。事前に必要とわかっているパッケージを導入する。時間に余裕があればflavor設定を入れても良い。|
||1画面のサンプルコード、テストコードのサンプル導入| メンバー間での実装方針を統一するためにサンプルコードとテストコードを導入する。|
||README記載|ビルド方法、設計＆実装指針、設計書のリンク等を記載する。|
|実装タスク|画面実装<br>機能実装<br>画面と機能の結合実装 | 後戻りコストを抑えるためタスクを分割する。例えばプロフィール機能のタスクであれば<br><br>プロフィール機能（画面）<br>プロフィール機能（機能）<br>プロフィール機能（結合）<br><br>の粒度で分割して進める。|
|開発効率化タスク | fastlane、アプリ配布サービス、CIなど | 無くてもいいが、あったほうが嬉しい。 |

雛形を先に作っておけば、どういう実装にすれば良いのかサンプルコードを見ればわかるので作業効率が上がります。

READMEにルールや環境構築＆ビルド方法が記載されていれば`git clone`してから動作確認までスムーズに作業できます。

実装タスクは1機能を3つのタスクに分割すれば作業しやすいと思います。

|作業|詳細|
|---|---|
|画面実装|デザイン通りにUIを実装する。ダミーデータを用意し、状態を表現する。|
|機能実装|データソースの状態を扱うビジネスロジックを実装する。|
|結合実装|画面と機能を結合して、１機能として動くように実装する（画面に命を吹き込む！）|

分割した作業毎にPR（Pull Request）を作成します。

１機能の規模がそこまで大きくなければ全ての作業を1PRで実施してもよいし、既に画面実装が終えていれば機能と結合を同じPRで作業しても良いです。

## 定例

週に1回の頻度で1時間程度の定例を行います。定例のアジェンダは以下の通りです。

- 共有事項の報告
- 担当者からの進捗報告＆デモ
- 次やることを確認＆新しいタスクの担当決め

進捗報告時のデモはとても有効です。デモは実際にアプリを動かして共有します。出来上がったアプリを確認できるのでチームの士気が上がりますし、挙動に誤りがあればそこで指摘できますし開発終盤での後戻りコストを抑えることができると思います。

# 作業を担当する

例えば、以下のチームでアプリ開発を考えます。

- リードエンジニア
- ジュニアエンジニア（未経験）

基本的には設計や難しい実装タスクはリードエンジニアが行い、設計が決まった実装タスクで比較的簡単なものやオンボーディングタスクをジュニアエンジニアが行います。

例えばプロフィール機能のタスクでは以下のようになります。

|作業|難易度|担当|
|---|---|---|
|プロフィール機能（画面）|低|ジュニア|
|プロフィール機能（機能）|中|リード|
|プロフィール機能（結合）|高|リード|

※ 難易度はあくまでも例

ただ、このまま開発を進めていくとリードの負担が大きいままです。いくつかタスクが消化できたら徐々に機能や結合実装をジュニアにアサインしましょう。ジュニアのレベル感や成長過程を見てアサインするタスクを判断できれば良いですね。

不具合改修タスクも同様です。

最初は難易度の低いタスク（既に修正方法がわかっているタスク）をジュニアにアサインし、徐々に難易度の高いタスク（調査しないと修正方法が分からないタスク）を渡せるようにしましょう。

ここのタスクの移行がうまくいかない場合は、後述するペアプログラミングでジュニアのスキルアップを図ります。


## 進捗の見える化

タスクの進捗を見える化するための手順です。

- 着手した段階で作業ブランチを作り、Draft（WIP）でPRを作る
```sh
# 作業ブランチを作り、空コミットをプッシュする
git branch <ブランチ名>
git commit --allow-empty -m "first commit"
git push origin <ブランチ名>
```
- 対応内容のチェックリストを作り、完了したらチェックをつける
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183031/83d90efc-9e3d-7ba6-3bb3-9f6435dae8f4.png" width="70%"/>


そうすることで、PRの一覧からタスクの進捗（2 of 5 tasks）が分かります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183031/2b1f0149-973e-6442-b5c7-59b8b865450e.png" width="70%"/>

## 担当者の開発速度を計測

TODO

# コードレビュー
実装タスクのコードレビューをエンジニア間で行います。

## 実装方針 & レビュー観点を共有する
実装前に実装方針やコードレビュー観点をチーム内で共有できれば、安心して作業ができます。

詳しくは、[株式会社NeverのFlutterコーディング規約5選](https://qiita.com/hukusuke1007/items/80d9548a352560d9dcc3)をご確認ください。

## レビューコメントの付け方
レビューコメントを見るとドキッとしますよね。そのドキッとだけならいいですが、心を痛める場合も無きにしも非ず...

また、テキストベースなのでコメントの温度感を伝えるのもなかなか難しいです。

それらの課題を解消するために、コメントの先頭にラベルをつけます。また、コメントの語尾を優しい表現にするとレビューイはより安心できると思います。

|ラベル|詳細| 例 |
|---|---|---|
|IMO(In my opinion)|自分なら直すけどどう? 緩やかな指摘|`[IMO] ここの文字列は定数化して管理したいですね。`|
|MUST| 必ず直すべき|`[MUST] この実装だと持っている要素数を超えて配列にアクセスしてしまうので事前に配列の個数をチェックしてからアクセスしましょうか。`|
|Q(Question)|質問|`[Q] この実装はドキュメントのどこに書かれていますか？勉強も兼ねて確認がしたく！`|
|nits(nitpick)|細かい指摘|`[nits] 対象外のコードに改行が入っちゃってます！`|

ちなみに、レビューワーとレビューイのお互いの信頼関係が構築されていれば、ラベルがなくてもうまく運用できると思いますが、構築されるまでラベルを付与しましょう（笑）

## メンバーの士気を上げる
褒める事を意識しましょう。例えば良い実装をしていればレビューコメントで「この実装良いですね👍」と伝えるのものありです。

また、PRを承認した際にLGTM（Looks good to me）をコメントに添えてやるとレビューイの士気が上がります。

私は、[LGTM Moon](https://lgtmoon.herokuapp.com/)の画像を承認と同時に貼り付けています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183031/99b7d0eb-8a54-5dc4-f7ee-09396362c6ae.png" width="60%"/>


# 教育

チームメンバーがうまくワークしない場合は、チーム内で教育します。

あれ？ワークしていないかも？と気づくタイミングとしては

- 期限までにPRが来ず、タスクの進捗が悪い
- コードレビュー時に指摘対象の質が悪い

この場合、しっかりヒアリングしてメンバーが持つ課題感を認識します。

- 仕様が分からない → 細かい仕様を明確に伝える
- 実装方法が分からない → アルゴリズムを伝える
- アルゴリズムを伝えても分からない → たくさん勉強してもらう

[実装方針 & レビュー観点](#実装方針--レビュー観点を共有する)をしっかり共有できているか、確認できているかも伝えましょう。特にコードレビューでの課題がある場合は、この辺りの認識をレビューワーとレビューイで合わせれば良くなってくると思います。

## 技術力を上げるためには考えてコードを書くしかない

経験談になりますが、技術力を上げるためにはやはり**考えてコードを書きまくる**のが大事です。

特に今まで実装したことない画面や機能のコードを書くことが大切です。実装経験がないので必然的に何をどうやって実装しようかと考えてコードを書くことができます。この経験を多く積めば、実装方法の引き出しも増えて様々な要件に耐えれるスキルが身につきます。

オススメはよく使っているアプリの模写です。例えば私でしたらX（旧：Twitter）のアプリが好きなので、そのUIを模写した後にアレンジしたUIを自分のアプリに取り入れていました。

## ペアプログラミング
チームメンバーのスキルアップには[ペアプログラミング](https://ja.wikipedia.org/wiki/%E3%83%9A%E3%82%A2%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)が有効です。

詳しくは、[実践・ペアプログラミング](https://qiita.com/hukusuke1007/items/888c0ef0c1b604cc87a5)をご確認ください。

## 面談

マネージャーとメンバーが1対1でお話します。1on1とは違ってここでは以下のアジェンダで話をします。

- メンバーに心境を語ってもらう
    - 実際に開発をしてみてどうだったか、ざっくばらんに話をしてもらう
- メンバーに対してフィードバックをする
    - 良い点と改善点を伝える
- 課題を確認し、メンバー自らが解決のためのアクションを見つける
    - こちらからアドバイスはせずに傾聴する

ワークしないメンバーへのサポートはかなり難しいです。ワークしない理由は本人しかわからないからです。

方法としては、こちらから一方的にアドバイスをするより、メンバー自らが課題解決の具体的なアクションを見つけて遂行してもらうのが良いと思います。

メンバーが見つけたアクションを聞いてしっくりこなければ

**「それを実行して今までできなかったタスクができるようになりますか？」**

と質問を繰り返して再度確認します。不安はありますがやってみて多分できそうといった回答であれば、メンバー信じてやってもらいます。

### メンバーの不安を解消する

ヒアリングをしていくと、あることが理由でメンタルの調子が悪く、パフォーマンスに影響がでているかもしれません。

このような不安を解消することで、キャッチアップのパフォーマンスが高くなり、上手くいくことがあります。

よくあるメンバーの不安な事例としては以下の通りです。

- チーム内で想像以上に期待されていてプレッシャーを感じる
- 他のメンバーはできているが、自分だけができない
- プライベートなことで不安を抱えている

様々な不安がありますが、不安を解消するためには、Notionやメモアプリに不安を書き出して整理することをオススメします。そして、その不安を解消するためのアクションも書きます。

```md
チーム内で想像以上に期待されていてプレッシャーを感じる
→ 上司との1on1や定例等で自己開示をして、自身のレベルを知ってもらう（自分の弱さを伝える）

他のメンバーはできているが、自分だけができない
→ 他人と比較をしない、今自分ができることを全力で務める

プライベートなことで不安を抱えている
→ 不安を放置せず、暫定でも良いのでちゃんと解決するアクションを決める
```

気持ちがとてもスッキリしますので、ぜひメンバーに勧めてみてください。


# 最後に

チームで楽しく良いアプリを作っていきましょう👍