$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

スムーズに進行するためのエンジニアリングタスク分割の工夫

会社の振り返りで「エンジニアリングの作業タスクがうまく分割できていそうだったが、その知見を共有してほしい」と言われたので、自分がどう考えてタスク分割をしているかをこの記事で共有したい。

この記事のスコープとすること・しないこと

今回の記事では、あるユーザーストーリーが存在するとして、その設計・実装・テストなどをスムーズに進行するための工夫について書く。

逆に次のようなタスク分割については取り扱わない。

  • ユーザーに提供すべき価値があるとして、それをユーザーストーリー単位に分割する
    • このトピックは今回の記事より前段の話である
  • 実装の時のPullRequest分割手法
    • このトピックは今回の記事より後段の話である。実際には今回の分割より細かくPRを送ることが多い

タスク分割をするときの工夫点

自分が分割するときは次のことに気をつけて分割している。

  • 少なくとも1スプリント以内で終わるタスクになっている
  • 完了条件が明確である
  • 開始から終了まで他タスクによる待ち時間がない
  • 他タスクが待ち状態になる時間を最小限にする
  • 自分にとって難易度の高いものが1タスクの中で1つである
  • 初めから完璧なタスク分割を目指さない

少なくとも1スプリント以内で終わるタスクになっている

大前提として、1スプリント以内で終わるタスク粒度で分割している。1スプリントは1~2週間で設定しているチームが多いと思うが、これまでの経験上はこの期間を超えるタスク粒度にすると問題が起こりやすい。たとえば

  • ユーザーストーリーへの理解が甘くなり、タスクをやっている最中に新しい課題が発見されがち
  • チームの他のメンバーから進捗状況が見えづらい
  • 終わるまでの期間が長く、自分のモチベーションを維持しづらい

これは一番簡単にできる工夫と感じている。「1スプリントで終わる粒度だよな」と自問しながらタスク分割をすると、ユーザーストーリーの中で曖昧な部分や難易度の高い部分にも気づきやすい。

もちろんやってみたら思ったより難しくて1スプリント超えちゃったというのは問題ない。1スプリントに収まるように意識すること、もし収まらなかったら振り返って次に活かすことが大事だ。

完了条件が明確である

タスクを1つずつスムーズに完了させるには、完了条件が明確であることも大事だ。僕はタスクの説明文に完了条件を明記することが多い。

たとえば「実現可能性の調査をする」というタスクだと曖昧なままずっと続いてしまうことが多い。そうではなく「Proof of Conceptとして実装をし、実現可能であることを明確にする」というタスクにした上で

  • Proof of Conceptの実装をPullRequest形式で作れている
  • 基本方針が実現可能であることを説明するサマリー文書を作れている
  • 実現可能か不明瞭かつ調査に時間がかかる箇所が新しく見つかれば、難しい部分を検証する追加タスクを作れている

のように完了条件をつけるようにしている。こうすれば完了のために出すべき成果物がはっきりするため、完了に一直線で向かえる。また終わっているか終わっていないか分からないという状態にならないため、ずるずるとタスクが長引くことも防げる。

開始から終了まで他タスクによる待ち時間がない

他の人が担当しているタスクによる待ち状態は基本的に自分ではコントロールできない。途中で待ち状態が発生してしまうようなタスクの切り方をすると、着手したが完了できずに待ち状態のまま置いてあるタスクが何個もできてしまう。この状態になると地味に頭のリソースを待ち状態のタスクに取られてしまい効率が悪くなる。

こうならないように、開始から終了までは他タスクによる待ち時間がないような切り方を心がけている。別の言い方をすると、タスクに着手したら自分だけで完了状態に持っていけるようなタスクの切り方をしている。

他タスクが待ち状態になる時間を最小限にする

1つ前の工夫と逆で、自分が他のタスクを待ち状態にしすぎないようにタスクを分割すると良い。そうしておけばチーム開発の待ち時間を減らせる。たとえばロジックの本筋を実装する前にAPIからダミーデータを返す実装をしておけば、クライアントサイド側は先にビューを実装できる。

自分にとって難易度の高いものが1タスクの中で1つである

自分にとって難易度の高い部分が複数あると前段階の調査が長くなる傾向になり、結果的に実装に取り組むまでの時間が長くなる。複数の調査〜実装をすると自分に多くの認知負荷がかかり1つずつ行うより時間がかかることが多い。

そのため自分にとって難易度の高いものが1タスクの中で1つであるように心がけている。このようにすれば新しい部分の調査〜その部分の実装までのスパンを短くでき一歩ずつ前に進める。一歩ずつ進めるため自分の認知負荷を減らせ、結果として素早くタスクを終わらせられる。

