Skip to content.

Sections
Personal tools
You are here: Home » コミュニティ » XP-jp » XP関連記事 » XPは私達に何をもたらすのか

Document Actions

all of that review

第1版(平成14年1月28日)
(株)永和システムマネジメント
藤本 聖(hiziri@esm.co.jp)
平鍋 健児(hiranabe@esm.co.jp)

   目次

  1. 導入
  2. 開発の現場から
  3. XPとは
  4. xUnitの紹介
  5. XPで幸せになるのだろうか
  6. 実践ペアプログラミング
  7. 最後に
  8. XP関連情報
  9. 参考文献

   はじめに

今,世の中を騒がしている2つのXPがあります.1つはマイクロソフトのWindows XP, もう1つは,eXtreme Programming(エクストリーム・プログラミング)です.Windows XP(eXPerienceを指す)についてはほかにお任せし,本稿では,もう一方のXPである エクストリーム・プログラミングについて解説したいと思います.

日本にXPが紹介されて約2年になります.その間に,XPについての書籍が出版され,雑 誌で特集が組まれ,また,各地で講演が行われて,広く知られるようになってきまし た.そこで,本稿はで単なるXPの入門解説ではなく,「XPは私達を幸せにしてくれるん じゃない?」というプログラマの視点から観点でXPを紹介したいと思います.また,注 目されているアジャイル宣言やXPの日本でのローカライゼーションについても触れたい と思います.


   開発の現場から

ソフトウェアの開発にはさまざまな問題が伴います.たとえば皆さんの周りから次のよ うな会話が聞こえてくることはないでしょうか?

プログラマ: 「稼動は7月末か.総合テストに1ヶ月,結合テストに1ヶ月必要だから,そうする と,設計が1ヶ月,プログラミングが1ヶ月!? そんなん,できるわけないじゃん.」
メンバ: 「リーダ,ここですけど,数量が負の時はどうすればいいんですか? 設計書には 書いてないんですけど」
リーダ: 「そこ? んー どうだっだかな.質問書に記入しておいてよ.来週,お客さんのとこ ろに進捗報告に行くから,そのときに聞いてくるよ.それまで,他のところを進めてて」
開発者: 「当方が提出している仕様に関する質問書ですが,質問の321番と322番に関して,回 答をいただいていませんので,よろしくお願いします」
顧客: 「321番だけどさ,前に○○さんが来たときに,説明したんだけど」
顧客: 「えぇ! 稼動をさらに1ヶ月延ばしたいって!? 当初の計画からすでに1ヶ月伸ばして いるんだよ.困るな」
顧客: 「商品検索で色での検索はできませんか?」
開発者: 「検索に関しては種類とサイズの2つの検索のみとなります.設計完了段階でお出し している仕様書に対して,お客様からも承認印を頂いております」
顧客: 「それはそうなんだけど,現場から,それがないと困るという意見が出てて」
開発者: 「それならば,仕様変更ということになりますので,別途,開発期間と費用を見積も らせて頂きたいと思いますが」
顧客: 「・・・・」
リーダ 「これが内部の開発線表だから遅れないように頼むよ.お客さんには+2週間の線表で 報告してるけど,あくまでも保険のためだからね」
結合担当者: 「なんだよ,このソース,コンパイル通らないじゃないか.おーい担当者を呼んでく れ.えー,もう帰った.どうすんだよ,今日の結合」
プログラマ: 「誰だよ,おれのソースに手を入れたのは.あの処理は不要に見えたかもしれないけ ど,ほかの所で使ってたんだぞ.おかげで,動かなくなってしまったじゃないか」
プログラマ: 「この印刷のロジックですけど,あっちこっちに似たようなのがあるのでまとめてし まってはどうでしょうか?」
リーダ: 「わかっているんだけど,今からやって何か障害が出ると怖いからやめておこう.そ れに,その方がステップ数が多くなるからお客さんに報告するときに都合がいいよ」
開発者: 「その機能を付けると,データベースのスキーマが変更になりますので,全てのテス トをやりなおす必要があります.再テストには約2週間必要です」
顧客: 「進捗だと90%までできているようですね,こちらの方でも動かして見たいので提供 してもらえませんか?」
開発者: 「90%完成していますが,それは個々の機能レベルです.こちらのテスト環境でしか 動作しませんので,提供は難しいです」
リーダ: 「無事稼動したことだし,そろそろ仕様書のメンテナンスを始めようか.分担を決め るから,担当部分を読んで赤入れをしてくれるかな.あと,差し替えをするから,最 新の画面をファイルに取り込んでくれるか」

どうでしょうか.皆さんの開発現場はこれほどではないかもしれませんが,もしかする と思い当たるものもあるのではないでしょうか.

プログラミングが好きでソフトウェア業界に入った方も多いのではないかと思いま す.でも現実は,毎晩毎晩の残業.たび重なる仕様変更.延々と続くデバッグ.どんど ん延びていく開発期間.その度に自分に鞭打ち,家族に苦しい言い訳をし,そうして 完成させたシステムだけども,顧客の当初の要求範囲を中途半端に縮小し,思いもか けない入力による障害が発生し,開発側も顧客側も,もうこれ以上開発を続けること はできないということで苦しい妥協をする.

何故なのでしょうか? 一人で好きなものを作っていたときは,あんなに楽しかったの に・・・・

あなたがプログラマならば,一度や二度は自分でも最高だと思うようなプログラムを 書いたことがあるのではないでしょうか? その最高は,なぜ,顧客の最高に結びつ かないのでしょうか? みんな,いい仕事がしたい(だらしない仕事はしたくない)と 思っているのに,なぜ,うまくいかないのでしょうか・・・

XPならできる

ここに1つのソフトウェア開発方法(プロセス)があります.このプロセスはプログラ マに常に達成感を与えてくれます.このプロセスはプログラマが常に最高の能力を発 揮できるような環境を提供してくれます.このプロセスはプログラマに過酷な作業を 強いません.それでいて,顧客に対して,一番欲しい機能を,一番欲しい順に提供し ます.そがXP(エクストリーム・プログラミング)です.


   XPとは

XPは繰り返し型のライトウェイトな開発プロセスです. ほかの開発方法と比べて以下の点を特徴とします.

  • 開発の中で発生するさまざまな変化を自然に受入れ,それに対応していくことを 基本姿勢としている.XPではこれを"Embrace Change(変化ヲ抱擁セヨ)"として あげている
  • 開発の中でテストを非常に重視する.すべてのテストは自動化され,かつ,コー ディングに先立って記述される.この自動化テストがXPの開発の基盤
  • 初期設計よりもリファクタリングによる再設計を重視します.設計は今回必要と なることのみに限定し,先々必要となるであろうことには考慮しない
  • XPを行うにあたって従うべき実践項目(=「プラクティス」)が明確に示されている

