エクストリーム・プログラミング プラクティス
エクストリームプログラミング(XP)は、ソフトウェアプロジェクトの実施に用いられるアジャイルソフトウェア開発手法である。本稿では、この方法論で使用されるプラクティスについて詳しく説明する。
エクストリームプログラミングには、ソフトウェアエンジニアリングのベストプラクティスから派生した4つの領域にグループ化された12のプラクティスがある。
ペアプログラミングとは、すべてのコードが、2人の人間が1つのワークステーションで1つのタスクをプログラミングすることによって生成されることを意味する。一人のプログラマはワークステーションを操作し、主にコーディングの詳細を考えていく。もう一人のプログラマは全体像に集中し、最初のプログラマが作成しているコードを継続的にレビューしていく。1分から1時間の周期でプログラマーの役割を交代していく。
ペアは固定ではない: プログラマーは頻繁にパートナーを入れ替えることで、誰もが誰が何をしているのかを把握し、自分のスキルセット以外の部分であってもシステム全体に精通していく。
このように、ペアプログラミングはチーム全体のコミュニケーションを強化することができる(これは共有所有の概念とも密接に関係している)。
エクストリーム・プログラミングにおける主な計画プロセスは、計画ゲームと呼ばれている。
ゲームとは、通常は週に一度、イテレーションごとに開催される会議のことである。計画のプロセスは2つに分かれている。
リリース計画: これは、どのような要件がどの直近のリリースに含まれるか、いつ配信されるべきかを決定することに焦点を当てる。顧客と開発者の両方が参加する。リリース計画は3つのフェーズで構成される:
探索フェーズ: このフェーズでは、顧客はシステムの重要な要件の候補リストを提供する。これらは、ユーザーストーリーカードに書き留められる。
コミットメントフェーズ: コミットメントフェーズでは、ビジネス側と開発者は、次のリリースに含まれる機能と日付にコミットする。
ステアリングフェーズ: ステアリングフェーズでは、計画を調整したり、新しい要件を追加したり、既存の要件を変更・削除できる。
イテレーション計画: ここでは開発者のアクティビティとタスクを計画する。このプロセスでは、顧客は関与しない。イテレーション計画も3つのフェーズで構成される:
探索フェーズ: このフェーズでは、要件がさまざまなタスクに変換される。タスクはタスクカードに記録される。
コミットメントフェーズ: タスクはプログラマーに割り当てられ、完了するまでの時間が見積もられる。
ステアリングフェーズ: タスクが実行され、最終的な成果が元のユーザーストーリーと一致していく。
計画ゲームの目的は、製品を納品に導くことである。いつ成果物が必要とされ、完成するかという正確な日付を予測するのではなく(それは困難である)、直接的なアプローチで「プロジェクトを舵取り」して納品することを目指す 。
計画ゲームのアプローチは、ソフトウェア以外のプロジェクトやチームでも、ビジネスアジリティの文脈で採用されている。
これは、要件を収集し、それら各要件の作業影響を見積もるという反復的なプロセスである。
ストーリーを書く: ビジネスには問題が伴う; ミーティング中に、開発はこの問題を定義して要件を取得しようとする。ビジネス上の問題に基づいて、ストーリー(ユーザーストーリー)を書かなければならない。これはビジネス側で行われ、システムの各部に何をしてほしいのかを指摘していく。開発側がこのストーリーに影響を与えないことが重要である。ストーリーはユーザーストーリーカードに書き込まれる。
ストーリーの見積もり: 開発側は、ストーリーカードがほのめかす作業の実装にかかる時間を見積もる。開発側は、問題を分析したり解決するためのスパイクソリューションを作成することもできる。このソリューションは見積もりに使われ、全員が問題の明確な可視化を得た時点で破棄される。繰り返しになるが、ビジネス要件に影響を与えてはいけない。
ストーリーを分割する: すべての設計上の重要な複雑さは、イテレーション計画を開始する前に対処する必要がある。開発側でストーリーを見積もれない場合は、分割して再度書き直す必要がある。
ビジネス側がこれ以上の要件を思いつくことができない場合に、コミットメントフェーズに進む。
このフェーズでは、コスト、メリット、スケジュールへの影響を判断する。 4つのコンポーネントを有する:
価値でのソート: ビジネス側は、ユーザーストーリーをビジネス価値で並び替える。
リスクでのソート: 開発側は、リスクによってストーリーを並び替える。
速度の設定: 開発側は、プロジェクトを実行できる速度を決定する。
スコープの選択: 次のリリースで完了されうるユーザーストーリーを選択する。ユーザーストーリーに基づいてリリース日が決定される。
ビジネス側は、ユーザーストーリーをビジネス価値でソートする。それらは3つの山に整理される:
クリティカル: それがないとシステムが機能できない、または意味がないストーリー。
重要なビジネス価値: 高いビジネス価値を持つクリティカルでないユーザーストーリー。
あってよかった: 高いビジネス価値を持たないユーザーストーリー。
開発側は、ユーザーストーリーをリスク順にソートする。こちらも3つの山で分類する:低、中、高リスクのユーザーストーリー。以下は、このアプローチの一例:
リスク指標の決定: 各ユーザーストーリーに、次の各要素について0から2のインデックスを付ける:
完全性 (我々はストーリーの詳細をすべて知っているか?)
完全 (0)
不完全 (1)
不明 (2)
変動性(変化する可能性があるか?
低い (0)
中間 (1)
高い (2)
複雑さ(どのくらい作りにくいか?)
単純(0)
標準的 (1)
複雑 (2)
すべてのインデックスがユーザーストーリーに追加されたら、ユーザーストーリーに低(0–1)、中(2–4)、または高(5–6)のリスク指標が割り当てられる。
ステアリングフェーズの中で、プログラマーとビジネス側はプロセスの「舵取り」をすることができる。つまり、変更を加えることができる。個々のユーザーストーリーや、さまざまなユーザーストーリーの相対的な優先順位が変更される場合がある: 見積もりが間違っているかもしれない。これは、それに応じて計画を調整するチャンスである。
今までの計画を受けてチーム速度のストーリーポイントを検討する。イテレーション期間は1週間から3週間である。
イテレーション計画の探索フェーズでは、タスクを作成し、その実装時間を見積もる。
要件のタスクへの変換: タスクカードを配置する。
タスクの結合・分割: タスクが小さすぎたり大きすぎたりして見積もれない場合、プログラマーはタスクを結合や分割する必要がある。
タスクの見積もり: タスクの実装にかかる時間を見積もる。
イテレーション計画のコミットメントフェーズでは、プログラマーには、さまざまなユーザーストーリーを参照する作業が割り当てられる。
プログラマーがタスクを受け入れる: プログラマーは、各自が責任を負うタスクを選ぶ。
プログラマーはタスクを見積もる: プログラマーがタスクの責任を負うようになったため、プログラマーはタスクの最終的な見積もりを行う必要がある。
負荷率の設定: 負荷率は、1つのイテレーションでのプログラマー1人あたりの実際的な開発時間の理想的な量を表す。 たとえば、週に40時間で会議に5時間が費やされるのであれば、これは35時間以下になる。
バランスをとる: チーム内のすべてのプログラマーにタスクが割り当てられたら、タスクの推定時間と負荷率を比較される。その後、プログラマー間でタスクが調整される。あるプログラマーがオーバーコミットしている場合、他のプログラマーが彼のタスクの一部を引き継ぐ必要がある。その逆も同様である。
タスクの実装は、イテレーションのステアリングフェーズで行われる。
タスクカードを取る: プログラマーは、自分がコミットしたタスクのうちの1つのタスクカードを取る。
パートナーを探す: プログラマーは他のプログラマと一緒にタスクを実装する。これについてはペアプログラミングのプラクティスで詳しく説明する。
タスクの設計: 必要に応じて、プログラマーはタスクの機能を設計する。
テスト駆動開発(TDD)を用いてタスクを実装する(以下を参照)。
機能テストの実行: 機能テスト(関連するユーザーストーリーとタスクカードの要件に基づいた)が実行される。
ユニットテストは、コードの一部 (クラス、メソッドなど) の機能性をテストする自動テストである。
XPでは、ユニットテストは最終的なコードがコード化される前に書かれる。
このアプローチは、プログラマーが自分のコードが失敗する可能性のある条件について考えるように刺激することを意図している。
XPでは、プログラマーは、コードが失敗する可能性のある条件がこれ以上思いつかなくなったときに、コードが完成したと言う。
テスト駆動開発は、次のステップを素早く回しながら進む。各ステップは、長くても数分、望むらくははるかに少ない時間で完了する。
各ユーザーストーリーは、通常1日から2日の作業を必要とするので、ストーリーごとに非常に多くのサイクルが必要となる。
ユニットテストを書く: プログラマーは、本番のコードに機能が完全には実装されていないので、失敗するはずの最小限のテストを書く
新しいテストが失敗するのを見る: プログラマーは、テストが実際に失敗するのを確認する。時間の無駄に思えるかもしれないが、このステップは、本番コードの状態についてのあなたの信念が正しいことを確認するのに重要である。テストが失敗しなかった場合、プログラマーはテストコードにバグがあるか、本番コードが新しいテストで記述された機能をサポートしているかを判断する必要がある。
コードを書く: プログラマーは、新しいテストが合格するように、十分な量の本番コードを書く。
テストの実行: ユニットテストを実行して、新しい本番コードが新しいテストに合格しているかどうか、他のテストが失敗していないかどうかを確認する。
リファクタリング: 本番コードとテストコードの両方からコードの臭いを取り除く。
上記のプロセスのより強力なバージョンについては、Robert C. Martinの「TDD 三原則」を参照のこと。
XP内では、「顧客」は請求書を支払う人ではなく、システムを実際に使用する人である。
XPでは、顧客は常に手元にいて、質問に対応できるようにしておくべきだと述べている。例えば、財務管理システムを開発するチームには財務管理者が含まれるべきである。
開発チームは常に最新バージョンのソフトウェアで作業する必要がある。
さまざまな変更や改良を加えたバージョンをローカルに保存しているチームメンバーがいるかもしれないので、数時間ごと、または大きな休憩が発生した際は、現在のバージョンをコードリポジトリにアップロードさせる必要がある。
継続的インテグレーションを行うことで、統合の問題によって引き起こされる、プロジェクトサイクル後半での遅延を避けることができる。
XPの教義は、今日必要なものだけをプログラミングし、それをできるだけシンプルに実装することを推奨しているため、時には、これによってシステムが行き詰ることがある。
この症状の一つは、二重 (または複数の) メンテナンスの必要性である: 機能の変更は、同じ(または類似した)複数のコピーされたコードへの変更を要求し始める。
別の症状として、コードのある部分の変更が他の多くに影響を与えることである。
XPの教義によると、これが発症するのは、システムが、アーキテクチャを変更してコードをリファクタリングし、よりシンプルで汎用的にするように指示しているのだそうである。
ソフトウェアの配信は、具体的な価値を生み出す、生きた機能の頻繁なリリースを介して行われる。
小さなリリースは、顧客がプロジェクトの進捗状況に自信を持つのに役立てられる。
顧客は事実に基づいてプロジェクトに提案を行うことができるため、チーム全体のコンセプトの維持を助ける。
コーディング規約とは、開発チーム全体がプロジェクト全体で遵守することに合意した、合意された一連のルールである。
規約は、使用するプログラミング言語でのソースコードの一貫したスタイルと形式を規定するもので、欠陥が発生する可能性を減らすための避けるべき様々なプログラミング構造やパターンも含まれる。
コーディング規約は、言語供給者によって規定された標準規約(Sunが推奨するJavaプログラミング言語のコーディング規約など)や、開発チームが独自に定義したものである。
エクストリーム・プログラミングの支持者は、可能な限り自己文書化されたコードを推奨している。
これにより、コード自体と同期が取れなくなる可能性のあるコードコメントの必要性を減らすことができる。
ソースコードの共同所有(「チームコード所有」および「共有コード」とも呼ばれる)は、すべてのコードに対してすべての人が責任を負うことを意味する;
したがって、誰もがコードのどの部分を変更することもできる。
ソースコードの共同所有は、組織的なポリシーだけでなく、感覚的なものでもある。
「開発者は、システムのコンテキストを理解し、問題のコードに貢献し、コードの品質を高く評価し、製品がユーザーのニーズを満たし、チームの結束度が高いと信じるほど、チームコードの所有権を強く感じる。」
ペアプログラミング、特にオーバーラップペアローテーションは、このプラクティスに貢献する:
異なるペアで作業することで、プログラマはシステムコンテキストをより理解し、コードベースのより多くの領域に貢献することになる。
エラーを発見した開発者はすぐにそれを修正できるので、コードを共同所有することで開発は加速し、全体的なバグを減らすことができる。
ただし、プログラマがよく理解していないコードを変更すると、バグが発生する可能性もある。
十分に定義されたユニットテストは、この問題を軽減するはずである: 予期せぬ依存関係がエラーを発生させた場合、ユニットテストが実行された際にエラーがあらわになる。
ソースコードの共同所有は、メンバーへの支援が改善され、知識と学習の幅が広がり、コードの責任が共有され、コードの品質が向上し、やり直しが減る。
しかし、メンバー間の衝突の増加、バグの増加、開発者の集中力の乱れと思案の中断、開発時間の増加、またはコードの理解不足につながる可能性もある。
プログラマーは、ソフトウェア設計に「シンプル・イズ・ベスト」のアプローチを取るべきである。
新しいコードが書かれるときはいつでも、作者は「同じ機能を導入するためのより簡単な方法はないか」と自問自答する必要がある。答えが「イエス」であれば、シンプルな方を選択すべきである。
リファクタリングは、複雑なコードをよりシンプルにするのにも使われるべきです。
システムメタファーとは、顧客、プログラマー、マネージャーなど、誰もがシステムがどのように機能するかを語ることができるストーリーのことである。
これは、チームメンバーが特定のクラス/メソッドの機能をその名前だけから容易に推測できるようにするクラスとメソッドの命名についての概念である。
たとえば、図書館システムは、借り手(クラス)の貸出_記録(クラス)を作成し、項目が期限切れになった際に目録(クラス)に対して「延滞_発生」操作を実行する。
それぞれのクラスや操作の機能は、チーム全体から見ても明らかである。
プログラマーやソフトウェア開発者は週40時間を超えて働いてはならず、ある週に残業があったとしても、その次の週にはそれ以上の残業をしてはならないという考え方である。
開発サイクルが連続的インテグレーションの短いサイクルであり、完全な開発(リリース)サイクルがより頻繁に行われるため、XP のプロジェクトは、他のプロジェクトが必要とする(残業が必要となる)よくあるクランチタイム(訳注: 締め切り前の踏ん張りどころ)には従わない。
また、この概念には、人は十分な休息をとっていれば、最高のパフォーマンスを発揮し、最も創造的な活動を行うことができるということも含まれている。
持続可能なペースを達成するための重要な要因は、頻繁なコードマージと、常に実行可能でテストが網羅された高品質のコードである。
絶え間ないリファクタリングの作業方法は、チームメンバーに新鮮で注意深い心を強制する。
チーム内での激しい共同作業のやり方は、週末に充電する必要性を駆り立てることとなる。
十分にテストされ、継続的に統合され、頻繁にデプロイされるコードと環境は、予期せぬ本番の問題と停止の頻度、関連する時間外の夜間や週末の作業を最小限に抑える。