また難易度の高い部分が複数あると工数見積もりも難しくなる。ある程度の精度の見積もりをできるためにも難易度の高い部分は分割しておくと良い。

「自分にとって」という部分も大切だ。たとえば入社したばかりでプロジェクトのコードに詳しくない場合、いつもだったら簡単に終わることでも時間がかかる。一般的に難しいところを分割するのは当然として、その時の自分の能力を勘案して知らない部分は難易度が高いとみなしておくと良い。

初めから完璧なタスク分割を目指さない

タスク分割の工夫ではないが、初めから完璧なタスク分割を目指さないことも大事だ。一番最初は自分の理解も浅いので良いタスク分割ができないことも多い。そのため最初に考えたタスク分割に拘らず、実装しながら良いタスク分割が思いつくたびに整理を繰り返すと良い。

工夫を考慮した分割例

上記の工夫を考慮してタスクの分割の例を説明する。

たとえば「自分がフォローしている人の投稿一覧をオススメ順で閲覧できる」というユーザーストーリーがあり、そのユーザーストーリーの中で自分はサーバーサイドを担当しているとする。この時、次のようなタスク分割が考えられるだろう。

  • (1) Proof of Conceptとして実装をし、実現可能であることを明確にする
    • 完了条件: Proof of Conceptの実装をPullRequest形式で作れている。基本方針が実現可能であることを説明するサマリー文書を作れている。実現可能か不明瞭かつ調査に時間がかかる箇所が新しく見つかれば、難しい部分を検証する追加タスクを作れている
  • (2) ユーザーストーリー全体の設計を確定する
  • (3) 暫定的にAPIからフォローしている人の投稿を新着順で返す(ページングなしで1ページ目のみ返す)
  • (4) フォローしている人の投稿をページングできるようにする
  • (5) 投稿一覧で運営から非表示にされた投稿は表示しない
  • (6) 投稿へのいいね数に応じて、オススメ順に投稿一覧を返す

工夫をどのように適用したかを説明する。

  • すべてのタスクで自分の力量を考慮して1~2週で終わる粒度となるように心がけた
  • (1)のように他の人から見ても完了判断がつきやすい完了条件を各タスクにつける
    • (2)~(6)については記事内の説明の簡潔さを優先して割愛する
  • (3)と(5)を分割したのは「開始から終了までに他タスクによる待ち時間がない」を意識した
    • この2つはそれぞれ難易度が高くはないので一覧表示と非表示フィルタリングを一気にやることも考えられる。しかし別の人が「運営が非表示設定をできる」というタスクに取り組んでいる場合、一覧表示実装と非表示設定された投稿のフィルタリングの合間に待ちが発生する
    • この2つを細かく分割することで、(3)は他の人の状況にかかわらず一気に終わらせられて、(5)は関係する他タスクが終わった後に取り組み始めれば一気に終わらせられる
  • オススメロジックを最後に回して(3)や(4)を先にやることで、他タスクが待ち状態になる時間を最小限にできる
    • オススメロジック実装は不確実性が高く、もしかしたら想定より時間がかかるかもしれない。そうなるとクライアントサイドの人が一覧ビューを作り始めるまで時間がかかってしまう
    • 先に簡単にでもダミーの一覧を返しページングする部分だけ作ってしまえば、クライアントサイドはロジックのことを気にせずに一覧取得部やビューの作成に取り組める
  • (2)と(3)の分割や(6)の分割は「自分にとって難易度の高いものが1タスクの中で1つである」を意識している
    • プロジェクトに入ったばかりだと「一覧を出す」「ページングを実装する」のどちらも自分にとっては難易度が高くなりうる。あえて(2)と(3)を分けることで一歩ずつ進めるようにする。もちろん慣れていて両方を一気にやっても問題ないなら(2)と(3)を分割する必要はない
    • (6)のオススメの実装はパフォーマンス面など一般的にも難しくなる可能性が高いので分けておく

そしてこのタスク分割は進行中にいつでも調整しても良いと意識しながら実装を進める。最初のタスク分割に拘りすぎないことで実装時に気づいたことを反映させやすくなる。

まとめ

今回は自分がエンジニアリングタスクを分割するときに工夫している点について書いてみた。工夫点は「少なくとも1スプリント以内で終わるタスクになっている」「完了条件が明確である」「開始から終了まで他タスクによる待ち時間がない」「他タスクが待ち状態になる時間を最小限にする」「自分にとって難易度の高いものが1タスクの中で1つである」「初めから完璧なタスク分割を目指さない」である。「自分がフォローしている人の投稿一覧をオススメ順で閲覧できる」というユーザーストーリーの分割例を通してこの工夫を具体的に説明した。

自分の工夫が参考になったら嬉しい。また他にも良い工夫があったら教えてほしい。