XPの生い立ち

XPは,Smalltalkのコミュニティから生まれました.生みの親はKent Beck とWard Cunninghamです.1996年に伝説的なプロジェクトC3(Chrysler Comprehensive Compensation)において,Kent BeckはRon Jeffries,Martin Fowler らと共にXPを実践しました.

その後,Kent Beckは1999年に"Extreme Programming Explained - Embrace Change" (翻訳書は「 XPエクストリーム・プログラミング入門」)という最初のXP本を書き,世の中に XPを提示しました.

ちなみに,Kent BeckとWard Cunninghamは,ソフトウェアパターンの開祖となる一派 (Hillside Group)であり,建築家Christopher Alexanderの「パターン言語」のアイ ディアを初めてソフトウェアに取り入れ,1987年のオブジェクト指向に関するカンファ レンス「OOPSLA'87」で"Using Pattern Languages for Object-Oriented Programs"と して発表しています.また,Martin Fowlerは"Refactoring"(翻訳書は「 リファクタリング」)の著者です.リファクタリングはXPの重要なプラクティスで すが,XPにおいてはじめてその有用性が確かめられ理論化されたともいえます.

4つの価値

XPでは,開発チームが何に重きを置くかの判断基準として, 以下に示す4つの価値を示しています.

  1. コミュニケーション
    コミュニケーションは4つの価値の内で最も重要なものです.XPは顧客と開発者,ま た,開発者同士のコミュニケーションがあって初めて成り立ちますし,ゆえに,積極 的にコミュニケーションを推進します.


  2. シンプルさ
    XPの戦略の基本はシンプルさです.今必要とされることのみ実装を行います.将来を 考えて複雑さを持ち込むことは行いません.将来のことは,それが本当に必要になっ たときに初めて行います.この根底には,変更のコストは時間と共に増加していくも のではなく,ある一定のレベルで抑えることが可能であるというXPの考え方がありま す(Fig.1).
    Fig.1 時間と変更のコスト
  3. フィードバック
    XPではフィードバックを常に求めます.テストを中心とした開発を行うことにより, システムからのフィードバックを,リリースを頻繁に行うことにより顧客からの フィードバックを得やすくします.


  4. 勇気
    コミュニケーション,シンプルさ,フィードバックの3つの価値は,開発者に勇気を 与えます.実装済みの多くの機能に影響を与えるような変更を行ったり,うまくいき そうにないアプローチのコードを捨てたりすることを勇気を持って行うことができま す.

コアプラクティス

XPではプロジェクトが従うべき実践項目を13個のコアプラクティスとして定めていま す(※).

(※) XPのプラクティスとしては従来12または14個のものが知られていますが,ここ では,Ron Jeffriesが論文"What is Extreme Programming?"で述べているコア プラクティスを説明します

プラクティスとは経験に基づき,その有用性が立証されてきたテクニックのことで す.XPでは13個のコアプラクティス全てを最大限に実践します.ゆえにエクストリー ム(= 極限)という名前があります.コアプラクティス全てを最大限に実践することに より,個々のプラクティスが相互に関連しあい,プロジェクトを安定させ,かつ,生 産性を高くします.

Fig.2にコアプラクティスの全てとその間の関係を示します.以下では,各プラク ティスについて簡単に説明します.

Fig.2 コアプラクティス関連図
  1. チーム全体(Whole Team)
    XPは「顧客」を含めたチームでプロジェクトを進めます.顧客がチームに入り,開発 者の直ぐそば(オンサイト)で一緒に仕事を進めます.ここが他の開発方法と大きく異 なる所です.顧客はビジネスの代理人であり,最大のビジネス価値が得られるように チームに対する要求を定義し,そのプライオリティを設定します.また,プログラ マからの質問にフルタイムで答えます.


  2. 計画ゲーム(Planning Game)
    XPの開発は顧客とプログラマが共同でシンプルな計画を立てることから始めます.顧 客が要求をストーリとして提示することから始まり,そのストーリを元に数ヶ月単位 のリリース計画と2~3週間単位のイテレーション計画を立てます.この計画は開発の 間,継続的に行います.

    XPでは顧客のビジネス価値を常に最大に保つことを重視します.これにより顧客は満 足し,プロジェクトは継続していきます.

  3. 顧客テスト(Customer Tests)
    XPの顧客は,チームに提示した機能が正しく実装されていることを確認するために, 受入れテストを定義します.この受入れテストは必ず自動化され,システムのリリー ス時に常に実行されます.チームはこの受入れテストにより,必要とされる機能が正 しく実装できたこと,および,既に実装済みの機能に悪い影響を与えていないことを 確認します.

  4. 小さなリリース(Small Releases)
    XPではリリースごと,そして2~3週間のイテレーションごとに実際に動くプログラムを提供します.小さな単位で頻繁に顧客に提供し,実際に使ってもらうことにより,顧客に対して最短の時間で最大のビジネス価値を提供し,そして顧客から最大のフィードバックを得ます.

  5. シンプルな設計(Simple Design)
    システムは可能な限りシンプルに設計します.XPでは開発を通して,設計を常に行い ます.求められている機能を実装するために最もシンプルな設計を素早く行い,そし て実装を進めます.

    XPには'YAGNI'という言葉があります.You Are not Gonna Need It(あなたは多分そ れを必要としない)の略です.実装するのは最低限必要な機能のみで,必要となるで あろう機能については実装を行いません.何故ならば,それは今は不要な機能であ り,コード量を増やして可読性を落とし,メンテナンスを難しくします.そして顧客 のビジネス価値を高めることに対して何の貢献もしないからです.

    「XPエクストリーム・プログラミング導入編」の中では,コードのシンプルさについ て以下のように述べられています.
    1. 全てのテストをパスし,
    2. 意図(何をしたいのか)が明確に表現されており,
    3. どんなことも一度,ただ一度だけ記述されており,
    4. 上記を満たしながらクラスとメソッドの数が最小である

  6. ペアプログラミング(Pair Programming)
    コーディングは常に2人がペアになって1台のコンピュータに向かって行います.常に ペアでプログラミングを行うことにより,コードは常にレビューされることになり, 単純ミスが減り品質が上がります.

    ペアプログラミングの作業コストは1人(シングル)で行う場合と比較して200%になる と考えてしまいますが,論文「The Cost and Benefits of Pair Programming」の実 験によると,そのコストは115%であるとの結果が出ています.しかも,シングルと比 較して,ペアプログラミングのコードの欠陥率は15%低く,また,コードサイズは 80%(多分,良い設計がなされている)との結果も出ており,作業時の15%のオーバヘッ ドは,これらによって相殺されると考えられます.

    また,ペアでプログラミングを行うことによりチーム内での知識の共有や各自のスキ ルアップが自然に行われます.このことはプロジェクトのトラックナンバー(※)を増 やす上でも重要です.

    (※) トラックナンバー トラックに轢かれるとプロジェクトが継続できなくなるメンバーの人数.最悪は1で, これは1人のスーパーマンがプロジェクトのキーとなっているケース.

  7. テストファースト開発(Test-First Development)
    プログラマはコーディングに先立ってまずテストプログラム(ユニットテスト)を書き ます.そして,そのユニットテストにパスするまでコーディングとテストを繰り返し ます.このユニットテストはコードと一緒にリリースされ,システムにコードを追加 するときは,そのシステムの全ユニットテストにパスする必要があります.また,プ ログラムを作成する前にテストを書くことにより,その機能を「使う」ことに焦点を 当たり,結果として良い設計へ繋がります.

  8. 設計の洗練(Design Improvement)
    XPのシンプルな設計は「リファクタリング」によって洗練されていきます.リファク タリングによって,システムを現在求められている機能を提供するためにもっともシ ンプルに設計された状態に保ちます.

    ユニットテストと受入れテストは,リファクタリングで間違った変更をしたのではな いかという不安からチームを解放してくれます.

  9. コードの共同所有(Collective Code Ownership)
    XPではコードの担当者を決めません.全てのコードは全員で共有し,誰でもコードを 自由に変更することができます.

    この共同所有によりコードが多数の人の目によってチェック(レビュー)され品質が向 上します.また,各担当者が同じような機能を自分担当のコードの中に抱え込むと いった弊害がなくなります.

  10. コーディング標準(Coding Standard)
    全てのコードはプロジェクト標準のコーディングルールで記述します.チーム全員が 同じ基準でコードを書くことにより,ペアプログラミングを円滑にし,また,コード の共同所有にも貢献します

  11. 継続的インテグレーション(Continuous Integration)
    XPでは1日に何回でもインテグレーション(結合)を行います.ユニットテストが完了 したタスクは,すぐにシステムに結合され,全ユニットテストが行われて,リポジト リに登録されます.

    頻繁に結合を行うことにより,プログラマ間の変更の衝突が起きにくくなります.ま た,誤って他の機能を壊してしまっても,すぐに検出することができます.

  12. メタファ(Metaphor)
    システムの動きを理解するために,チーム全員がメタファ(比喩)と呼ばれるビジョン を共有します.メタファはシステムがどのように動くかを説明した,誰にでも分かる シンプルな例え話です.チームはこのメタファを使って互いのコミュニケーションを よりスムーズにします.

    例えばC3プロジェクトでは,給与支払いシステムのメタファとして工場の生産ライン を使いました.時間の部品を取ってきて,お金の部品に加工し,その他の経費の部品 を組み込んで,最終的に給料ができあがるといった感じです.

  13. 適切なペース(Sustainable Pace)
    XPではいつまでも持続可能なペースで作業を行います.このプラクティスは以前は 「週40時間労働」と呼ばれていました.

    What is Extreme Programming より ~
    「最近ではデスマーチプロジェクトは生産的でもないし,高品質のソフトウェアを生 産するものでもないことが,よく理解されてきている.XPチームは勝つためにエクス トリームなのであり,死ぬためにエクストリームなのではない」

   XPの開発の流れ

