開発の現場から | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ソフトウェアの開発にはさまざまな問題が伴います.たとえば皆さんの周りから次のよ うな会話が聞こえてくることはないでしょうか?
どうでしょうか.皆さんの開発現場はこれほどではないかもしれませんが,もしかする と思い当たるものもあるのではないでしょうか. プログラミングが好きでソフトウェア業界に入った方も多いのではないかと思いま す.でも現実は,毎晩毎晩の残業.たび重なる仕様変更.延々と続くデバッグ.どんど ん延びていく開発期間.その度に自分に鞭打ち,家族に苦しい言い訳をし,そうして 完成させたシステムだけども,顧客の当初の要求範囲を中途半端に縮小し,思いもか けない入力による障害が発生し,開発側も顧客側も,もうこれ以上開発を続けること はできないということで苦しい妥協をする. 何故なのでしょうか? 一人で好きなものを作っていたときは,あんなに楽しかったの に・・・・ あなたがプログラマならば,一度や二度は自分でも最高だと思うようなプログラムを 書いたことがあるのではないでしょうか? その最高は,なぜ,顧客の最高に結びつ かないのでしょうか? みんな,いい仕事がしたい(だらしない仕事はしたくない)と 思っているのに,なぜ,うまくいかないのでしょうか・・・ XPならできるここに1つのソフトウェア開発方法(プロセス)があります.このプロセスはプログラ マに常に達成感を与えてくれます.このプロセスはプログラマが常に最高の能力を発 揮できるような環境を提供してくれます.このプロセスはプログラマに過酷な作業を 強いません.それでいて,顧客に対して,一番欲しい機能を,一番欲しい順に提供し ます.そがXP(エクストリーム・プログラミング)です. |
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つの価値を示しています.
コアプラクティスXPではプロジェクトが従うべき実践項目を13個のコアプラクティスとして定めていま す(※). (※) XPのプラクティスとしては従来12または14個のものが知られていますが,ここ では,Ron Jeffriesが論文"What is Extreme Programming?"で述べているコア プラクティスを説明します プラクティスとは経験に基づき,その有用性が立証されてきたテクニックのことで す.XPでは13個のコアプラクティス全てを最大限に実践します.ゆえにエクストリー ム(= 極限)という名前があります.コアプラクティス全てを最大限に実践することに より,個々のプラクティスが相互に関連しあい,プロジェクトを安定させ,かつ,生 産性を高くします. Fig.2にコアプラクティスの全てとその間の関係を示します.以下では,各プラク ティスについて簡単に説明します.
|
XPの開発の流れ | ||||
XPの開発の流れを簡単に示します. サークルオブライフXPの開発はFig.3に示すサークルを描きます.顧客が定義した価値 に対してプログラマがコストを見積り,そのコストに応じて顧客が価値を選択し,そ して選択された価値をプログラマが作ります.この流れは各リリース/イテレーショ ンで繰り返し行われ,学習によって各作業の精度が上がっていきます.
開発の流れXPにおける開発の流れをFig.4に示します.
開発は顧客が要求をユーザストーリとして提示することより始まります.チームは ユーザストーリを元に数ヶ月単位のリリース計画と,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"というツールが存在します.例え ば,
などです.この他にも数多くの言語や環境に対応するxUnitが提供されています. xUnitを使用することにより誰でも簡単に自動化テストのための環境を構築すること ができます.ここではCppUnitを例にその方法を簡単に紹介します.なお,書籍 「 eXtreme Programmingテスト技法」では,各xUnitの使い方や応用例が詳しく紹介さ れています. CppUnitのダウンロードRon Jeffriesのサイト(xprogramming.com )の「Downloads」 のリンクを辿って,CppUnitをダウンロードします.本記事執筆時点では C++ Ver 1.5(ファイル名:CppUnit15.zip)です. ダウンロードしたファイルを展開するとFig.5に示す構成になっています.
テストの記述方法テストを記述するためには,TestCaseを継承したクラスを作成します.そして,その中に名前が"test"で始まるメソッドを追加してテストを記述します. テストメソッドでは以下のメソッドを使用してテスト結果の検証を行います.
クラスには,テストメソッドの他に以下の3つのメソッドを定義します.
テストの実行方法テストの実行にはTestRunnerクラスを使用します.TestRunnerにはテキスト版とGUI 版の2種類があります. テキスト版のTestRunnerを実行する場合は,以下のようにmain()を記述します.
テキスト版の実行は,コマンドの引数にテストケース名を渡します.
GUI版のTestRunnerでは,OnNewDocument()またはOnInitDialog()の中に以下の処理を 記述します.
GUI版の実行はダイアログのRunボタン押下で行います.テストスイートに登録された 全テストが実行され,全てパスした場合はプログレスバーが緑色に,1個でも失敗し た場合は赤色になり,失敗したテストの内容が表示されます(Fig.6).
自動ユニットテストを実際に使ってみようxUnitを使用した自動ユニットテストは,XPに限らず他の開発方法においても非常に 有効です.ぜひ取り入れていって下さい.ここでは簡単にしか説明しませんでした が,サンプルを実行して,関連するソースを眺めれば,比較的容易に理解できると思 います. なお,CppUnitのサンプルの実行方法ですが,GUI版はVC++のプロジェクトとなってい るため,culib → TestRunner → HostAppの順でビルドしていけば問題なく実行でき ます.テキスト版に関しては次に示すmakeファイルを使えば簡単に構築することがで きます.(ただし,コマンドの実行パスに nmake.exe と cl.exe が含まれていること を前提としています.これらのコマンドは例えばC:\Program Files\Microsoft Visual Studio\VC98\binの配下にあります) CppUnitではテストメソッドを記述する他に,自分でテストスイートを構築する必要 があるため少し面倒です.この解決方法として,先に紹介した書籍「eXtreme Programmingテスト技法」にはスクリプト言語を使用して自動的にテストスイートを 構築する方法が紹介されています.
|
実践ペアプログラミング | ||||||||||||||||||||||||||||||||||
XPではペアプログラミングをプラクティスの1つと定めているけれど,本当に効果が あるの? どんな風に行われるの? 疑問を感じている方もいらっしゃると思います.そ こで,実際のペアプログラミングの作業風景を実況中継的に紹介したいと思います. このペアプログラミングは2001年11月に実際に行ったものです.括弧内には時間経過 を示しました.なお,記事を書くために特別に行ったもので,開発の中で行われたも のではありませんが,その雰囲気は感じていただけると思います. 登場人物は(HF)と(KH)の2名です.どちらもプログラミング経験10年以上で,ほぼ同 じレベルでのペアになります. タスクカード
(※) このBigNumという概念はLisp文化から来ており,無限の桁数を取り扱えること が特徴です.ちなみにC言語のint(32bit)で取り扱える数値の桁数は9桁まで, 64bitでも19桁までとなります. 生成(14:10~)
(HF) どこから始めようか (KH) まずは
(HF) 了解.単純に生成したら0ということだね.じゃ最初にBigNumTestを書こう.
(HF) まずはテストを実行.でもBigNumがないからコンパイルエラー.じゃBigNumを 作ろう.クラス内部で数値を保持しないといけないね.どう保持しようかな. (KH) まずはすごくシンプルにデフォルトコンストラクタと,0を返すintオペレータの みにしたらどうかな. (HF) そうだね.じゃ
(HF) じゃテストを実行.よーしOK.数値からの生成を実装しよう.まずはテストを 書いてと
テストのコンパイルは当然失敗.じゃBigNumを修正しよう.今度もシンプルに数値 はintで保持するようにしてしまおう.
(KH) メンバ変数の初期化は代入ではなく,初期化リストを使うべきだね. (HF) あ,そうか.よしできた.
(HF) テストを実行して.よしOK. じゃ,次は文字列からの生成を実装しよう.まず はテストから.
(HF) コンパイルには失敗.じゃBigNumを書こう.そろそろ決断をしないといけない ね.クラス内部の数値は文字列で保持しようか,それともintのvectorにしようか. (KH) どっちも良し悪しがあるね.どっちが好き. (HF) んー,文字列で実装しよう.まずは文字列を扱うように直そう. (KH) その間にSTLの本を取ってくるね.
(HF) 数値を文字列に変換しないといけないから,これにはtoString()というメソッド があればOK. よし,次はtoInt()とtoString()を実装しよう.数値と文字列間の変換か.Java のStringクラスみたいにtoInt()とかあるのかな? (KH) ないみたいだね.でも確か,stringstreamを使えばできるはずだよ.cinやcout のように使うんだ.私が書くよ.
(HF) じゃテストを通して見よう.よしOK. (KH) BigNumTestのsuite()にテストメソッドを追加していくのは大変だね.マクロを 作ろうか.
(HF) そうだね,マクロにしよう.(...コーディング...) あ,testCreate12sは実行 されてなかった.suite()にtestCreate1のメソッドで登録してしまっている. マクロにして正解だね.
(HF) よしこれでOK.テストもOK. (KH) ちょっと休憩しようか.タバコ吸ってくる. 整数との加減算(15:00~)(HF) 整数との加減算を実装しよう.でもこれはintオペレータがあるから簡単に通っ てしまうんじゃないかな.
(HF) テストを実行.よし,OK.
(HF) これもOK.何も修正しなくても通っちゃたね. BigNum同士の加算(15:05~)(HF) じゃいよいよ,BigNum同士の加算を実装しよう.add()メソッドは現在の値に引 数を足しこむようにしたいね.まずはテストを書いてと.
(HF) テストはコンパイルで失敗.じゃadd()を実装しよう. (KH) 文字列操作での加算になるしアルゴリズムが複雑だね.ちょっと紙の上で作戦 を練ろう.えーと,互いの文字列のlength()-1から0までを順に足していけばよくて・・・ 長い方の文字列をmax()で求めて・・・ (HF) 結果の文字列はせいぜいmax()+1の長さだね・・・
(KH) なんとなく感じが掴めたので,私が書くよ. (HF) どうぞ. (...コーディング...) (KH) えーと,長い方の文字列の長さをmaxに入れて,短い方の長さをminに入れて・・・ (HF) それぞれの長さを別々に管理しないと,配列の領域外アクセスが避けられないのでは? (KH) これでもいけるはずだよ.一通り書かせて. (HF) 了解 (...コーディング...) (HF) for文の中がゴチャゴチャになってきたね.何をやりたいのかが曖昧になってき ているような・・・ (KH) やりたいことを外に出そう.やりたいのは,
(2)に関しては1の桁からアクセスするから,桁を指定して数値を取り出せるように しても便利かも (HF) 有効な桁を超えたら0を返すようにすると,文字列の長さの違いを管理しなくて もいいから便利じゃないかな. (KH) そうだね.じゃ.
(KH) よし,できた.これを使ってadd()をコーディングしよう.
(KH) 完成. 引数をthatにして,thisとthatでネーミング的にいいかなと思ったのに,this はポインタだから"->"でthatは参照だから"."なので今一つかな."->"を使うか "."を使うかの判断を人に要求するのがC++の難点かな.コンパイラが勝手に判 断してくれればいいのに. (KH) テストを実行.あれNGだ.結果として2を期待しているのに0になっている. num_とresultをcerrに出してデバッグしてみよう. DEBUG: result = '' (KH) んー.何も入っていない.なぜだろう. (HF) わかった.reminderへの代入の所だよ.toAscii()が抜けてる. (KH) そうか.
(KH) 実行して見よう.よしOKだ.でもデバッグ出力が何か変だ.
(HF) resultが0終端されてないのかな. (KH) いや,string result('0', max + 1) で,この場合は"00"となっているはず. 生成直後のresultをデバッグ出力に出してみようか.
(KH) resultのサイズが47になっている,2になるはずなのに!! (HF) なぜ,^Bなのだろう.^Bのアスキーコードは2だから・・・ そうか,わかっ た.stringのコンストラクタの引数が逆なんだ. (KH) マニュアルを見ると・・・. その通り.なんでコンパイラは警告してくんない のかな?
(KH) これでテストをして,OK. デバッグ出力もOK.そうだ,外部演算も必要だね. (HF) じゃ交代して,まずはテストから.BigNumを活かした大きな数にしよう.
(HF) これでテスト.あれ,パスしちゃった. (KH) intオペレータでint変換されて,桁落ちしてテストに通ってしまったんじゃな いかな.んー,どうしようかな.よし,こうしよう. (KH) BigNumに,空の+オペレータと==オペレータを追加しよう.
(KF) この==オペレータは絶対に失敗しないから,テストは不要だ.これでテストを 行うと,よし,失敗している. (HF) じゃ,+オペレータを本当に実装しよう.
(HF) テストを実行.よし,OK.思ったより時間がかかったね.一休みしよう. リファクタリング(16:00~)(KH) これでタスクはすんだけど,リリースする前に気になるところを直しておこう か.休憩の間に考えたんだけど,add()を+=オペレータにしたいのと,メソッド 内のローカル変数の名前が気になる. (KH) 辞書を引いて・・・ 余りはremeinderじゃなくてremainderだ.それと,商は divisionじゃなくてquotientだ. (KH) add()を+=オペレータにして,add()を使っている所と,テストも直して,テス ト実行,よしOK. (HF) 私はadd()のループの中がやっぱり分かりにくいので何とかしたいけど,いい方 法が思いつかない. (KH) じゃ,このメソッドの戦略をコメントにして入れておこう. (HF) そうしよう.コメントを追加して,一応テストしてOK.じゃ,リリースしよう. 終了(~16:20)
実際のペアプログラミングの雰囲気は伝わったでしょうか? 2人とも久しぶりのC++で のプログラミングでしたので,オペレータオーバーローディングや参照に関してC++ 言語が持つ独特のくせのようなものに苦しめられました.また,この中では触れてい ませんが,実際はコンパイル時のエラーでも苦しんでいます.しかし,このC++のく せに関する知識をペアの間でうまく補い合うことができました. できあがったBigNumクラスですが,使用に耐えるものとはなっていません.intオペ レータを実装したことの可否(toInt()メソッドにするべきだったかどうか),int演算 でのオーバーフローの未考慮,マイナス演算や負の値の未考慮など,まだまだ,実装 が不完全です.ただし,与えられた仕様の範囲内で十分な実装と言えるでしょう.こ の後,実際に必要なエラーケース等を含んだ仕様をタスクとして追加していくことに なります.
|
最後に | ||||
話題のプログラム開発プロセス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関連情報と参考文献を紹介して,筆 をおくことにします.
|
8. XP関連情報 |
8.1 XPの本
8.2 関連技術
8.3 関連サイト
8.4 メーリングリスト
|
9. 参考文献 |
|