リーン開発_第8章_品質
フィードバック
古い習慣では生き残れない窮地になってはじめて、より優れた新製品開発手法が必然的に生まれてきた。 そのような、堅牢な開発プロセスにはかならず2つの共通点がある。
1.秀逸ですばやいフィードバック
2.優れた詳しい規律
リリース計画
計画は、市場ニーズ(あるいはビジネスニーズ)、製品コンセプト、目標コスト、
稼働タイミングを見極めるところからはじまる。
- 1.初期投資期間中には、詳細な長期計画を作らず、短期間でインクリメンタルなリリース計画を作成する。
- 2.直近の開発についての計画を立て、最も重要な機能を見つけ出し、その土台となるアーキテクチャを確立させる。
- 3.収益獲得(や投資の回収)のために、最小限の有用な機能セットをもって早期稼働を計画する。
- 4.定期的に機能を拡充するため、後続のリリースを計画する。
- 5.初回のリリース目標は、実現可能性を確認し、暫定的なアーキテクチャーを確立する機能セットを開発することである。
- 6.リリースは、アプリケーションのすべての階層を縦に貫き、全体がどのように組み合わさるのかを示していなくてはならない。
その機能セットは次の点を考慮して選ばなくてはなたない。
- 1.価値が低い機能よりも、高い機能を先に
- 2.リスクが低い機能よりも、リスクが高く価値の高い機能を先に
- 3.すでによく知られている知識よりも、新しい知識を生み出す機能を先に
- 4.開発やサポートに高いコストがかかる機能よりも、低いコストで済む機能を先に
リリース計画によって、詳細な計画に多大な資金を投入する前に、技術や市場に対する仮設を検証できるようになる。
実装に着手し、進捗をトラッキングすることで、計画の実現可能性を早い時点で見通すことが出来るのである。
リリース計画を実行に移してみて、最初のリリースでスケジュールから遅れたとしたら、その計画は強引すぎるということだ。
この時点では、ビジネスプロセスや開発中の製品を単純化したり、その機能を実装する技術的手法を単純化したり、その機能をそっくり削除してしまうのがいい。
一般的にイテレーションやリリースの決められた「時間枠(タイムボックス)」を守り、その時間枠内で実装を完了できる機能に制限するのが最善の取り組み方。
アーキテクチャー
- 開発中の機能セットでの必要に応じて開発してくべきである、と主張している。
成功した寿命の長い商品では、新しい適用領域が発見され、当初のアーキテクチャーではまっく思い描いてなかった機能が必要になったら、3年に1回ぐらいは大幅なアーキテクチャー改善があるかもしれない。 もう、「アーキテクチャーは、あらゆる開発に着手する以前に、完全でなくてはならない」という神話は捨てなくてはならない。
イテレーション
- 反復開発は、一定のリズムで、徐々に技術的進歩を同期させていく開発スタイル。
まず、バックログ(求められている機能の優先順のリストに簡単な説明をつけたもの)がある。 機能を実装する少し前に、顧客のドメインや技術を理解しているチームメンバーが機能を分析、ストーリーに分割する。
ストーリーとは
- 2〜3日程度で確実に完成できると考えられる開発単位のこと。
計画ミーティングでは、チームが次のイテレーションでいくつかのストーリーが実現できるのかを、それまでの記録(速度)を基にして見極め、そのストーリーの完成を約束する。
イテレーションの間は、チーム全体が毎日短時間ずつ顔を合わせて、イテレーション計画の進みがどうなっているのかを話し合ったり、実装するという約どくを果たすための軌道確認をしたりして、お互いに助け合う。
イテレーションの最後のは、ストーリーが完成していなくてはならない。
結合し、テストし、ドキュメントを作成して、使用できる状態にする。
レビューミーティングでは、進捗の成果をデモし、フィードバックを得るために行う。
フィードバックは、ストーリーやバックログへの変更としてまとめる。
何度かイテレーションを繰り返せば、有用な機能セットは完成し、導入可能となっている。
準備
- バックログ項目は、最初は大まかな内容の箇条書きである。大まかには理由がある。
リーン手法とは
詳細な分析を、対応に間に合う最後の瞬間まで遅らせる手法なので、項目は、優先順位の上位にいけばいくほど、より小さい、より管理しやすい断片へと分割していかなくてはならない。
バックログ項目は
- その設計が1つ以上のストーリーとしてまとめられるまで、開発できる状態ではない。
- 各ストーリーを実装する人たちは、ストーリーをはっきり理解し、その実装作業を確実に見積もることが出来なくてはならない。
- 確実に提供するには、確実な見積もりが必要、各ストーリーは、ビジネスの視点から、なんらかの明確な価値を備えていなくてはならない。
- ストーリーの規模を決める基準は、それにかかる実装作業量
- 通常は、1.5〜4日分の作業のストーリーにする。
- 製品を設計する人たちは、ストーリーの価値がその実装コストに見合うものかを見極めなくてはならない。
- 通常、ビジネス目標に関連した用語で表現
- ハイレベルな目標は、ストーリーというより、叙事詩(じょじし)のようになる。
- 項目が優先順位の上のほうに来ると、顧客の仕事をよく理解しているチームメンバー(プロダクトオーナー、アナリストなど)が、叙事詩からストーリーへの分割作業を統率する。
- 本質的なユースケースと懸念ドメインモデルの組み合わせや、ビジネスルールやポリシー、ユーザインターフェース(UI)プロトタイプ文書のような、標準的な分析テクニックは、製品設計のこの分割作業を考える上で効果的。
- ユースケースが複雑で、関連するインターフェースやルール、永続化などを含めた場合には、1つのユースケースが数個のストーリーとなり、一度のイテレーションではそのユースケースの主要なシナリオを実現できない場合もある。
イテレーション準備の目的は
- 次に開発されるはずの製品「全体」の一部を設計すること。
- ビジネスルールやポリシー、ワークフロー、機能性、インターフェース設計について決定しなくてはならない。
- この設計活動によって「ちょうど十分」で、注意深く考えられたストーリーを次のイテレーションに「ジャストインタイム」で作り出す。
- 優れたストーリーは、きちんと定義された実装作業の単位になり、確実な見積もりを出したり、次のイテレーション内で完成させたり出来る程度に小さいもの。
- 目的は、製品全体について、広範にわたる分析ドキュメントを作ることではなく、実装を行う人たちにビジネス上の意図を明確に伝えるために、サンプルとなるテストを十分に提供すること。
計画
- イテレーションのはじめに計画ミーティングを開く
- チャンピオンやプロダクトオーナーと協力し、チーム全体で、最優先のストーリーを開発、テスト、文書化、導入(あるいは導入準備)に必要な時間を見積もる
- チームメンバーは最初のストーリーを選んで、その完成を約束
- 2番目のストーリーを選んで、こちらも提供を約束できるのかどうか、判断する。
- このプロセスは、チームメンバー次のストーリーを提供できるかどうか、確信を持てなくなるまで行う。
- チームメンバーは、イテレーションの間位に実装すると合意した機能セットのテーマを表すイテレーション目標を約束
- どの程度の作業が必要になるのかは、別段教わらなくても、2〜3回イテレーションを回せば、各チームが速度(ベロシティ)を確立するので、この値を見れば、チームが一度のイテレーションでどの程度の作業を済ませられるのか、全員が検討をつけられるようになる。
- チームメンバーはその約束を、目標達成のために1つのチームとして協力し合うという成約であるとみなす。
- ときには、チームが多くを約束することもあるし、技術的な問題が持ち上がるかもしれない。そのような場合、チームは適切に状況に対応し、多くの約束しすぎた根本原因を見つけて、再発防止のための対策を取らなくてはならない。
実装
- イテレーションの間、チーム全体がイテレーション目標を達成するために協力し合う。
- 全員が毎日、10〜15分のミーティングに参加し、一人ひとりのメンバーが前回のミーティングで以降に何をし終えたのか、次のミーティングまでに何をする予定なのか、どのような問題を抱えているのか、どの部分で手助けを必要としているのかを話し合う
- このミーティングでチームが対話することによって、個々のメンバーは、チームの目標を達成するために次に何をしないといけないのかが、教えられなくてもわかるようになる。
お勧めの手法:ストーリーテスト駆動型開発
(受け入れテスト駆動型開発とも呼ぶ)
- 一度に1つのストーリーに取り組むのだが、チームメンバーは機能的な詳細やワークフロー、ユーザーインターフェースの設計に重点的に取り組み、開発者と協力して、その製品に必要な振る舞い(ビヘイビア)を、テストケースの形式で的確に表現
- このような議論により、関係のある変数や、適用できる方針、そのドメインのビジネスルールが確定していく。
- この共通の言語を使って、入力や手順ときたいされる結果の形で振る舞いを定義する。
- 何人かのチームメンバーが十分な件数のテストケースを出していく間、開発者はテストケースからアプリケーションへのインタフェースを作り、そのテストケースが通るコードを書く。
- 開発者が、不明点を確認し詳細情報を知る必要が出てくれば、顧客ニーズを理解するチームメンバーがそれについて議論し、そこで合意した内容を記録するためのテストケースを定義する手助けをする。
- テストケースをすべて集めれば、事実上、非常に詳細で、自己検証的な製品設計仕様書になる。
- ストーリーテストによって仕様が示された振る舞いを実装するために、開発者は単体テスト駆動型開発を利用
- コードを見て、ストーリーテストの目的に貢献するシンプルな振る舞いを選ぶ
- その振る舞いを実装するため、開発者は適切な名前をつけたオブジェクトやメソッド、メソッドの引数を決める。ストーリーテストで使われている名前と一致する名前を選ぶようにする。
- 開発者は単体テストを書くことによって、設計上の決定を文書化しておく
- 単体テストは、新しいコードが意図されたとおりの振る舞いをするようになるまでは失敗する。
- それ以前のテストを失敗させることなくこのテストが通りように、簡単なコードを書く
- 最後に、新しいコードを加えたコードベースをチェックし、リファクタリングによってコードの重複を取り除いたり、理解しやすいように単純化したり、コードの意図を明確にしたりして、コードベースの設計を改善。開発者はこのサイクルを繰り返し、ストーリーテストを通るまで、振る舞いを追加していく。ストーリーテストが通ると、次のストーリーに取り掛かる。
毎回のイテレーションの終わりに、完全で「リリースできる」機能が出来ているのが目標
評価
- イテレーションの終わりにレビューを開く
- レビューによって、何かを変更しなくてはならないことになった場合、小さな問題であれば、新たなストーリーにし、大きな問題であれば、バックログに入れて、他の項目に照らして優先順位をつける。
- それ以上は手間を掛けずに、次のイテレーションの計画ミーティングへ移る。
- チームが学習していくのにあわせて、テスト一式も新たに生み出された知識を表現すように、適応していかなくてはならない。
- 目を見張るべき点として、テストによって変更のコストが非常に低くなること
- 誰かが以前の設計上の決定にうっかり反してしまったら、すぐにテストが失敗する。
- それによって、チームがそのコードを直すのか、あるいはその設計を表現しているテストを更新するまで、ラインストップをするように警告を発する。
応用:ユーザインターフェース
- ほとんどの組織では、実用に際して、自分たちの状況にあうように反復型プロセスを修正している
- 修正が必要となる可能性の高い、特別な状況のひとつが、ユーザインターフェイス(UI)開発
イテレーション中、UI設計者にはいくつかの仕事がある。
1.今後のイテレーションのための顧客データ収集
- 2.前回のイテレーションで開発されたUIのテスト
- 3.現在のイテレーションで、コーディング中に出来た質問への回答
- 4.次回のイテレーションで実装されることになっているUIの詳細設計
UI設計を実装する前に、顧客データを収集し、プロトタイプでさまざまな選択肢をテストし、実装準備が整った詳細設計を確定する。
商用コードのユーザービリティテストは、実装よりも1つ後のイテレーションで行われる。
5S(ごえす)
- 5Sは、必要になったときにあらゆるものがすぐに使える、余計な混乱のない職場を編成するための、古典的なリーンツールである。
「S」は日本語でSから始まる5つの言葉を指す。
- 整理(Sort)
- 整頓(Systematize)
- 清掃(Shine)
- 清潔(Standardize)
- 躾(Sustain)
ソフトウェア開発の職場の5S
整理
- チームのワークステーションやサーバにあるものを整理し、もう使われることのない古いソフトウェアバージョンやファイル、レポートを見つけ出す。
- 必要ならバックアップをとってから、消す。
整頓
- デスクトップのレイアウトやファイル構造は必要である。
- 論理的な編成で、見つけやすいように作られていなくてはならない。
- 2人以上で共有して使っている作業スペースは、チームで決めた共通のレイアウトに沿うようにし、どこにログインしても必要なものが見つけられるようにしておかなくてならない。
清掃
- 空き缶やコーヒーカップを捨て、モニターの指紋を拭き取り、書類を片付けよう。
- ホワイトボードは、重要な設計が描かれていたら写真に収めてから、キレイに消す。
清潔
- 自動化や標準化を実施して、すべてのワークステーションに常にツールの最新バージョンがあるようにし、定期的にバックアップを行って、いろいろなゴミが溜まらないようにする。
躾
- これであとは、その規律を守り続けるだけ。
Javaの5S
整理
- コードベースのサイズを小さくする。
- 不要なものは捨てる。
- 使われていないコードを除去する。
- 使われていないimport文を除去する
- 使われていない変数を除去する
- 使われていないメソッドを除去する
- 使われていないクラスを除去する
- 冗長なコードをリファクタリングする
整頓
- プロジェクトやパッケージを整頓する。
- すべてのものの置き場所を決めて、そこにそれぞれきちんと置いておく。
- パッケージ間の依存関係の解決
- 依存関係の最小化
清掃
- きれいにしよう。
- 全てがきちんと、キレイになっていれば問題はもっと見つけやすくなる。
- 単体テストの失敗やエラーを解消する(成功=100パーセント)
- 単体テストのカバレッジを向上させる(80パーセント以上)
- 単体テストの効率を向上させる
- 全テスト実施時の効率をチェック
- Checkstyleの警告を解消する
- PMDの警告を解消する
- Javadocの警告を解消する。
- TODO(やるべきこと)を解消する
清潔
- 一度キレイにしたら、綺麗なまま保とう
- 保守を楽にするために、時間の経過とともに増していく複雑さを減らそう。
躾
- 標準的な手順を用いて、それに従う。
標準
標準があれば、反射的に対応できるようになり、変換というムダなしに情報を移動させられるようになる。
共通のアーキテクチャーを持つ標準化されたインフラストラクチャによって、複雑さが減り、その結コストも低く抑えられる。
早く進みたい組織には、かならず有効な標準がある、ソフトウェア開発組織が考慮すべき標準を紹介
もちろん、標準は決めるだけで役に立たない。
一貫して適用されなければ、標準には価値がない。
リーンな環境では、標準はある仕事をするための、現在の最善方法として捉えている。
どんな場合でも、よりよい方法があるという前提なので
どんな標準にも、誰でも積極的に異議を唱えていい。
よりよい方法が見つかって、そちらの方法のほうが効率的だとわかったら、それが新たな標準になる。
標準に従い、標準を絶えず変えていくという規律は、組織の骨格の一部である。
コードレビュー
コードレビューでは、別の問題に着目しなければなたない。
例えば
経験の浅い開発者のコードをレビュー
- シンプルになっているのかどうか
- 変更を受け入れやすいか
- 重複がないか
- その他の優れたオブジェクト指向の設計原則に従っている
などの点をチェックを行う。
コードレビューは。複雑さなどの問題意識を高めるためにも適切なツールになる。
ペアリング(ペアプログラミング)
コードをチェックインする前に、レビューを行わなくてはならないという
決まりにすると、レビュー待ちの未完成の作業が累積してしまう場合もある。
リーンな環境では、そのような事態はなんとしても避けなくてはならない。
遅れをだすとこなく、コードレビューを行うひとつの方法として、ペアでコーディングを行う。
ペアプログラミングを行うことで
- 一度にまとめて、コードレビューをするのではなく、流れの中で継続的にコードレビューを行っていく。
- ペアリングは、上手に使うと非常に有益なものになる。
- ペアになって開発を進めれば、学習効果やチームワークを、問題解決能力が高まる。
- ペアになって2組の目で見ることによって、コードの品質と堅牢性が改善され、生産性が上がることが多い。
- ペアになっていると、中断をうまくかわし、お互いをタスクに集中させておける。
- ペアリングによって相乗効果が生まれる場合が多い、2人が協力し合えば、それぞれが別々に作業を進めた場合に比べ、より統合され、よりテストされ、より欠陥の無いコードが作り出せる。
- ペアリングは、未完成の作業という在庫を積み上げることなく、レビューの効果が得られる最高の方法のひとつ
ポカヨケ
間違った人が悪いのではない、間違いが起こりそうな部分にポカヨケを施さなかったシステムが悪い。
ソフトウェアでは、失敗する可能性のあることは、実際に失敗する
個人の「責任」で起きた欠陥を数えていって、もっと注意深くなるようにプレッシャーをかけても、時間のムダ。
欠陥が見つかったら、その度にラインストップし、根本原因を見つけ出し、今後、同様の欠陥が防げる方法を考え出そう。
開発チームは、コードにポカヨケを施す効率的な方法について、広い視野で考えるべき。
テストや運用の担当者たちも参加させて、潜在的な障害発生地点を見極め、欠陥が起きる前にポカヨケを入れるようにする。
自動化
自動化をすることで、人為的なミスを防ぐだけではなく、人の知能に対する敬意を示すことにもなる。 繰り返しのタスクは、間違いのもとになるだけではなく、人をロボットのように扱ってもよい、という考えの現れ。 人であれば、よりよい仕事の進め方や問題の解決方法について、考えをめぐらせるべきである。
自動化の例
1.ワンクリックビルド ビルドの自動化が第一歩である。 ビルドの後には、何かが壊れていないのかを確かめるために、自動テスト一式をキックする。 多くのチームでは、Antを使っている。
2.定期ビルド ビルドがクリックひとつできるようになったら、簡単にスケジューリングできる。 時刻やコードのチェックインをトリガーとして、ビルドを実施 CruiseControlがよく使われる。
3.ビルド結果の通知 誰にでも結果が知らされてないのであれば、ビルドをしても意味がない。 ビルドが失敗したら、メールで通知するようにするのが簡単でよい。 赤札をあげたり、赤いラバランプを点灯させたりして、全員にビルドの失敗の警告を出すのが良い。
4.ワンステップリリース リリースには、リリースブランチを作成し、コードをダウンロードしたり、CDに焼いて配布できる形式の、ファイルやファイル一式にパッケージングするという作業が含まれる。 上記は、絶対に自動化すべきプロセスであり、そうすればエラーなど起こるはずがない。
5.確実なインストール 配布ファイルが顧客の手元に届いたら その後のインストールプロセスは、手助けのために誰かを現場に出向かせるとしても、自動化されているべきである。 配布メディアには、インストールが失敗したとき(もし失敗したら、ということではない)に役立つ、簡単な診断ツールを含めておくことも出来る。
テスト駆動型開発
テストには2種類存在する。
- 1.欠陥の発生後にそれを発見するテスト
- 2.欠陥を予防するためのテスト
テストに求められているのが、欠陥の発見ではなく予防なのであれば、通常私たちが行っている様々な種類のテストにおいて、それがどういう意味になるのかを考える必要がある。
ブライアンマーリックは、テストを4つの視点から見るように提案
テストに2つの目的がある。
- 1.プログラマの仕事を支援
- 2.同時にそのソフトウェアが組み込まれる製品全体を評価
技術的な観点からと、ビジネス的な視点の2つの視点で行われる。 これで4つの一般的なテストカテゴリーが出来る。
それぞれのカテゴリーは以下の通り
単体テスト(プログラマテスト)
- 単体テストは、開発者が自らの設計の意図をコードが実現している事をテストするために書く。
- 開発者が単体テストを最初に書くと、テストからコードの設計が発展していくこと、そして、単体テスト一式が事実上のソフトウェア設計仕様になることに気づく。
- 最初にテストを書くと、通常は設計がシンプルになる。
- テスト可能なコードを書いていると、コードの結合度が弱くなるからこの好循環のおかげで、開発者がテストファースト開発をはじめると、それ以外の方法でソフトウェア開発したがらなくなる。
- 単体テストを選び出して、ビルド時に走らせるテスト装置(testharness)にする。
- ビルド時にのテスト一式はすばやく動かなくてはならない。
- ビルドとテストは10分以内で完了すべき、これ以上長くなると開発者たちは使わなくなる。
- ビルド時のテスト一式でテストするコードは、実行スピードを上げるために、モックオブジェクトを使って、データベースと切り離されることが多い。
- 単体テストは、プログラマーテストと呼ばれる場合もあるが、それは、プログラマーが単体テストのツールをコードの小さな部分以上のものをテストするために使っているため。
- 単体テストのツールは、単体、機能、システムなど、どのレベルでのテストでも用いられている。
ストーリーテスト(受け入れテスト)
- ストーリーテストは、システムのビジネス側の意図を示している
- 顧客の仕事をこなす際に、ソフトウェアが適切に顧客をしえんしているかどうかを見極めるためのテスト。
- コーディング前にストーリーテストが書かれていると、顧客の仕事にどんな作業が含まれているか、そしてそれをどのようにソフトウェアで支援していくことになるのかを、全員がじっくり考えるのに役に立つ。
- チームは、システムが何をしなくてはならないかを示す例を通して、作業を進める
- ストーリーテストは、実例より示される仕様書になる
- 前もって仕様を書くなら、実行可能な形式にしても良い、後でテストを書くムダや、コードが仕様どおりになっているかを確認するムダが省ける。
- 自動のストーリーテストは、ユーザインターフェースからは実行されない
- 一般的には、ユーザインターフェースよりも下で実行される。
- これを実現するには、ユーザーインターフェースは、非常に薄いプレゼンテーション層でなくてはならず、すべてのロジックやポリシーはそれよりも下の、独立してテスト可能な層になくてはならない
- 通常の残りのユーザインターフェース層は、ビジネスロジックから独立して、完全にテストが出来る
- ストーリーテストは、自動化し、現実的な範囲で出来るだけ頻繁に実行すべき
- 通常、ストーリーテストはサーバやデータベースを必要とするため、ビルド時のテスト一式には含まれない。
- ストーリーテストをいくつか選び出したものを毎日実行し、さらに完全に近いテスト一式を毎週実行すべき。
- そして、イテレーションの最後にはすべてのテストが成功しなくてはならない。
ユーザビリティテストと探索的テスト
- ユーザビリティテストや探索的テストは、その性質上、手作業で行うテスト
- 自動テストを通ったら、システムが求められているとおりの挙動をしているというこになる
- ユーザビリティテストは、実際のユーザがシステムの試験を行う
- 探索的テストは、経験を積んだテスト技術者たちが、境界条件や予期せぬ入力に対するシステムの挙動をチェック
- 探索的テストによって、コードのもろい部分が発見されたら、開発者たちに何をすべきかを示すテストを書いて、テスト装置に加えなくてはならない。
特性テスト
- 特性テストには、応答時間や拡張性、堅牢性など、いわゆる非機能要件へのテストが含まれる。
- 負荷をかけた状態でシステムをテストしたり、セキュリティ問題をチェックしたりするための専用ツールがある
- 考えられるシステムの構成をすべてテストするための、連結テストを生成するツールもある
- ツールが自分たちの環境に適しているようなら、時間や労力を割いて、ツールを使いこなさるようなると良い
- 開発プロセスの初期段階でそのようなツールを使ってみる
- 実際の操作条件に出来る限り近い環境でも使ってみる
構成管理
構成管理は、どのようなソフトウェア開発でおいても、中心に位置する規律
- 1.コードのどの部分あっても、一度に数人が手を入れられる
- 2.リリースが小規模で、頻繁である
- 3.ある機能セットが商用リリースされる間に、新機能が開発されている
- 4.コードベースの全体に絶えずリファクタリング(継続的な改善)が行われる
構成管理システムは、コードを変更しようとしている人たちにコードを貸し出して、コードが返ってきたら新シバージョンを正しくリファクタリングする、図書館員(ライブラリアン)のような役目を果たす。
コードのリポジトリはだけでなく、ドキュメントやテスト結果の管理にも利用できるため、規則の厳しい環境では特に有用。 どのような開発組織にも、組織内での用途に合った構成管理システムがなくてはならない。 そのシステムの使い方もきちんと定めておく。
構成管理システムの用途の典型的なシナリオをいくつか紹介
シナリオ1
- 開発者が個人の作業スペースにファイルをチェックアウトする
- そこで、変更を行い、コードをチェックインする直前に、各自のマシン上にある最新コードとマージして、個人環境でのブル度のテストを行う
- すべてがうまくいったら、新しいコードを構成管理システムにチェックインする
- それをトリガーとして、統合環境でのビルドのテストが行われる
シナリオ2
- リリースのタイミングで、そのリリースに入るすべてのコードを含めたブランチが作られる。
- 開発者はメインのコードベースに新機能を続ける
- リリースのテストや保守の間に行われた変更はすべて、できるだけ早く、メインのコードベースにマージされる(コードがイテレーションの一部としてリリースされたり、修正なしにブランチが導入されたりする場合には、このシナリオは不要)
継続的な統合
- コードが個別の作業スペースにチェックアウトされたり、別のブランチに分けられたりすると、からなず2つのコード系統で不一致が発生する。
- 別々のコード系統として存在する期間が長ければ長いほど、その不一致大きくなる。
- 頻繁に統合すればするほど、初期問題を捉えやすく、その原因を特定しやすい
ただ、開発者は開発スピードや都度起動するテストによって、開発時間をが削られることを嫌い、そのような理由から、コードベースに統合する前に、大量にコードを溜め込んでおこうという気になる。
- 統合の間隔をあけても逆効果である
しかし、一度ソフトウェア開発チームがすばやいビルドや継続的な統合を実現する方法を見つけ、問題発見時にただたちにその対処のために、全員が誠実に作業を中断できるようになれば、神業に匹敵するほどの効果が得られる。
これが非常に実践しづらい規律であることは、いくどとなく言われてきたが、いったん上手く言ってしまえば、誰も古いやり方に戻そうとは考えないはず。
入れ子になった同期
- 独立したチーム同士で、サブシステムを結合しようとした場合、何が起きる?
変更されることもないのだから、最終的にサブシステムが結合される段階になっても、なんら問題が起きないはず。
だが、現実はそのようにうまくいくことは殆どない。
事実、開発プログラムを締めくくりでのサブシステム結合の失敗が、スケジュールのずれ込みやコスト超過、プログラムそのものの失敗の、最大の原因の一つになってきた。
- ソフトウェアを木と考え、サブシステムを枝と考えれば、どこに問題があるか、大体見当がつくと思う。
通常、枝をそれぞれ別に育てて、それから木の幹に接ぎ木しようとはしない。 サブシステムは生きた幹から育てていくべき、幹にあたるシステムがないのなら、それを最初に構築すべき。 それからサブシステムを有機的にシステムと結合させれば、最後にすべてを接合させようとして気を揉む必要もない。
- 別々のコード系列についての法則は、より大きなサブシステムでも当てはまる。
インターフェースを定義して、それが上手く動くのを期待するのではなく、実際にまずインターフェースを定義してそれを動かし、それからサブシステムを構築して、現実的な範囲でできる限り頻繁に統合すべき。
実際に行うとした場合
- 継続的に統合から手を付ける
- 開発者が、一日に何度かコードをチェックインする
- それが、トリガーとなって、自動のビルドとテストが行われ、細部にいたるまで、依然としてすべてが同期した状態にあるかどうかを検証する。
- 受け入れテスト装置は、夜間に実行
- さまざまな構成やプラットフォームのテストは、週末に行う
- イテレーションごとにコードベース全体を同期し、「リリース可能な」状態にする
- 他のサブシステムや、ハードウェアとの同期を行う場合もある。
- リリースごとにコードを導入し、顧客と同期する
大規模システムや分散開発チームの場合
- 入れ子になった同期がさらに欠かせないものになる
- 継続的にコミュニケーションをとり、定期的にチーム全体の知識を1か所集積させるための基盤となる。
密接な関係を持つサブシステムに取り組むチーム間では
- 共通のコードベースから離れて作業を進め、お互いの作業を同期すべき。
主要なサブシステムは
- イテレーションの終わりごとに接合させなくてはならない
大規模プロジェクトでは
- システム全体を現実的な範囲で出来るだけ頻繁に同期すべき