XPの開発の流れを簡単に示します.

サークルオブライフ

XPの開発はFig.3に示すサークルを描きます.顧客が定義した価値 に対してプログラマがコストを見積り,そのコストに応じて顧客が価値を選択し,そ して選択された価値をプログラマが作ります.この流れは各リリース/イテレーショ ンで繰り返し行われ,学習によって各作業の精度が上がっていきます.

Fig.3 サークルオブライフ

開発の流れ

XPにおける開発の流れをFig.4に示します.

Fig.4 XPの開発の流れ

開発は顧客が要求をユーザストーリとして提示することより始まります.チームは ユーザストーリを元に数ヶ月単位のリリース計画と,2~3週間単位のイテレーション 計画を立てます.

リリース計画ではプログラマは顧客の説明を聞きながら,提示されたユーザストーリの難易度(コスト)を見積もります.それをもとに,顧客が次のリリース時期と,そこに盛り込むべきストーリを決定します.盛り込むストーリの取捨選択は,ストーリの難易度と顧客が持つビジネス優先度から決定します.

イテレーション計画ではリリース計画で盛り込まれたストーリの内,直近の2~3週間 (イテレーション)でどのストーリを行うかを決定します.顧客により提示されたス トーリは,チームのブレーンストーミングにより実装の検討が行われ,さらに詳細な 機能(タスク)へとブレークダウンされます.その後,各プログラマは自分がどのス トーリを担当するのかを決定します(サインアップと呼びます).

ブレークダウンされたタスクは,プログラマが通常1~2日で完了できる量であり,ペ アによるテストファーストの開発で実装が行われます.


   XPで幸せになれるのだろうか

XPはプログラマを幸せにしてくれるのでしょうか? 想像して見て下さい,あなたは今, XPで開発を行っています・・・

あなたはリーダではなく顧客から直接ストーリカードを受け取る.そして,見積りを 行う.見積りは難しい作業だが,あなたは気楽に行える.仕様が不明な点は目の前に いる顧客に聞けばいいし,見積りの単位も数ヶ月ではなく1~2週間程度だ.仮に見積 もりがぶれたとしても,次の計画の時に軌道修正が可能だ.

顧客はあなたの見積りをもとにストーリの優先順位を決めてリリース計画を立ててい る.あなたは自分の思う通りの順番でストーリを実装していきたいと思うかもしれな い.でもそれは違うんだ.どの順番で実装していけばよいかを一番知っているのは顧 客だ.あなたはその順番に従って実装を行い顧客を喜ばせればよい.どれを先にすれ ばよいかで思い悩まなくていいんだ.

顧客から次のイテレーションで行うべきストーリが提示された.皆でどのように実装 すべきかを短時間で検討する.楽しく刺激的な時間だ.ストーリはタスクにブレーク ダウンされ難易度がつけられた.あなたのチームでは難易度を単純に2点や3点といっ た点数で表している.あなたは2週間のイテレーションで行う分,つまり8点分のス トーリを選択し名前を書き込む.サインアップが完了した.目標が決まった.あなた は自分がサインアップしたストーリの実装に専念すればよい.

朝のスタンドアップミーティングであなたは今日実装するタスクを決定する.進捗会 議なんてないし,毎週(あるいは毎日)提出する進捗資料もない.進捗状況はどのス トーリのどのタスクまで完了したかということで明白だし,完了したかどうかはテス トが教えてくれる.

