📅

開発手法?タスク管理に振る舞い駆動 なにをもって完了とするか

2024/12/10に公開

はじめに

Webアプリケーション開発のなかで、プロジェクトの進行フェーズやチームの成熟度によって、最適なタスク管理方法が変わることがあります。
初めてマイクロサービスアーキテクチャでの開発を進めた際、初期からリリース後までに渡り3段階のタスク管理アプローチの変化を経験しました。
本記事では、その変遷とプロジェクトを通して感じたそれぞれの手法のメリット・デメリットについて書き残します。

プロジェクト概要

  • 技術スタック:
    • フロントエンド: React, Next.js
    • BFF: NestJS, GraphQL
    • バックエンド: NestJS, gRPC, Prisma
  • 進行形態: アジャイル
    • 毎週のスプリントでゴールを設定し、実装すべき機能(ユーザーストーリー)を明確にする
  • メンバー構成
    • PM(1人)
    • デザイナー(1人)
    • エンジニア(2~3人+インターン生数名)

プロジェクト初期はメンバーそれぞれの技術キャッチアップが必要であったことや、システムの全体像が見えていなかったため、フロント、BFF、バックエンドといったレイヤーごとにタスクを分けて、それぞれのチケットの消化をスプリントのゴールとして管理していました。
しかし、プロジェクトが進むにつれ、開発者が各レイヤーを横断的に扱えるようになっていきました。またプロジェクトを進めていくうえでいくらかの課題もでてきました。振る舞い(ユーザーストーリー)単位でタスク分担・管理し、スプリントゴール設定を行う手法に移行しました。

以下では、その2つのフェーズにおける進め方と得られた知見を整理します。

フェーズ1: レイヤーごとのタスクをスプリントゴールとしている管理方法

進め方と背景

プロジェクト初期は、新しい技術スタックへのキャッチアップ期間でもありました。React/Next.jsによるフロントエンド開発・GraphQLの扱い方、BFFの役割やNestJS + gRPC + Prismaからなるバックエンド開発、ドメイン駆動設計・イベントソーシング・CQRSなど自分含めそれぞれ身に着けるべき技術や設計方針が複数ある状態でした。
それぞれが優先してキャッチアップすべきテーマを絞るため、まずは各レイヤー単位で担当を振り分けました。
具体的には、

  • フロントエンドチーム:画面表示やフロントロジック部分
  • BFF・バックエンドチーム:API実装、DBスキーマ設計やgRPCサービス実装

といった形でレイヤーを明確に分け、レイヤー別にタスク消化をスプリントゴールを設定していました。

メリット

  • 担当領域が明確
    • 各メンバーは自分が熟知したい技術領域で作業に集中できます。技術的キャッチアップをしやすく、学習コストを分散できました。
  • プロジェクト基盤の安定化
    • UI実装、API設計、DBスキーマ定義、フロント・BFF・バックエンドの構成などレイヤー単位での整備に集中できるため、基盤を固めるには有利でした。
  • 達成感を得やすい
    • プロジェクト初期はそれぞれがレイヤーごとに独立して進められるタスクも多く、スプリントゴールをレイヤーごとのタスク消化で設定する方法はスプリントでの達成感を得やすい方法でした。

デメリット

  • 統合時の実装漏れ発生
    • フロント側、BFF側、バックエンド側それぞれのタスクが「完了」となっても、いざエンドツーエンドで機能を繋いで動かすと、想定していなかったデータ欠落やインターフェースの不一致が発覚しました。結果として、完了したはずのタスクに追加作業が発生してしまいます。
  • ユーザー価値の把握が困難
    • この段階では、まだユーザーストーリー単位での「機能完成」をしっかりスプリント内で実証することが難しく、「ユーザーが何をできるようになったか」が不明瞭でした。

フェーズ2: レイヤーごとにタスク分担するが、スプリントゴールは振る舞い駆動で管理

進め方と背景

ファーストリリース前後の段階になると、ある程度各レイヤーでの開発フローが見えてきました。しかし、まだメンバー全員がフロントからバックエンドまで横断的に扱えるほどではなかったため、レイヤーごとの担当は継続しつつも、スプリントゴールを「ユーザーストーリー(振る舞い)」単位で定義し始めました。

つまり、開発者の実務はフロント・BFF・バックエンドといったレイヤーごとに分担して進めつつも、スプリントで目指すべき最終形は「この機能(振る舞い)がユーザー視点で成立しているか」という基準で評価します。

振る舞い駆動(BDD)とは

振る舞い駆動(Behavior-Driven Development: BDD)は、ユーザー視点の振る舞い(機能的な要求)を明確にし、それを起点にテストや開発を行う手法です。
例えば「ユーザーがプロフィールを更新できる」という振る舞いを定義し、その振る舞いが実現しているかを基準に受け入れテストを行うことで、ユーザー価値に直結した開発を進めやすくなります。

