Findyの爆速開発を支えるタスク分解

こんにちは。

ファインディ で Tech Lead をやらせてもらってる戸田です。

既に皆さんも御存知かと思いますが、弊社では開発生産性の向上に対して非常に力を入れています。

以前公開した↓の記事で、弊社の高い開発生産性を支えている取り組み、技術についてお話させていただきました。

tech.findy.co.jp

ありがたいことに、この記事を多くの方に読んでいただき反響をいただいております。

そこで今回は、↑の記事でも紹介されている「タスク分解」について更に深堀りしてお話しようと思います。

タスク分解は、弊社にJOINしたら最初に必ず覚えてもらう最重要テクニックの中の1つです。

それでは見ていきましょう!

タスク分解とは

何かしらの開発タスクを任されたあなたが最初にやるべきことは何でしょうか?

もしいきなりコードを書き出す人がいるのであれば、この記事を読むことをオススメします。

開発タスクを任された際、まず最初にタスクの洗い出しを行い、それらを可能な限り分解していきましょう。

分解したタスク毎にPull requestを作成することで、自然とPull requestの粒度を適切に保つことが可能になります。

まずはタスク分解におけるメリットを紹介します。

メリット

事前に対応方針の認識を合わせやすくなる

弊社ではGitHubのIssueにタスクリストを作成し、実装着手前にタスクリストをレビューしてもらうようになっています。

実際に対応する内容と、考えているタスクの内容が一致しているのか、対応する順番は適切か、などを確認して実装着手前に認識を合わせるようにしています。

これからのタスクの予定を目に見える形で確認することが出来るので、事前に対応漏れや考慮漏れに気づきやすくなり、手戻りの発生が減ります。

これにより工数見積の精度も上がり、開発スケジュールが大きくずれ込むことを防ぐことが出来るようになります。

Pull requestの粒度を適切に保つことが出来る

基本的に作成したタスクごとにPull requestを作成することになります。

Pull requestの粒度が大きくなってしまう原因の1つに、「やるべきことがどんどん増えていって、結果的に大きくなってしまった」というものがあります。

しかし、事前にタスクをある程度の粒度で切り出しているため、Pull requestを作成している途中に肥大化してしまうことが少なくなります。

それでも考慮漏れなどでPull requestの粒度が大きくなってしまうこともゼロではありません。その場合、着手中のタスクの粒度が大きいと判断し、そこから更にタスクを分解するようにします。

実装中にタスクを細分化することにより、意図しないPull requestの肥大化を防ぎ、結果的に適切な粒度のタスクリストに近づくようになります。

また、Pull requestのレビュワーからの視点だと「これからどんな事をしようとしているのか」がIssue内のタスクリストによって把握することが出来るようになります。

そのため、Pull requestの粒度が細かい状態でレビュー依頼が来たとしても、局所的なレビューではなく全体像をある程度把握した上でのレビューが可能となります。

進捗管理、引き継ぎをしやすくなる

タスクリスト内の終わったタスクにはチェックを入れ、進捗管理としても利用します。

全体を通してやるべきことと現在終わっていることがタスクリストを見ることで一目でわかるようになっているため、開発の進捗がどうなっているのか確認出来るだけでなく、他のメンバーに開発の引き継ぎをしやすくなります。

タスクの作り方

まず弊社では、GitHubのIssueのテンプレートにタスクリストの項目を用意しています。

---
name: Feature request
about: 新機能や改善等の仕様用

---

## なぜやるのか
<!-- やることになった背景等を書く -->


## ゴール
<!-- これをリリースすることで何を達成したいのか -->


## 仕様
### 概要
<!-- 量が多ければ、概要と詳細に分ける -->
<!-- 期待する・期待しない動作を書く -->

### タスクリスト
- [ ] add task

## 補足事項
### 懸念
<!-- 気になる点や仕様上での懸念事項等あれば記載する -->

## 関連Issue

このように、Issueを作成し開発に着手する前にタスクリストを作成することが必要であることを明確にしています。

また、チェックボックスで作成したタスクからIssueを直接作成する機能などもGitHubから提供されているので合わせて確認してみてください。

docs.github.com

具体例