あなたは彼をペアプログラミングの相手として選んだ.彼と一緒に1つ目のタスクを 実装していく.ペアプログラミングと聞いて最初は違和感を感じたが,実際に行って いみると非常に楽しいことがわかった.あなたは自分のやりたい事を口にしながら コーディングを進めていく.言葉にすることで今から行うことがあなたの中で明確に なる.もしあなたが一人ならば他からは怪しげなやつに見えるかもしれない.でもペ アプログラミングなのだから全然変じゃない.困ったことがあれば遠慮なく彼に聞 く.一人で悩む必要はない.彼はすぐに教えてくれるかもしれないし,マニュアルを 取りに行ってくれるかもしれない.あなたと彼は共に助け合いながら一緒にコーディ ングをしているのだ.

あなたはまずテストを実装して実行する.テストは失敗だ.あたりまえだ,今から実装するのだから. あなたは実装に取り掛かる.今回の実装にはあのクラスが使えそうだ.あなたはクラスを修正する. 自分が作ったクラスではないが失敗を恐れる必要はない.彼が横で見てくれているし, そのクラスにもユニットテストが用意されている. ユニットテストを実行すればあなたがミスをしたかどうかすぐに分かる.

実装を終えてテストを実行.よしOKだ.実装,コンパイル,そして実行.この完結 した作業に達成感を感じる.自分でヘッダを誤魔化しながらコンパイルする必要もな し,実行は1週間後の結合までできないなんてこともXPではありえない.

あなたは彼と結合マシンに移動して結合を行う.システムに用意されている全てのユ ニットテストが次々に実行されていく.よし全てOKだ.このタスクはストーリの最後 のタスクだ.顧客が定義した受入れテストを実行する.緊張の一瞬.よし通った.あ なたは顧客が求めているものを,今作り終えたのだ.

コードをリポジトリに登録し,慣習に従って結合マシンの横の鈴を鳴らす.「チー ン].近くでコーディングしているメンバが親指を突き出して「イェイ」と言ってく れた.あなたは誇らしげに自分の席に戻っていく.

午後6時.今日の作業は完了した.あなたはオフィスを後にする.まだ明るい.あな たはアスレチックジムへ向かった.

どうでしょうか,かなり美化していると思われるかもしれません.しかし,XPが定義 する開発のベクトルとプログラマの幸せのベクトルは同じ方向を向いていると感じら れなかったでしょうか?


   xUnit

XPでは自動化されたテストに非常にこだわります. xUnitはテスト(特にユニットテスト)を自動化するためのテスティング フレームワークです.xUnitという名前は総称で,テストの対象となるプログラミン グ言語(あるいは実行環境)に応じて"何とかUnit"というツールが存在します.例え ば,

JUnitJava用
CppUnitC++用
VBUnitVisual Basic用
NUnit.NET用

などです.この他にも数多くの言語や環境に対応するxUnitが提供されています.

xUnitを使用することにより誰でも簡単に自動化テストのための環境を構築すること ができます.ここではCppUnitを例にその方法を簡単に紹介します.なお,書籍 「 eXtreme Programmingテスト技法」では,各xUnitの使い方や応用例が詳しく紹介さ れています.

CppUnitのダウンロード

Ron Jeffriesのサイト(xprogramming.com )の「Downloads」 のリンクを辿って,CppUnitをダウンロードします.本記事執筆時点では C++ Ver 1.5(ファイル名:CppUnit15.zip)です.

ダウンロードしたファイルを展開するとFig.5に示す構成になっています.

Fig.5 CppUnitの構成

テストの記述方法

テストを記述するためには,TestCaseを継承したクラスを作成します.そして,その中に名前が"test"で始まるメソッドを追加してテストを記述します.

テストメソッドでは以下のメソッドを使用してテスト結果の検証を行います.

assert(bool condition) 論理式conditionが成立するかどうかをチェックする
assertLongsEqual(long expected, long actual) 実際の値actualが期待した値expectedと等しいことを チェックする
assertDoublesEqual(double expected, double actual, double delta) 実際の値actualが期待した値expectedの近似値(delta 以内)であることをチェックする

クラスには,テストメソッドの他に以下の3つのメソッドを定義します.

static Test *suite() 各テストメソッドから構成されるテストスイートを返すようにします.
void setUp() 必要に応じて各テストの実行に先立って行わ前処理を記述します.
void tearDown() 必要に応じて各テストの実行後に行う後始末処理を記述します.

ExampleTestCase.h
#include "TestCase.h"
#include "TestSuite.h"
#include "TestCaller.h"

using namespace std;

class ExampleTestCase : public TestCase {
  protected:
    string *value_;

  public:
    ExampleTestCase(string name) : TestCase(name) {}

    void setUp() {
        value_ = new string("test");
    }

    void tearDown() {
        delete value_;
    }

    static Test *suite() {
        TestSuite *testSuite = new TestSuite("ExampleTestCase");

        testSuite->addTest(
                new TestCaller("testLong", testLong));
        testSuite->addTest(
                new TestCaller("testDouble", testDouble));
        testSuite->addTest(
                new TestCaller("testString", testString));

        return testSuite;
    };

  protected:
    void testLong() {
         assertLongsEqual(2, (1 + 1));
    }

    void testDouble() {
         assertDoublesEqual(2.0, (1.0 + 0.99), 0.1);
    }

    void testString() {
         string s("test");
         assert(value_ != &s);
         assert(*value_ == s);
    }
};

テストの実行方法

テストの実行にはTestRunnerクラスを使用します.TestRunnerにはテキスト版とGUI 版の2種類があります.

テキスト版のTestRunnerを実行する場合は,以下のようにmain()を記述します.

int main(int ac, char **av) {
    TestRunner runner;

    runner.addTest("ExampleTestCase", ExampleTestCase::suite());
    runner.run(ac, av);

    return 0;
}

テキスト版の実行は,コマンドの引数にテストケース名を渡します.

   > TestRunner.exe ExampleTestCase

GUI版のTestRunnerでは,OnNewDocument()またはOnInitDialog()の中に以下の処理を 記述します.

    TestRunner runner;

    runner.addTest(ExampleTestCase::suite());
    runner.run();

GUI版の実行はダイアログのRunボタン押下で行います.テストスイートに登録された 全テストが実行され,全てパスした場合はプログレスバーが緑色に,1個でも失敗し た場合は赤色になり,失敗したテストの内容が表示されます(Fig.6).

Fig.6 TestRunner

自動ユニットテストを実際に使ってみよう

xUnitを使用した自動ユニットテストは,XPに限らず他の開発方法においても非常に 有効です.ぜひ取り入れていって下さい.ここでは簡単にしか説明しませんでした が,サンプルを実行して,関連するソースを眺めれば,比較的容易に理解できると思 います.

なお,CppUnitのサンプルの実行方法ですが,GUI版はVC++のプロジェクトとなってい るため,culib → TestRunner → HostAppの順でビルドしていけば問題なく実行でき ます.テキスト版に関しては次に示すmakeファイルを使えば簡単に構築することがで きます.(ただし,コマンドの実行パスに nmake.exe と cl.exe が含まれていること を前提としています.これらのコマンドは例えばC:\Program Files\Microsoft Visual Studio\VC98\binの配下にあります)