メリット

  • ユーザー価値の明確化
    • スプリントレビュー時には、「ユーザーがログインできる」「プロフィール更新が可能」といった具体的な振る舞いをデモでき、ステークホルダーへのアピールが容易に。
  • 追加作業の減少(一部)
    • 前フェーズほどではないにせよ、振る舞い全体を意識することで、後から気づく統合不整合の頻度が若干減少しました。

デメリット

  • 技術的慣れ不足による遅れ
    • フロント〜バックエンドの全体像を誰もがカバーできるわけではないので、依存関係が生じ、スプリント中に互いの合流を待つことが増えました。

フェーズ3: ストーリーごとに分担し、振る舞い駆動でゴール設定

進め方と背景

ファーストリリースを経て、メンバー全員が各レイヤーの技術習熟度を高めると、1人または少人数でフロントからBFF、バックエンドまで一貫して開発が可能になりました。この段階では、タスク分担を完全に振る舞い(ストーリー)単位へ移行します。
具体的には、「Aさんはユーザーがプロフィールを更新できるストーリーを担当」といった形で、一つのストーリーの実現に必要なフロント改修・BFF調整・バックエンド修正を一手に引き受けます。

メリット

  • ユーザー価値の明確化
    • こちらはフェーズ2と同様
  • 追加作業のほとんどを排除
    • 1人またはチームがエンドツーエンドで責任を持つため、レイヤー横断での不整合が出にくくなり、実装漏れや追加タスク発生が大幅に減りました。
  • 価値の明確化・納品物の可視化:
    • スプリントの終わりには、ユーザーストーリーとして定義された機能が実際に動いていることを示せます。デモ時にはユーザー目線で成果を説明でき、ステークホルダーの理解も得やすくなります。
  • 追加作業の減少:
    • レイヤーごとでのタスク管理時には、後から統合して問題が出るケースがありましたが、振る舞い単位だと受け入れ条件を満たすまで「完了」にならないので、開発者が最初からエンドツーエンドで責任を持つため、スプリントゴール達成後の実装漏れや追加タスクの発生が大幅に減少しました。「タスクは終わったと思ったが実は未完了」というスケジュール管理のうえで実際の進捗とチケットの進捗が一致しないケースがなくなりました。??????

デメリット

  • 初期導入ハードルの高さ
    • フロントからバックエンドまで網羅的なスキルが必要で、技術未習熟のメンバーにはハードルが高くなります。
  • 細かな受け入れ条件の明確化のための時間が必要
    • 業務やシステム理解が浅い人などメンバー間でストーリーに対する解像度が異なります。受け入れ条件をはじめに明確化する時間を取れないまま走り出すと、パターンの考慮漏れなど発生してしまうため、ストーリー着手前の準備時間が大切になってきます。
  • 適切な粒度でストーリーを切る

成功要因

このようにレイヤー内におさまっていた作業範囲を広げてうまくいった背景も簡単にですが残しておきます。

  • BFF/バックエンド担当のフロント参画、またその逆をするタイミングがあること
    • 不具合対応や要望での機能変更など簡単なタスクから別レイヤー担当も実装できるようになっていった。
  • レイヤー内の構成が固まっていたこと
    • プロジェクトが進むにつれ「どこでなにする」「どう書く」といった実装例・規約を固められたこと。そのうえで別レイヤー作業に入っていけた。
  • 相互レビュー、開発振り返り、勉強会での知見の共有

まとめ

本プロジェクトでは、

  • レイヤーごとのタスクをスプリントゴールとしている管理方法(初期)
  • レイヤーごとにタスク分担するが、スプリントゴールは振る舞い駆動で管理(中期)
  • ストーリーごとに分担、振る舞い駆動でのゴール設定(成熟期)

という3段階でタスク管理手法を変遷させました。

  • 初期はレイヤーに集中することで学習負荷を軽減しつつ基盤を作れましたが、統合時の手戻りが発生しやすい欠点がありました。
  • 中期はスプリントゴールを振る舞いで管理することでユーザー価値を意識しやすくなりましたが、まだ担当分野が分かれているため不整合の発生を完全には防げませんでした。
  • 成熟期にはストーリーごとのエンドツーエンドな担当が可能となり、追加タスクをほとんど抑えつつユーザー価値を明確に示せるようになりました。

結局、どの手法が最適かはプロジェクトのフェーズやチームのスキル成熟度、システムや実現したいストーリーの規模等に依存します。もし今あなたのチームが初期段階であれば、まずはレイヤー別に取り組み、徐々に振る舞い駆動にシフトする段階的アプローチが有効かもしれません。
これからもユーザー価値を最大限に引き出し、効率的な開発サイクルを築くため、状況に合わせていろいろなタスク管理手法に挑戦していきたいです。

Discussion