例えば、「ユーザーデータの一覧を返すREST APIを追加する」タスクが割り振られたとしましょう。

これだけだと、タスクリストの初稿はこうなります。

- [ ] ユーザーデータの一覧を返すREST APIを追加する

これだけでは何がどう必要なのか、具体的によくわかりませんね。そこでPdMに確認すると、次のような要望が上がっているとのことでした。

- 登録しているユーザーの一覧を表示したい
- idとnameで絞り込みが出来るようにしたい

現状わかっている要件だけでタスク分解をしてみましょう。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [ ] データベースからユーザーデータの一覧を取得して返す
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] name

とりあえず「動くもの」であれば、これだけで実装できそうです。

この状態でフロントエンド担当のメンバーにレビューしてもらいましょう。画面モックを確認するとページネーションとソートの機能が必要であることがわかりました。

ここでタスクを追加しておきましょう。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [ ] データベースからユーザーデータの一覧を取得して返す
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] name
  - [ ] ページネーションに対応する
  - [ ] ソートに対応する
    - [ ] idのasc/desc

要件や必要な機能が少しずつ明確になってきましたね。次に他のバックエンドエンジニアにレビューしてもらいましょう。

すると、「nameの検索条件は完全一致、部分一致のどっちなのか?」という指摘をもらいました。

確かに画面モックから読み解くのは難しかったです。PdMと議論し、部分一致で実装することに決定しました。

ここで既存のタスクを修正しましょう。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [ ] データベースからユーザーデータの一覧を取得して返す
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] nameの部分一致
  - [ ] ページネーションに対応する
  - [ ] ソートに対応する
    - [ ] idのasc/desc

一通りの要件はこれで揃ったようです。これで実装に着手していきましょう。

ところが実装を開始してテストコードを書いていると、退会ユーザーのレコードが存在している可能性が出てきました。この場合、退会ユーザーは一覧に表示したくありません。

この要件をタスクリストに追加しましょう。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [ ] データベースからユーザーデータの一覧を取得して返す
    - [ ] 全件返す
    - [ ] 退会ユーザーは一覧から除外する
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] nameの部分一致
  - [ ] ページネーションに対応する
  - [ ] ソートに対応する
    - [ ] idのasc/desc

ひとまず全件データを返すところまでPull requestで対応して、別のPull requestで退会ユーザーを一覧から除外するコードを追加すればOKです。この様に、実装中にタスクを更に細分化することも十分ありえます。

ひとまず退会ユーザーを一覧から除外するところまで対応が完了したので、チェックボックスにチェックを入れて進捗を管理します。

- [ ] ユーザーデータの一覧を返すREST APIを追加する
  - [x] データベースからユーザーデータの一覧を取得して返す
    - [x] 全件返す
    - [x] 退会ユーザーは一覧から除外する
  - [ ] 絞り込みに対応する
    - [ ] id
    - [ ] nameの部分一致
  - [ ] ページネーションに対応する
  - [ ] ソートに対応する
    - [ ] idのasc/desc

チェックを入れて進捗を管理することで、完了しているタスク、していないタスクを一目で確認することが可能になり、他のメンバーに開発の引き継ぎをしやすくなります。

今回は極端な例で紹介しましたが、タスクリストの作り方、整理の仕方を具体的に理解できたかと思います。

良いタスクリストを作るコツ

良いタスクリストを作成するためのコツは、最初から完璧なタスクリストを作ろうとしないことです。

まず最初に大枠のタスクを考え、そこから分解していくように意識してタスクリストを作成すると、結果的に詳細なタスクリストが完成しています。

小さくコツコツと修正を上乗せしていき、最終的に完成形に近づけていくような分解の仕方が良いでしょう。

大きな機能の実装担当になった際に、一度に全ての機能を実装するのではなく、小さい機能追加を何回も繰り返して結果的に大きな機能を完成させるようなイメージを持つと良いです。

まとめ

いかがでしたでしょうか?

実装コードを書く前の準備は非常に重要です。タスク分解の精度を上げることにより、結果的にスピード感を持った開発を行うことが出来るようになります。

現在、ファインディでは一緒に働くメンバーを募集中です。

興味がある方はこちらから ↓ herp.careers