CppUnitではテストメソッドを記述する他に,自分でテストスイートを構築する必要 があるため少し面倒です.この解決方法として,先に紹介した書籍「eXtreme Programmingテスト技法」にはスクリプト言語を使用して自動的にテストスイートを 構築する方法が紹介されています.

#
# makefile for CppUnit/samples
#

FW      = ../test/framework

INCS    = /I $(FW)
CPP     = cl.exe
CPPFLAGS = /c /GX /GR $(INCS)

OBJECTS = ExampleTestCase.obj

all: $(OBJECTS)
#
# makefile for CppUnit/test/framework
#

INCS    = 
CPP     = cl.exe
CPPFLAGS = /c /GX /GR $(INCS)

OBJECTS = TestCase.obj TestFailure.obj TestResult.obj TestSuite.obj

all: $(OBJECTS)
#
# makefile for CppUnit/test/textutil/
#

TS      = ../../samples
FW      = ../framework

INCS    = /I $(TS) /I $(FW)
CPP     = cl.exe
CPPFLAGS = /c /GX /GR $(INCS)

IMPORT  = $(TS)/ExampleTestCase.obj $(FW)/TestCase.obj $(FW)/TestFailure.obj \
          $(FW)/TestResult.obj $(FW)/TestSuite.obj

OBJECTS = TestRunner.obj TextTestResult.obj

TARGET  = TestRunner.exe

all: $(OBJECTS)
        $(CPP) /Fe$(TARGET) $(OBJECTS) $(IMPORT)


   実践ペアプログラミング

XPではペアプログラミングをプラクティスの1つと定めているけれど,本当に効果が あるの? どんな風に行われるの? 疑問を感じている方もいらっしゃると思います.そ こで,実際のペアプログラミングの作業風景を実況中継的に紹介したいと思います.

このペアプログラミングは2001年11月に実際に行ったものです.括弧内には時間経過 を示しました.なお,記事を書くために特別に行ったもので,開発の中で行われたも のではありませんが,その雰囲気は感じていただけると思います.

登場人物は(HF)と(KH)の2名です.どちらもプログラミング経験10年以上で,ほぼ同 じレベルでのペアになります.

タスクカード

  クラスBigNum(※)を作成する.機能は以下の通り.
    ・ 20桁以上の数値を取り扱うことができる
    ・ 整数(int)および文字列から生成できる
    ・ 整数との加算・減算ができる
    ・ BigNum間で加算ができる
	

(※) このBigNumという概念はLisp文化から来ており,無限の桁数を取り扱えること が特徴です.ちなみにC言語のint(32bit)で取り扱える数値の桁数は9桁まで, 64bitでも19桁までとなります.

生成(14:10~)

Fig.7 ペアプログラミングの風景

(HF) どこから始めようか

(KH) まずは

  BigNum n; n == 0
  
からでどう?

(HF) 了解.単純に生成したら0ということだね.じゃ最初にBigNumTestを書こう.

class BigNumTest : public TestCase {
 public:
    BigNumTest(string name) : TestCase(name) {}

    void testCreate() {
        BigNum n;
        assertLongsEqual(0, n);
    };

    static Test *suite () {
        TestSuite *testSuite = new TestSuite("BigNumTest");
        testSuite->addTest(new TestCaller 
                           ("testCreate", testCreate));
        return testSuite;
    }
};

(HF) まずはテストを実行.でもBigNumがないからコンパイルエラー.じゃBigNumを 作ろう.クラス内部で数値を保持しないといけないね.どう保持しようかな.

(KH) まずはすごくシンプルにデフォルトコンストラクタと,0を返すintオペレータの みにしたらどうかな.

(HF) そうだね.じゃ

class BigNum {
 public:
    BigNum() {}

    operator int() {
        return 0;
    }
};

(HF) じゃテストを実行.よーしOK.数値からの生成を実装しよう.まずはテストを 書いてと

    void testCreate1() {
        BigNum n(1);
        assertLongsEqual(1, n);
    }

テストのコンパイルは当然失敗.じゃBigNumを修正しよう.今度もシンプルに数値 はintで保持するようにしてしまおう.

    BigNum() {
        num_ = 0;
    }
	

(KH) メンバ変数の初期化は代入ではなく,初期化リストを使うべきだね.

(HF) あ,そうか.よしできた.

class BigNum {
 private:
    int num_;

 public:
    BigNum() : num_(0) {}

    BigNum(int num) : num_(num) {}


    operator int() {
        return num_;
    }
};

(HF) テストを実行して.よしOK. じゃ,次は文字列からの生成を実装しよう.まず はテストから.

    void testCreate12() {
        BigNum n("12");
        assertLongsEqual(12, n);
    }

(HF) コンパイルには失敗.じゃBigNumを書こう.そろそろ決断をしないといけない ね.クラス内部の数値は文字列で保持しようか,それともintのvectorにしようか.

(KH) どっちも良し悪しがあるね.どっちが好き.

(HF) んー,文字列で実装しよう.まずは文字列を扱うように直そう.

(KH) その間にSTLの本を取ってくるね.

class BigNum {
 private:
    string num_;

 public:
    BigNum() : num_("0") {}

    BigNum(int num) : num_(toString(num)) {}

    BigNum(string snum) : num_(snum) {}

    operator int() {
        return toInt(num_);
    }
};

(HF) 数値を文字列に変換しないといけないから,これにはtoString()というメソッド があればOK. よし,次はtoInt()とtoString()を実装しよう.数値と文字列間の変換か.Java のStringクラスみたいにtoInt()とかあるのかな?

(KH) ないみたいだね.でも確か,stringstreamを使えばできるはずだよ.cinやcout のように使うんだ.私が書くよ.

    static string toString(int num) {
        stringstream out;
        out << num;
        return out.str();
    }

    static int toInt(string snum) {
        int out;
        stringstream converter;
        converter << snum;
        converter >> out;
        return out;
    }
	

(HF) じゃテストを通して見よう.よしOK.

(KH) BigNumTestのsuite()にテストメソッドを追加していくのは大変だね.マクロを 作ろうか.

    static Test *suite () {
        TestSuite *testSuite = new TestSuite("BigNumTest");
        testSuite->addTest(new TestCaller 
                           ("testCreate", testCreate));
        testSuite->addTest(new TestCaller 
                           ("testCreate1", testCreate1));
        testSuite->addTest(new TestCaller 
                           ("testCreate12s", testCreate1));
        return testSuite;
    }

(HF) そうだね,マクロにしよう.(...コーディング...) あ,testCreate12sは実行 されてなかった.suite()にtestCreate1のメソッドで登録してしまっている. マクロにして正解だね.

