自己相似性に注意を払うべきだった。
『Kent Beck』(注1)
はじめに
本連載では「アジャイルに開発する人達(アジャイル開発者)が開発するからアジャイル開発である」と考え、アジャイル開発者になるために必要なスキルを磨くための習慣を紹介しています。
連載の前回は、ソフトウェア開発という活動は、「ソフトウェアという仕組み」(=開発対象のソフトウェアシステム)を開発すると同時に、「ソフトウェアという仕組みを開発する仕組み」(=開発プロセス)を開発するものだと説明し、こうした仕組みを育てるための習慣を紹介しました。
今回は、まずアジャイル開発者がこれらの仕組みをループ構造としてとらえていることを説明します。それから、アジャイル開発者の4つのスキル[2]がループ構造を支えていることと、このループ構造が複数レベルのスケールから構成されていることを説明します。そして、ループ構造の各スケール間に連続性を築き、維持するために、アジャイル開発者が身につけている習慣を紹介します。
プロジェクトを「回す」
ソフトウェア開発プロジェクトの運営を滞りなく進めることを「プロジェクトを『回す』」と表現することがよくあります。アジャイル開発者に限らず幅広く使われている言い回しです。
ここでの「プロジェクト」という言葉は、前回説明した2つの仕組み(開発対象のソフトウェアシステム・開発プロセス)と、それに関連するリソース(人・モノ・金・時間)をすべてひっくるめている、という程度にとらえてください。
この「プロジェクトを回す」という言い回しは「メタファ(比喩)」です。プロジェクトそのものが文字通りに回転するわけではないからです。仮にプロジェクトが回転していたとしても、その姿は目に見えません。
プロジェクトは概念である
確かに、プロジェクトに携わっている人々や、書いたドキュメント、成果物であるソフトウェアが動作しているハードウェアといった、プロジェクトに関連するモノは目に見えるかもしれません。それでもやはり、プロジェクトという存在そのものは直接目には見えません。プロジェクトは、人の生みだした「概念」だからです。
いわゆるプロジェクトの「見える化」の潮流は「見えないから問題がわかりづらい」ということにその端を発しているわけですが、今回お話したいのはそのことではありません。
概念を理解するためのメタファ
人は、目に見えない概念を理解するためにはメタファを使います[3]。ほかの経験で理解していることをメタファとしてその概念に適用することで理解するのです。具体的なメタファには、「恋愛は旅である」「理論は建築物である」といったものがあります。
「プロジェクトを回す」というメタファが広く流通しているということは、私たちはこのメタファを通じてプロジェクトという概念を理解しているといえます。「回すもの」といえば、皿や車輪、ボールといった円形や球体です。「回っている」といえば、球体の回転や、円を描くような運動のことです。
プロジェクトはループ構造
「プロジェクトの構造」を円形や球体として、「プロジェクトの運動」を回転や円を描くものとしてとらえると、アジャイル開発者のさまざまな振る舞いを理解しやすくなります。
プロジェクト全体のレベルから眺めたとき、この運動がループして「1周」するのは、ユーザの要求(=ストーリ)(注4)がソフトウェアとして実現され、ユーザからのフィードバックを得たときです。ユーザからのフィードバックと、新たな要求が次のループを推進します。プロジェクトのループを正しく「1周」させるための作戦が開発プロセスです。
このループは1日~数日程度の周期で繰り返されます(もちろん、プロジェクトによってはもっと短い場合もあれば、長い場合もあります)。
プロジェクトのループ構造の入れ子
ループ構造として構成されているのはプロジェクト全体レベルだけではありません。ユーザの要求をソフトウェアとして実現させる過程も、プロジェクト全体と同じループ構造で構成されています。ループ構造は入れ子になっています(図1)。
ストーリを実現させるために、ストーリを技術的なタスクに分割します。タスクにはテストを定義します。このテストに成功するようにプログラムを設計・実装します。無事テストに成功したら、そのフィードバックをもとにリファクタリングを行い、タスクの成果を開発対象システムに統合します。このループは数時間~数日程度の周期で繰り返されます。
プロジェクトの入れ子構造は、さらに小さなスケールにも、より大きなスケールにも見いだせます。タスクで定義したテストケースの一つ一つを実装する過程(数分~数時間のスケール)もそうですし、複数のストーリをまとめたリリースのレベル(数週間~数ヵ月のスケール)もそうです。このように、あるレベルの構造とより大きな(より小さな)レベルの構造が、同様の構造から構成されている性質を「自己相似性」と呼びます。
アジャイル開発者にとってのプロジェクトのイメージは、さまざまなスケールのループから構成される自己相似構造のメタファで理解できます。アジャイル開発者の仕事は、このループ構造を支え、推進することです。そのためにアジャイル開発者が心得ておくべきことは次の2つです。
- 4つのスキルがループ構造を支えている
- ループ構造の各スケール間に連続性を築く
以下で順番に説明していきます。2点目が今回紹介する習慣「スケール間に連続性を築く」です。
プロジェクトのループと4つのスキル
本連載で言及するアジャイル開発者の4つのスキルはプロジェクトのループを正しく「1周」させるためのスキルです。それぞれのスキルとループ構造との関わりを順番に説明します。ここで説明するのは、プロジェクト全体レベルでの適用についてです。
ストーリの作成
ストーリの作成は、プロジェクト全体レベルのループの出発点です。ソフトウェアへの要求を、ユーザ価値の視点から、ユーザの語彙を使って数行の文章で記述したものがストーリです。たとえば「閾値ベースの通知対象者選択機能を実装する」ではなく「設定された閾値を越えている対象者を一覧から選択して通知できる」といったようにです。
ストーリそのものに詳細を含める必要はありません。必要に応じて補足するドキュメントや仕様書を用意して対応します。
ストーリは受け入れテストと対をなします。ストーリは、受け入れテストを書くことができ、受け入れテストに成功すれば「正しく」ソフトウェアが作られていることを検証できるような記述を心がけます。アジャイル開発者の腕の見せどころです。
テスト駆動開発(TDD)
プロジェクト全体レベルでのTDDは、ストーリに対する受け入れテストの定義(と実行)です。受け入れテストには2つの役割があります。
テストを定義する際には、文字通り「そのテストが作業のゴールであり、そのゴールへ向かって開発が駆動されていくこと」を念頭に置いてください。
すでに述べたとおり、具体的な開発作業はストーリをタスクに分割して取り組みます。タスクの分割は「受け入れテストに成功するためには何をすればよいか?」という視点から行います。タスクを分割しきれたかどうかを判定する質問は、「分割したタスクをすべて完了させれば、受け入れテストに成功できるか?」です。
受け入れテストの自動化
受け入れテストの実行は、必ずしもすべてが自動化されている必要はありません。誤解されていることも多いのでここで補足しておきます。現場での受け入れテストは、自然言語で書かれた文書[5]であることも多いです。
TDDではテスティングフレームワークの利用を強調するので「テスト実行の自動化」が注目を集めがちです。しかし、開発対象のソフトウェアの特性や受け入れテストのケースによっては、実行を自動化するためのコストが非常に大きいものもあるからです。
実行の自動化は重要な要素ですし、取り組む価値のある課題ですが、TDDの本質ではありません。繰り返しますが、TDDの本質は「そのテストを書くことが開発を駆動するか?」を問い続けることです。
リファクタリング
プロジェクトは1回のループでストーリの実現に必要な作業を行うわけですが、その作業全体を通してリファクタリング――システムの振る舞いを変えずにソフトウェアの設計を洗練させる――を行います。
ユーザ価値とリファクタリング
リファクタリングは、プロジェクトのループを継続させていくうえで必要な作業です。しかし、リファクタリングはユーザ価値を提供し続けるために基盤としてこの上なく大事なものではありますが、ソフトウェアの振る舞いは何も変わらないので直接的にはユーザ価値を提供しません。
ですから、リファクタリングが直接ストーリとして表現されるのはよほど特殊な例外的状況にあることを心得てください。ユーザ価値を提供するストーリと関連させたタスクとして、日常的継続的に少しずつコツコツと進めていくのがリファクタリングです。
リファクタリングの手順を実践できることもアジャイル開発者として必要なスキルですが、どうやってプロジェクトの日常的な作業に組み入れていくかの作戦を考えられることは、さらに重要なスキルです。
計画づくり
計画づくりは、プロジェクトの各回のループがリズムを持って正しく回転するように定めるプロセスです。計画づくりでは、どのストーリをどういった順番で実現していくのかを、ストーリの見積りを踏まえたうえで、タイムボックスに収まるようにビジネス的な優先順位に従って決定します。
アジャイルな開発スタイルと従来型の開発スタイル(いわゆるウォーターフォール型)との比較に、「アジャイル VS. 計画駆動」という図式がよく用いられますが、アジャイル開発も計画を重視します。
後述しますが、アジャイル開発ではさまざまなレベルで計画づくりを行います。計画づくりを実施する頻度は、一般に計画駆動と呼ばれている開発プロセスよりも格段に多くなります。
計画に対する両者のアプローチの違いは、状況に応じた計画づくり(プランニング)を重視するか、立てた計画(プラン)を予言として絶対視するかです。「プランニング重視(アジャイル)VS. プラン重視(計画駆動)」と考えたほうが実態に即していると思います。
計画と見積り
計画づくりにあたっては、ストーリやタスクを見積る必要があります。アジャイル開発での見積りは作業量の相対サイズで行います。
見積りについて言及すると、この連載の枠の範囲を大きく逸脱してしまいます。ここでは見積りについてのヒントを一つだけ紹介します。あなたが「見積り」と「コミットメント」と「ターゲット」の違いについて説明できないようであれば、今すぐ『ソフトウェア見積り』(注6)を読んでください。
習慣 #2 スケール間に連続性を築く
プロジェクトを構成するさまざまなスケールのループ構造は、それぞれ独立したものではなく、互いに連続性を持っています。しかし、その連続性は自動的には成立しません。人が絶えず意識し、手を入れる必要があります。スケールとスケールの間をつなぐのがアジャイル開発者の仕事です。
ループ構造の各スケール間に連続性を築くために必要なマインドセット(心構え)とプラクティス(実践)を紹介します。
マインドセット「“いま・ここ”のスケールを意識する」
プロジェクトに従事するとさまざまな作業やイベントがあります。計画づくり、ストーリの定義、スタンドアップミーティング、設計の議論、タスクの分割、プログラミング、テスティング、ふりかえり……。それぞれの局面で“いま・ここ”のスケールがどのレベルにあるのかを意識しましょう。
ストーリを定義する際に、ビジネス価値ではなく実装の詳細を語っていませんか? テストケースを定義する際に、ソフトウェアとしてのそもそも論を語っていませんか?(これは詳細を検討できるだけの情報を得ていないことや、チーム内の認識に齟齬があることのサインです)
マインドセット「スケール間にはギャップがある」
ループ構造は複数スケールで構成されると説明しましたが、これはあくまで比喩です。実際には完全にそのとおりではありません。スケール間にはギャップがあります。
プログラミングレベルでユニットテストの実行を完全に自動化できるからといって、受け入れテストが完全に自動化できるわけではありません。受け入れテストの手動実行を正式なタスクとして計画に組み入れる必要があるかもしれません。
タスクレベルの見積りの合計が、ストーリレベルでの見積りと自動的に一致するわけではありません。見積りの数値的な整合性よりも、タスクの作業結果がストーリと結びついていて、ストーリをタイムボックス期限内に実現できることの論理的な整合性に注意を払います。見積りが妥当かどうかは、チームで考えて判断しなければなりません。
小さいスケールでうまくいっていることを、そのまま大きなスケールに適用するだけではうまくいきません(逆も同様です)。重要なことは、ループ構造が各レベルごとの抽象度でリズムを持って正しく回転していることを、動作するソフトウェアで示すことと、各レベルのループを回している理由を、より上位のループ構造から導きだせることです。ストーリはユーザ価値を表現していますか? タスクとストーリとの関連を明確に説明できますか? そのテストケースはタスクの完了のために必要ですか? 「このスケールでうまくやるには何をすべきか(そして何をすべきでないか)」を常に考える必要があります。
プラクティス「スケール単位での計画づくり」
計画づくりを重視するアジャイル開発では、スケール単位で計画を立てます。計画はさまざまなレベルから構成され、それぞれをタイムボックス化[7]します。タイムボックスにはレベルごとにループ構造が存在します(図2)。
たとえば、四半期単位では、実現する内容を漠然としたテーマのような形でリストにします。直近の四半期については、リリース単位でストーリを一覧にします。リリース対象のストーリを具体的にいつ実装するかはイテレーション単位で計画します。各イテレーションでは、ストーリをタスクに分割し、日々の作業ではタスクを実現するために必要なテスト項目をリストにします。
プロジェクトカレンダー
四半期、月、週、日といったスケールをチームで共有するためには、プロジェクトのカレンダーを用意するとよいでしょう。ホワイトボードマーカを使って予定やイベントを書き込めると、計画の変更に適応できて便利です。私の周囲では「ほぼ日ホワイトボードカレンダー」に定評があります。
チームの時間割
私の周囲ではよく作られているものにチームの時間割があります。これは、スケール単位での計画づくりを日次のレベルに適用したものです。
チームの時間割は、学校の時間割と同じです。
1日を複数のコマに分割し、チームの作業時間単位とします。1コマの長さは1.5時間~3時間程度です。
チームの時間割は、1日の作業にリズムとメリハリをもたらします。また、タスク見積りの共通のスケールとして活用したり(「このタスクは2コマ分ぐらいだね」)、チームメンバーの作業結果を同期化するトリガーになったりします[8]。
プラクティス「スケール単位でのバーンダウンチャート」
バーンダウンチャートは、プロジェクトの進行状況を把握するための2次元のチャートです。横軸に時間、縦軸に残作業量をプロットします(図3)。
バーンダウンチャートは「これまでにどれだけ作業をしたか」ではなく「タイムボックス満了までにあとどれだけ作業が残っているか」を把握することを徹底します。
バーンダウンチャートはスケールごとに作成します。今回はよく作成される例として、イテレーションバーンダウンチャートとデイリーバーンダウンチャートを紹介します。
イテレーションバーンダウンチャート
イテレーションバーンダウンチャートは、リリースのレベルで作成します。チャートの時間軸の単位はイテレーション、残作業量の単位にはストーリポイントや、受け入れテストの残りケース数を使います。
チャートはイテレーションの完了のタイミングで更新します。チャートの更新はイテレーションのふりかえりの前に済ませておきます。
イテレーションバーンダウンチャートは、マネージャや顧客側の取締役などの利害関係者に、プロジェクトの進行状況の概要を示すのにも使えます。
デイリーバーンダウンチャート
デイリーバーンダウンチャートは、イテレーションのレベルで作成します。時間軸の単位はイテレーションの稼動日、残作業量の単位はタスクポイントです。更新頻度は1日1回で、1日の作業終了時(たとえば前回の連載で紹介した夕会)に更新します。
今回のまとめ
今回の内容を、前回までのまとめを拡張して図4にまとめました。
アジャイル開発では、ほかにも複数スケールの自己相似構造を見いだせます。今回は紹介できませんでしたが、テストコードを構造化する技法や、連載の第1回で紹介した「まずは自分、それからチーム」といった考え方にも自己相似性を見いだせます。アジャイル開発者として振る舞えばさまざまな自己相似構造を発見できるはずです。
それでは、また次回お目にかかりましょう。acts_as_agile!