#define ADD_TEST(name) addTest(new TestCaller  (#name, name))

    static Test *suite () {
        TestSuite *testSuite = new TestSuite("BigNumTest");
        testSuite->ADD_TEST(createTest);
        testSuite->ADD_TEST(create1Test);
        testSuite->ADD_TEST(create12sTest);
        return testSuite;
    }

(HF) よしこれでOK.テストもOK.

(KH) ちょっと休憩しようか.タバコ吸ってくる.

整数との加減算(15:00~)

(HF) 整数との加減算を実装しよう.でもこれはintオペレータがあるから簡単に通っ てしまうんじゃないかな.

    void testCalcSimplePlus() {
        BigNum n(1);
        assertLongsEqual(2, (1 + n));
    }

(HF) テストを実行.よし,OK.

    void testCalcSimpleMinus() {
        BigNum n(1);
        assertLongsEqual(0, (n - 1));
    }

(HF) これもOK.何も修正しなくても通っちゃたね.

BigNum同士の加算(15:05~)

(HF) じゃいよいよ,BigNum同士の加算を実装しよう.add()メソッドは現在の値に引 数を足しこむようにしたいね.まずはテストを書いてと.

    void testAdd() {
        BigNum n(1), n1(1), n2(2);
        n.add(n1);
        assert(n2 == n);
    }

(HF) テストはコンパイルで失敗.じゃadd()を実装しよう.

(KH) 文字列操作での加算になるしアルゴリズムが複雑だね.ちょっと紙の上で作戦 を練ろう.えーと,互いの文字列のlength()-1から0までを順に足していけばよくて・・・

長い方の文字列をmax()で求めて・・・

(HF) 結果の文字列はせいぜいmax()+1の長さだね・・・

Fig.8 アルゴリズムのスケッチ

(KH) なんとなく感じが掴めたので,私が書くよ.

(HF) どうぞ.

(...コーディング...)

(KH) えーと,長い方の文字列の長さをmaxに入れて,短い方の長さをminに入れて・・・

(HF) それぞれの長さを別々に管理しないと,配列の領域外アクセスが避けられないのでは?

(KH) これでもいけるはずだよ.一通り書かせて.

(HF) 了解

(...コーディング...)

(HF) for文の中がゴチャゴチャになってきたね.何をやりたいのかが曖昧になってき ているような・・・

(KH) やりたいことを外に出そう.やりたいのは,

  1. 文字列の長さを求める
  2. 文字列から指定したインデックスの文字を取り出す
  3. 数値文字を数値に変換する
  4. 数値を対応する文字に変換する

(2)に関しては1の桁からアクセスするから,桁を指定して数値を取り出せるように しても便利かも

(HF) 有効な桁を超えたら0を返すようにすると,文字列の長さの違いを管理しなくて もいいから便利じゃないかな.

(KH) そうだね.じゃ.

    static int toDigit(char c) {
        return c - '0';
    }

    static int toAscii(int i) {
        return i + '0';
    }

    int getDigit(int index) const {
        return toDigit(num_[index]);
    }

    int getColumnDigit(int column) const {
        return (num_.length() <= column) ?
                    0 : getDigit(num_.length() - 1 - column);
    }

    int getColumnCount() const {
        return num_.length();
    }

(KH) よし,できた.これを使ってadd()をコーディングしよう.

    void add(const BigNum& that) {
        int max = max(this->getColumnCount(), that.getColumnCount()); 
        string result('0', max + 1);

        int division = 0;
        for (int i = 0; i < max + 1; i++) {
            int sum = this->getColumnDigit(i) +
                      that.getColumnDigit(i) +
                      division;

            int reminder = sum % 10;
            division = sum / 10;

            result[max - i] = reminder;
        }
        if (result[0] == '0') {
            result.erase(0, 1);
        }
        num_ = result;
    }

(KH) 完成. 引数をthatにして,thisとthatでネーミング的にいいかなと思ったのに,this はポインタだから"->"でthatは参照だから"."なので今一つかな."->"を使うか "."を使うかの判断を人に要求するのがC++の難点かな.コンパイラが勝手に判 断してくれればいいのに.

(KH) テストを実行.あれNGだ.結果として2を期待しているのに0になっている. num_とresultをcerrに出してデバッグしてみよう.

DEBUG: result = ''

(KH) んー.何も入っていない.なぜだろう.

(HF) わかった.reminderへの代入の所だよ.toAscii()が抜けてる.

(KH) そうか.

            result[max - i] = toAscii(reminder);

(KH) 実行して見よう.よしOKだ.でもデバッグ出力が何か変だ.

    DEBUG: result = '2^B^B^B^B^B^B^B^B^B^B^B^B^B^B^B^B^B^B・・'

(HF) resultが0終端されてないのかな.

(KH) いや,string result('0', max + 1) で,この場合は"00"となっているはず. 生成直後のresultをデバッグ出力に出してみようか.

    DEBUG: result = '^B^B^B^B^B^B^B^B^B^B^B^B^B^B^B^B^B^B・・'
    DEBUG: result.length() = 47;

(KH) resultのサイズが47になっている,2になるはずなのに!!

(HF) なぜ,^Bなのだろう.^Bのアスキーコードは2だから・・・ そうか,わかっ た.stringのコンストラクタの引数が逆なんだ.

(KH) マニュアルを見ると・・・. その通り.なんでコンパイラは警告してくんない のかな?

        string result(max + 1, '0');

(KH) これでテストをして,OK. デバッグ出力もOK.そうだ,外部演算も必要だね.

(HF) じゃ交代して,まずはテストから.BigNumを活かした大きな数にしよう.

    void testBigAdd() {
        BigNum n1( "55555555555555555555");
        BigNum n2( "77777777777777777777");
        BigNum n3("133333333333333333332");
        assert(n3 == (n1 + n2));
    }

(HF) これでテスト.あれ,パスしちゃった.

(KH) intオペレータでint変換されて,桁落ちしてテストに通ってしまったんじゃな いかな.んー,どうしようかな.よし,こうしよう.

(KH) BigNumに,空の+オペレータと==オペレータを追加しよう.

    bool operator+(const BigNum& that) const {
        BigNum empty;
        return empty;
    }

    bool operator==(const BigNum& that) const {
        return (this->num_ == that.num_);
    }

(KF) この==オペレータは絶対に失敗しないから,テストは不要だ.これでテストを 行うと,よし,失敗している.

(HF) じゃ,+オペレータを本当に実装しよう.

    BigNum operator+(const BigNum& that) const {
        BigNum result(*this);
        result.add(that);
        return result;
    }

(HF) テストを実行.よし,OK.思ったより時間がかかったね.一休みしよう.

リファクタリング(16:00~)

(KH) これでタスクはすんだけど,リリースする前に気になるところを直しておこう か.休憩の間に考えたんだけど,add()を+=オペレータにしたいのと,メソッド 内のローカル変数の名前が気になる.

(KH) 辞書を引いて・・・ 余りはremeinderじゃなくてremainderだ.それと,商は divisionじゃなくてquotientだ.

(KH) add()を+=オペレータにして,add()を使っている所と,テストも直して,テス ト実行,よしOK.

(HF) 私はadd()のループの中がやっぱり分かりにくいので何とかしたいけど,いい方 法が思いつかない.

(KH) じゃ,このメソッドの戦略をコメントにして入れておこう.

(HF) そうしよう.コメントを追加して,一応テストしてOK.じゃ,リリースしよう.

終了(~16:20)

Fig.9 完了したタスクカード

実際のペアプログラミングの雰囲気は伝わったでしょうか? 2人とも久しぶりのC++で のプログラミングでしたので,オペレータオーバーローディングや参照に関してC++ 言語が持つ独特のくせのようなものに苦しめられました.また,この中では触れてい ませんが,実際はコンパイル時のエラーでも苦しんでいます.しかし,このC++のく せに関する知識をペアの間でうまく補い合うことができました.

できあがったBigNumクラスですが,使用に耐えるものとはなっていません.intオペ レータを実装したことの可否(toInt()メソッドにするべきだったかどうか),int演算 でのオーバーフローの未考慮,マイナス演算や負の値の未考慮など,まだまだ,実装 が不完全です.ただし,与えられた仕様の範囲内で十分な実装と言えるでしょう.こ の後,実際に必要なエラーケース等を含んだ仕様をタスクとして追加していくことに なります.

BigNum.h
#include 
#include 
#include 
#include 

using namespace std;

class BigNum {

 private:
    string num_;

    static string toString(int num) {
        stringstream out;
        out << num;
        return out.str();
    }

    static int toInt(string snum) {
        int out;
        stringstream converter;
        converter << snum;
        converter >> out;
        return out;
    }

    static int toDigit(char c) {
        return c - '0';
    }

    static int toAscii(int i) {
        return i + '0';
    }

    int getDigit(int index) const {
        return toDigit(num_[index]);
    }

    int getColumnDigit(int column) const {
        return num_.length() <= column ?
                0 : getDigit(num_.length() - 1 - column);
    }

    int getColumnCount() const {
        return num_.length();
    }

 public:
    BigNum() : num_("0") {
    }

    BigNum(int num) : num_(toString(num)) {
    }

    BigNum(string snum) : num_(snum) {
    }

    BigNum(const BigNum& that) : num_(that.num_) {
    }

    operator int() const {
        return toInt(num_);
    }

    BigNum operator+(const BigNum& that) const {
        BigNum result(*this);
        result += that;
        return result;
    }

    bool operator==(const BigNum& that) const {
        return (this->num_ == that.num_);
    }

    void operator+=(const BigNum& that) {
        /*
         * 1の位から1桁ずつ足していく.繰り上がりがあるため,
         * 最大桁+1まで操作を行い,最大桁が0(繰り上がりなし)ならば
         * 削除する
         */

        int len = max(this->getColumnCount(), that.getColumnCount()); 
        string result(len + 1, '0');

        int quotient = 0;
        for (int i = 0; i < len + 1; i++) {
            int sum = this->getColumnDigit(i) +
                      that.getColumnDigit(i) +
                       quotient;

            int remainder = sum % 10;
            quotient = sum / 10;

            result[len - i] = toAscii(remainder);
        }

        if (result[0] == '0') {
            result.erase(0, 1);
        }
        num_ = result;
    }
};

BigNumTest.h
#include "TestCase.h"
#include "TestSuite.h"
#include "TestCaller.h"

#include "BigNum.h"

using namespace std;

#define ADD_TEST(name) addTest(new TestCaller  (#name, name))

class BigNumTest : public TestCase
{
 public:
    BigNumTest(string name) : TestCase(name) {}

    void testCreate() {
        BigNum n;
        assertLongsEqual(0, n);
    };

    void testCreate1() {
        BigNum n(1);
        assertLongsEqual(1, n);
    }

    void testCreate12s() {
        BigNum n("12");
        assertLongsEqual(12, n);
    }

    void testSimplePlus() {
        BigNum n(1);
        assertLongsEqual(2, (1 + n));
    }

    void testSimpleMinus() {
        BigNum n(1);
        assertLongsEqual(0, (n - 1));
    }

    void testAdd() {
        BigNum n(1), n1(1), n2(2);
        n += n1;
        assert(n2 == n);
    }

    void testBigAdd() {
        BigNum n1( "55555555555555555555");
        BigNum n2( "77777777777777777777");
        BigNum n3("133333333333333333332");
        assert(n3 == (n1 + n2));
    }

    static Test *suite () {
        TestSuite *testSuite = new TestSuite("BigNumTest");

        testSuite->ADD_TEST(testCreate);
        testSuite->ADD_TEST(testCreate1);
        testSuite->ADD_TEST(testCreate12s);
        testSuite->ADD_TEST(testSimplePlus);
        testSuite->ADD_TEST(testSimpleMinus);
        testSuite->ADD_TEST(testAdd);
        testSuite->ADD_TEST(testBigAdd);
        return testSuite;
    }
};


   最後に

話題のプログラム開発プロセスXPについて,プログラマの幸せという観点から述べて きました.私がXPに関心があるのも,自分がプログラマとしてワクワクするからで す.「Teenage Sex(皆が話題にするけど,本当に実行している人は少ないの例え)」と 影口を叩かれるXPですが,多くの人が引きつけられるのも,やはりこのワクワク感か らではないでしょうか.

締めくくりとして,XPの周辺と日本におけるXPのローカライゼーションについて述べ たいと思います.

アジャイル宣言

人気を集めているXPですが,XPのみがライトウェイトなプロセスとしての考え方を実 現しているわけではありません.

アジャイル宣言」 (Agile Manifesto)は,アジャイルアライアンス( www.agilealliance.org)から 出された宣言文で,以下のような骨子です.

私たちは,
プロセスとツールよりも個人と対話に,
包括的なドキュメントよりも動くソフトウェアに,
契約交渉よりも顧客との協調に,
計画に沿うことよりも変化に対応することに,
価値をおく.

この宣言に参加しているのは,

Kent Beck, Mike Beedle, Arie van Bennekum, Alistair Cockburn, Ward Cunningham, Martin Fowler, James Grenning, Jim Highsmith, Andrew Hunt, Ron Jeffries, Jon Kern, Brian Marick, Robert C. Martin, Steve Mellor, Ken Schwaber, Jeff Sutherland, Dave Thomas

で,XPをはじめ, Scrum, 達人プログラマ(Pragmatic Programmer),DSDM, Crystal, Adaptive Software Developmentなどといった開発手法の中心人物たちです.これら の手法は,より現場的,実践的な視点から現代的ソフトウェア開発に一つの光を投じ ています.XPもこの大きな「アジャイル ムーブメント」の1つとして見ることができ ます.

XPの日本的ローカライゼーション

XPをそのまま適用することが,必ずしも正しいとは言えません.自分たちの環境に合 わせてプラクティスを適合させていく必要があると言えるでしょう.特に,日本での XPの適用を考えると幾つかの問題があります.
  • ドキュメントは?

    日本のソフトウェア開発,特に受託開発では,納品物としてドキュメントを求められ ることが避けられないことがあります.たとえそれが,開発後につじつま合わせで作 られたものであってもです.

    また,XPは「コードで意図を表現」するのが本筋なのですが,コードが英語になりが ちな現状のソフトウェア開発では,ある程度日本語のドキュメントやコメントがない と意図がうまく伝わらないこともあるでしょう.

    このように,英語がネイティブあるいはほぼ通じる文化でのプログラミングと,そう ではない日本のような文化でのプログラミングでは,ドキュメントの考え方が少し異 なるように思えます.

    ここは,一つのローカライズポイントでしょう.英語と日本語を対応させた用語辞書 やクラスの役割を記述した最小限のドキュメントは,XPといえども必要になると考え られます.

  • 契約と商習慣

    次に,特に受託開発においては「契約」の問題があります.XPでは最初にスコープを 全部決めてしまう訳ではないので,機能をコミットしてそれを見積もって契約すると いうことができません.最悪,

    「10人で6ヶ月ベストを尽くしますので,60人月になります」

    という契約になってしまいます.例えばパイロット開発を人月精算で短い期間行なっ て開発速度を測定し,そしてその後の本番開発で契約するなどの工夫が必要です.

    さらに,一般に大きな受託開発ではユーザから大手メーカーが一次受託し,それを傘 下のソフトハウスが二次受託するという形態が多く取られます.その場合に「ユーザ と一次受託者の契約」,「一次受託者と二次受託者の契約」をどうするのかという問 題もあります.XPでは「チーム全体」を考える必要があるのですが,そのチーム全体 が複数の企業にまたがってしまうことがあります.

    これらの問題も,日本での適用の大きなポイントと言えるでしょう.

  • 日本におけるXP実例

    日本における固有の問題もありますが,日本でXPを実際に適用されている方もいらっ しゃいます.

    NECの牛尾さんは,「ストーリーカードをプリペイドカードとして顧客に渡す」,と いうとても素敵な契約方法でXPにトライされています(Fig.10).

    Fig.10 プリペイド式XP契約手法

    松下ソフトリサーチの土屋さんは,ソフトウェア開発の中でも,特にファームウェア のテスティングに重点的にXPを適用しています(Fig.11). その現場では,テスト項目をカードベースで管理して独自のテストプロセスを確立して います.これは,XPのプラクティス全部というより,自分達の問題にXPの「スピリッ ト」を吹き込むことで積極的に現場を改善している例とも言えます.

    Fig.11 テスティングへのXPの適用

    XP は多くの人がその有効性を認めており,これから日本でも適用が進むと思われま す.日本での普及が進むには,やはりこのような「適用事例」の報告が多数必要だと 考えています.

是非みなさんも,以下のような場所で適用事例を報告し,本当に日本の現場で使える 手法として,XPを育てて行きませんか.最後に,XP関連情報と参考文献を紹介して,筆 をおくことにします.


   8. XP関連情報

8.1 XPの本

  1. XPエクストリーム・プログラミング入門 ソフトウェア開発の究極の手法
    • ピアソン・エデュケーション
    • XPの最初の本です.4つの価値や各プラクティスの詳細と関係などを含めて, XPの基本的な考え方について解説されています.

  2. XPエクストリーム・プログラミング導入編 XP実践の手引き
    • ピアソン・エデュケーション
    • XPを実践する上での各種テクニックを著者の実体験を踏まえて解説されています. プログラマは必読.

  3. XPエクストリーム・プログラミング実行計画
    • ピアソン・エデュケーション
    • XPを実際に行う上での計画の立て方について解説されています.

8.2 関連技術

  1. eXtreme Programmingテスト技法 xUnitではじめる実践XPプログラミング
    • 技術評論社
    • JUnit, HttpUnit, RubyUnit, WebUnit, VBUnit, CppUnit等のxUnitを使った 具体的なテストの実行方法や,AntとCVSを使った自動ビルド&テスト方法に ついて解説されています.

  2. リファクタリング :プログラミングの体質改善テクニック
    • ピアソン・エデュケーション
    • XPの技術ベースの1つであるリファクタリングの本です.

8.3 関連サイト

  1. Ron JeffriesのXPサイト
    • http://www.xprogramming.com/
    • Ron JeffriesのXP総合サイトです.様々な情報の他にxUnitのダウンロードが できます.

  2. eXtreme Programming FAQ

  3. 日本XPユーザグループ(XPJUG)
    • http://www.xpjug.org/
    • 日本におけるXPの普及を目的としたユーザグループです. 定期的にユーザ会やセミナー等を開催しています.

  4. JUnit

8.4 メーリングリスト

  1. XP-jp ML

  2. XP ML

   9. 参考文献

  1. XPエクストリーム・プログラミング入門
    • Kent Beck著, 長瀬嘉秀監訳, ピアソン・エデュケーション

  2. XPエクストリーム・プログラミング導入編
    • Ron Jeffries, Ann Anderson, Chet Hendrickson著, 平鍋健児他訳, ピアソン・エデュケーション

  3. XPエクストリーム・プログラミング実行計画
    • Kent Beck, Martin Fowler著, 長瀬嘉秀監訳, ピアソン・エデュケーション

  4. eXtreme Programmingテスト技法
    • 日本XPユーザグループ著, 長瀬嘉秀監修, 翔泳社

  5. ピープルウェア 第2版 ヤル気こそプロジェクト成功の鍵
    • Tom DeMarco, Timothy Lister著, 松原友夫/山浦恒央訳, 日経BP社

  6. オブジェクトハンドブック 2002
    • 平鍋健児監修, ピアソン・エデュケーション

  7. まるごと図解 最新 オブジェクト指向がわかる
    • 河合昭男著, 技術評論社

  8. リファクタリング
    • Martin Fowler著, 児玉公信,友野昌夫,平澤章,梅野真史訳, ピアソン・エデュケーション

  9. The Costs and Benefits of Pair Programming
    • Alistair Cockburn

  10. What is Extreme Programming?

  11. The New Methodology

  12. eXtreme Programming の魅力を探る - 新世紀のソフトウェア開発手法

  13. XP FAQ
    • 平鍋健児

  14. アジャイル宣言