ARCHIVES
アーカイブス
アーカイブス

eXtreme Programmingがしたい!

日経BP 日経ソフトウエア 2002年5月号特集 「XPはソフトウエア開発をどう変えたか?」の原稿を元に再構成

山本 啓二・水谷 雅宏
2002年05月01日
※内容は公開当時のものです

日本でXPが話題になりはじめてから、もう2年以上が経つでしょうか。それまで工業的に捕らえられがちだったソフトウエア開発において、その人間系の側面に光を当てたものとしてXPは多くの開発者に支持されてきています。しかし、国内においてXPを適用した事例はまだなかなか目に付きません。「ペアプロ楽しそ~!」、「テストファーストなんてやってられるの!?」といった期待に満ちたプログラマ達の声や、他の方法論などと比べてどうだという議論ばかりが聞こえてきます。

そうした期待や議論ももちろん大切ですが、XPは机上の空論や空疎な理念の単なるマニフェストではありません。顧客の最大利益を実現することで開発者を満足させるプラクティスです。実際のプロジェクトに適用してみてはじめてその良さが実感される性質のものです。

XPは他の多くの方法論や管理手法と同様アメリカ生まれの開発手法ですので、日本でのソフトウエア開発にそのまま適用できるプラクティスばかりとは限りません。また国内に限ってみても、顧客との関係や対象とするアプリケーションの質などは個々のプロジェクトで千差万別でしょう。より効果的な方法を顧客と開発チームが共に模索していかなくてはなりません。

本稿は、わたしたちがXPを実プロジェクトに適用した記録です。これからXPを適用していこうと考える開発者のみなさんの参考となれば幸いです。

プロジェクト概要

システムについて

前述のとおりプロジェクトの特質は千差万別であり、XPの取り込みかたもプロジェクト次第ですから、まずわたしたちがXPを適用したプロジェクトについて理解していただくことが必要でしょう。 今回の顧客は凸版印刷様でした。開発対象となったのは、メール・Webによるマーケティングサービスを行うシステムです。最終的にはパッケージ化あるいはASP化を目指していきますが、まずは東京お台場にある、「メディアージュ」(注1)で実証実験を行います。

どのようなサービスかというと、複合商業施設やイベントなどの来場者へ、携帯電話を介して情報を提供しよう、というものです。たとえば、メディアージュに映画を見に来たら、次の上映時間まで1時間ありました。じゃあそれまで近くをウロウロして時間をつぶすか......という来場者がサービスを受けると、始めてすぐに「メディアージュへようこそ!」というメールが届きます。メールに書かれたURLから館内情報案内のWebページを見ることが出来ます。30分後には「歩きまわって疲れてない? お茶を飲むならこんなお店があるよ!」、上映時間直前に「もうすぐはじまるよ」、上映終了後には「おなか空いてない? ごはんを食べるなら夜景のキレイなお店へどうぞ!」といったように、参加者の属性(この場合「映画Aを待っている人」)と時間軸(参加して何分後、あるいは何時何分という絶対時間)に合わせて、携帯電話向けのメール+Webでコンテンツを提供できます。

単なるメールマガジンや情報サイトにとどまらず、時間と来場者の属性を軸により的確な情報を提供することで、来場者の利便性を図ります。それによって、運営者が来場者の動線をあるていど制御することも期待でき、施設・イベントの活性化を実現します。

とはいえ、これは最終形で、プロジェクトの開始時点では、どのような情報提供の仕方が有効なのかははっきりしていません。さまざまな議論はなされましたが、実際の来場者が、どんな場面でどんな情報をほしいと感じるものなのか、携帯を使うことのメリットやデメリット、それにもちろんシステム的な実現方法、制限などは想像の域にとどまっています。もっと利用者に施設を使いこなしてもらう、それに役立つシステムを作っていこう、とだけ決まっています。

そのため、当初まずはプロトタイピングを行い、技術的な実証とサービスの検証を行うことが決定されました。

顧客チーム

このプロジェクトの顧客は、コンテンツビジネスや出版、施設運営などのプロフェッショナルからなるチームです。それぞれの分野では一流の方々が揃っていますが、この事業においてひとつの軸となるべきITシステムの分野に精通した方はいません。そこでわたしたちにお声がかかり、ビジネスプランの段階からコンサルタントとしてプロジェクトに参画させていただくこととなりました。開発チームは彼を擬似顧客とすることで、オンサイトに準ずるビジネスニーズとのコミュニケーションを保ちました。

擬似顧客は、顧客チームのサイトに常駐し、企画立案段階から共にアイディア出しを行いつつ、IT専門家の立場でそれらの企画の実現性を検証していきます。「システムとしてこれは正しい、できるできない」ではなく、「よりよいサービスを作り上げるには?」という視点を持って議論に参加していく中で、顧客チームとの信頼関係を作っていきました(XPについてこのロールから書いたコラムが後掲されていますので参照してください)。

開発チーム召集

擬似顧客は開発の始まる前からそうしたスタンスで顧客チームに合流していました。3ヶ月が経って、顧客チームでビジネスプランニングが進められ、開発チームが召集されました(表1 全体スケジュール表と表2 メンバー表を参照してください)。

召集されたメンバーは、開発経験2年の若手から10年超のベテランまで、専門もそれぞれに異なりました。チームはこの後もリリース計画に伴い増減し、メンバーの入れ替えが行われることになります。

当初予定ではまずビジネスの検証としてプロトタイプシステムを作成するということでした。そのための構築フェーズとして、わずか1ヶ月でのリリースが求められたのです。仕様としては、ビジネス向けに機能説明プレゼンテーションの資料、管理画面の画面構成図、それにユースケースがあるばかりでした。顧客のニーズをほぼ完璧に把握している水谷が、開発チームと密に連絡をとることでカバーしていく戦術を取ります。

そこで、開発チームはUMLautソフトウエアフレームワーク(注2)を利用することで工期の短縮を図ると共に、ビジネスロジックについては過剰な分析を行わずにスタートすることを決定しました。このフェーズで作りこんだソフトウエア資産については破棄もやむなし、という合意が取れていたためであり、この時点からXPの全面的な適用を意図してのことではありませんでした。

しかし、プロトタイプによる検証の結果、予想以上にビジネスニーズに適合したシステムが作られつつあることが判明。Umlautフレームワークを利用しているため、プロトタイピングとはいうものの確立されたアーキテクチャの上に一定レベルの品質を保ったコードが生産されてきていました。すべてを破棄するのではなくリファクタリングを行いつつ機能追加に耐えるものであるという判断によって、チームはXPへの道を歩みだすことになったのです。

表1 全体スケジュール

表2 メンバー表

eXtremeで行こう!−First eXtreme Iteration

導入も「テストファースト」で

この時点で、XPに対するチームの中での認知度はあまり高いものではありませんでした。開発チームでは、山本と篠原が、XPについての書籍やネット上の文献などを調べていたり、早川がJUnit(注3)を使ってみたりはしていたものの、水谷を含めた残りのメンバーは、「XP? 聞いたことあるけど......ペアでコード書くっていうあれでしょ? どんなメリットがあるの? 開発スピードが遅くなるだけじゃないの?」と、やや懐疑的な雰囲気だったのです。XPをそれなりに知っていたメンバーにしたところで、実効性について確信があったわけではありません。

ただ、テスティングとリファクタリングについては、このプロジェクト以前に社内で評価を行った結果、間違いなく有用であるとわかっていました。実プロジェクトに適用した場合、テストケースを書く時間が開発速度に悪影響を与えるんじゃないか、という危惧があったのは確かです。しかし、これ以降の開発では、ビジネスの要請によって試行錯誤的に機能追加を進めていくことになり、随時リグレッションテストを行う必要があることがわかっています。そのためには、いずれにしてもテストの自動化は必須でした。

また、一般的なプロトタイプのコードよりは品質的にマシとはいうものの、製品品質のコードであるとまでは云えません。機能単位で分業を行った結果、重複コードは各人が作ってしまっているし、綿密なモデリングによったクラス抽出ではなかったために、責務の偏りなどが随所に見られるものでした。全面的な書き直しを必要とするものではないが、手を入れないで走りつづけるわけにもいきません。リファクタリングも必須というべき状況でした。

そこで、顧客と水谷が次期リリース計画のベースとなるユースケースを作っている期間を利用して、開発チームではまずテストケースを実装することからはじめました。いわゆるテストファーストでは、テストを書くことでクラスの外部仕様を明らかにし、それから実コードを書くことになります。テストが仕様書がわりになるわけですが、それからすると、リバースエンジニアリングしたようなものです。

この時点ではまだXPのフルスペックを適用するつもりはありませんでしたが、JUnitを使用したことがあるメンバーも少なかったため、ペアでテストケースを実装することにしました。この時期は、実装はまるで行わずに、リファクタリングの帽子(注4)をかぶりつづけることになります。 山本と早川でペアを組み、早川がドライバーとなってこのプロジェクトのためにはじめて書いたテストケースがリスト1です。

リスト1

package net.lex.entity;
import java.io.*;
import junit.framework.*;

public class PatternFilenameFilterTestCase extends TestCase{
private PatternFilenameFilter filter;
public PatternFilenameFilterTestCase(String name){
super(name);
filter = new PatternFilenameFilter();
}
public void testAccept(){
filter.setPattern("ax");
assertTrue(filter.accept(
new File("lib"),"jaxp.jar"));
filter.setPattern("zzz");
assertEquals(false, filter.accept(
new File("lib"),"jaxp.jar"));
}
} 

これはjava.io.FilenameFilterインターフェースを実装するクラス、PatternFilenameFilterクラスに対するテストケースです。配信するメールやWebページを生成するために、テンプレートファイルをiMode用/JSky用/ezWeb用、と区分けして用意しており、それらのテンプレートファイルをリストアップするのに使われるものです。

/var/template/t1_ic.txt    .........   iMode カラー用 
t1_ib.txt   .........   iMode 白黒用 
t1_jb.txt   .........   JSky カラー用 
t1_jb.txt   .........   JSky 白黒用 
t1_eb.txt   .........   ezWeb カラー用 
t1_eb.txt   .........   ezWeb 白黒用 

といった構成でテンプレートファイルが用意されているとき、

リスト2

// テンプレートファイルのディレクトリ
File templateDir = new File("/var");

// テンプレート番号 1番のファイルは
// ファイル名に "t1_" を含む
PatternFilenameFilter templateFilter =
 new PatternFilenameFilter();
templateFilter.setPattern("t1_");

// テンプレートファイルのリストを取得
File[] templateFiles =
 templateDir.listFiles(templateFilter);

// テンプレートから実際の配信ファイルを生成
for(int i = 0; i < templateFiles.length; i++) {
  createDeliveryFile(templateFiles[0]);
}

のように利用します。

PatternFilenameFilterクラスはaccept(File,String)メソッドを実装します。accept(File,String)メソッドは、第二引数で与えられたファイル名にsetPattern(String)メソッドで設定された文字列を含めば、第一引数の親ディレクトリがなんであれtrueを返すという仕様になっています(リスト2)。

リスト3

package net.lex.entity;
import java.io.*;
class PatternFilenameFilter
implements FilenameFilter {
private String pattern;
public boolean accept(
   File dir, String filename) {
return (filename.indexOf(this.pattern) >= 0);
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
}

このテストケースは、その仕様をテストして、本体コードにもバグがなかったので問題なく通ります。

図1 成功したテストケース

図1 成功したテストケース

しかし、これで充分というわけではありません。このテストケースの場合、PatternFilenameFilterの仕様を充分に満たしているとは言えません。

早川:「通りましたね。これで完成としていいですか?」

山本:「いや、それじゃまだまだ足りないね。いま書いたのは明示的な仕様で、それはちゃんとテストできてると思うよ。でも実は暗黙的な仕様ってものがあるんだ」

早川:「暗黙的な仕様ですか?」

山本:「そう。たとえば、ファイル名の大文字小文字を区別するのかどうかについてはテストしてないよね。他にも、引数にnullが与えられたときの動作だとか、setPattern()されていない状態での動作についてはどうだろう」

早川:「あぁ......テストしてないです」

山本:「今回はそもそもメソッドごとに仕様書があるわけじゃないけど、大文字小文字の区別なんかは、ちゃんと仕様として定義しておかなくちゃいけないよね。他にも、文字列の比較をするなら、trim()してから比較するかどうかなんかも必ず出てくる話だよ」

早川:「言われてみればそうですよね」

山本:「これまでは使い捨てにするかもしれないソースコードだし、外にライブラリとして提供するわけでもないから、曖昧にしておいても支障はなかっただけなんだよ。せっかくいま仕様書としてテストを書いてるんだから、そこもちゃんとテストしておこう」

文字列比較をするときの注意点や、nullチェックは当然どこかでしなくてはならないなどのことは、経験があればわかるでしょう。しかし、たいていの仕様書が不足しているプロジェクトでは、こういった「そこそこの経験者なら経験的にわかっているだろうと思われること」が不明確なままです。しかも「わかっているだろうと思われること」は、経験者同士でも人それぞれです。そのため、nullチェックであれば呼び出し側とメソッド側の両方でチェックしてしまう冗長なコードや、どちらでもチェックしないで実行時エラーになってしまう脆弱なソフトウエアを産んでしまいます。ペアプロでテストケースを書く場合であっても、双方が初心者であると、こうした危険は避けられません。

ここでは、patternとファイル名において大文字小文字は区別して扱うこと、setPattern()されていない状態でのaccept()呼び出しはNullPointerExceptionをthrowすること、他のメソッドにおいても引数のnullチェックは呼び出し元の責務であること、という現在の仕様を明らかにするよう、テストケースを改良してみましょう。

リスト4

public void testAccept()
    throws Exception {              //(1)
  // setPattern()されていない時にaccept()を
  // 呼び出すとNullPointerException。
  try {                         //(2)
    filter.accept(
      new File("lib"),"jaxp.jar");
    fail();
  } catch(NullPointerException ex) {
  }
  filter.setPattern("ax");
  assertTrue(filter.accept(
     new File("lib"),"jaxp.jar"));
  // 大文字小文字は区別する。
  assertEquals(false, filter.accept(
     new File("lib"),"JAXP.jar"));      //(3)
  // accept()を呼び出す際、引数がnullであれば
  // NullPointerException。
  try {                        //(4)
    filter.accept(null,"jaxp.jar")};
    fail();
  } catch(NullPointerException ex) {
  }
  try {                        //(5)
    filter.accept(new File("lib"),null)}; 
    fail();
  } catch(NullPointerException ex) {
  }
  filter.setPattern(null);
  try {                        //(6)
  filter.accept(
    new File("lib"),"jaxp.jar")}; 
    fail();
  } catch(NullPointerException ex) {
  }
  filter.setPattern("zzz");
  assertEquals(false, filter.accept(
    new File("lib"),"jaxp.jar"));
  }

testAccept()はリスト3のようになりました。まずシグネチャが変わっており、throws Exception が宣言されています。これはテストケースを書くときのコツで、投げられるべき例外についてはテストケース内でcatchしテスト成功とすること、投げられるべき例外が投げられなかったときは明示的に失敗(fail())することをルールにします。投げられるべきでない例外が投げられたときは、テストの中でcatchしなければ、自動的にJUnitフレームワークがcatchしてそのテストが失敗であったことを明確にしてくれます。

そのようにして追加されたテストが(2)、(4) 、(5) 、(6)です。例外を投げるべきメソッド呼び出しをtry~catchで囲み、catchでは投げられるべき例外だけを明示的に指定します。例外がcatchされなかった場合はテストは失敗です(fail())。

また、(3)では大文字小文字を区別することを確認するテストを追加しています。テストケースには、できるだけテストの意図を明らかにするコメントを書くようにしました。わたしたちのプロジェクトでは、この時期以降、クラス本体にはほとんどコメントを書くことをしませんでした。その代わりにこのようなテストケースを書くことで、クラスのテストケースを見れば、サンプルコードとともにメソッドの外部仕様が明らかになるようにしてあります。テストケースをドキュメントとして使っているのです。

一般的なドキュメントはもちろん、JavaDocのコメントとしてソースファイルと同じところに管理したとしてさえ、工程が進んでいくにつれてソースコードの実態とドキュメントはかけ離れていくのが普通です。それを防ぐためには、まず不一致の個所を確実に補足するという膨大な作業が必要になります。

しかしテストケースであれば、実態と乖離したときはテストが失敗するというかたちで検出することが可能です。テストケース内のコードとコメントの乖離や、検査されるべき要件がテストされていない場合など、この手法でもすべてが解決するわけではありませんが、詳細ドキュメントのメンテナンスに頭を痛めている方は、このようなメリットにも目を向けてみてはいかがでしょうか(注5)。

ペアプロの日々

プロトタイピングは、前述のとおり機能単位で担当分けを行いました。その「機能単位」というのも、必ずしもきちんとしたモジュール分割によるものではなく、要件を顧客の目でグルーピングしたものだったので、個々のモジュールが複雑に依存しあっていたり、重複コードが発生したりしていました。また、担当者は自分の担当個所しか知らずに進めており、他の担当者の作業についてはブラックボックスになっていました。秩序立ったモジュール分割に基づいているならば、そのような状況は必ずしも悪いものではありませんが、この場合にそのまま進めるのは混乱を深めるばかりだったでしょう。

XP的に言うとトラックナンバー(注6)がほとんど1だったこともネックでした。全員がすべてを熟知する必要があるとは思えませんが、誰かが怪我でもしたときのためにも、他の誰かひとりはホットスタンバイしていてほしかったのです。

このあたりで、「XPで行こう!」という雰囲気が、チームの中で明確になってきました。まず顧客のニーズとして、要件の変更や急なリリースにも対応して欲しい、ということがありました。それ以上に、ペアプロが刺激的であったことがメンバーのやる気を引き出したようです。しかし、メンバーの全員がXPを全面的に肯定していたわけではありません。

「あれ? Ctrlキーが効かないよ?」

「あ、すみません。CapsとCtrl入れ替えてるんです」

こんなつまらないようなことでも、開発者には結構なストレスになります。エディタやキーボードはチーム内で揃えるに越したことはないようですが、そんなことまでチームで縛ること自体、不満が出ないといえば嘘になるでしょう。ペアプロだとスピードが落ちるとか、プログラムを書くところを人に見られているのは恥ずかしいといった意見もありましたが、複数の視点を持ち議論しながら進められるペアプロが、実用的で楽しい一面があることは誰もが認めていました。

「このクラス重くなりすぎてると思いません?」

「だいぶ大きくなったから、少し見通しが悪くなってきてますね。でもクラスの責務ははっきりしているから、変にクラスを分割するとよけいわかりにくくならないかな」

「JavaMail(注7)を直接使ってるメール送受信のコードが結構入ってきてますよね。それってJavaMailのラッパーとして切り出して、別クラスにしとくと嬉しいと思うんですけど」
「なるほど、そこでJavaMailへの依存を切りやすくもなる、と。うーん、それは確かに悪くないと思うけど、このアプリの中ではメール送受信はすでにこのパッケージに集約されてますしね。メールがらみのAPIを切り出すとすると、パッケージ全体に影響のある大きいリファクタリングになって、少し過剰な気がするんですよね」

そんな話をしながら、コードを書き、手近な紙にクラス図やシーケンス図を書きます。あとに残すようなドキュメントではなく、議論の助けになればよいので、ごく簡単なラフスケッチです。

XPでは、「分析・設計・実装・試験」のアクティビティが並行して行われます(図2-1~図2-3参照)。クラス設計にあたる作業がテストケースの設計であるといえるでしょう。もっと上のレイヤの設計や分析は、シンプルデザインとリファクタリングが担っています。さらにテストケースはドキュメントとしても利用できますし、プログラムの変更にしたがってちゃんとメンテナンスされていきます。それらはすべてペアプログラミングの中で実施されていくのです。

XPで一番有名なプラクティスであるペアプロは、そのようにXPを実践していく上でも中心となるプラクティスです。しかし、ペアの組み方など、なかなか簡単ではありません。

図2-1 ウォーターフォール型の開発ライフスタイル

図2-2 従来型スパイラルの開発ライフスタイル

図2-3 XPの開発ライフスタイル

わたしたちは、毎朝のスタンドアップミーティングでその日の午前中から作業を進めるペアを決定しました。プライオリティの高いストーリーにサインアップしているメンバーから優先的に、ペアになって欲しい相手を指定する、というのが基本スタイルです。ただ、そればかりだと上手くいかずに偏ってしまったりもしますので、適宜コーチが「篠原さんの今のタスクは、土屋さんと組むと上手くいくと思うけどどう?」とか、「西田さん、ずっとマスターメンテ関係ばっかりですよね。ちょっとメール送信機能のところなんか覗いておきたくありません?」などと誘導したりもします。 ペアの交代は、出来るだけ一日の間に一回はするようにしていました(朝ペアを組んで、午後一回交代、翌朝また別のペアに......)。交代するのに切りの良いタイミングは各ストーリーで違いますので、それもまたコーチが調整します。

問題に引っかかって、ペアが揃って煮詰まってしまっているときなどは、新しい人の眼から見るとすぐ解決したりします。コーチが直接アドバイスすることもありますが、その機会にペアを交代させてみたりもします。ただその場合、他の人と「交代させられた」人が「自分が抜けたとたんに解決した」とは思わないように、気を使う必要があります。

ペアの個性というのも出るようになっていました。ある人とペアでやっていると考え込みすぎて煮詰まってしまう人が、他の人と組むと考慮が浅いうちに走ってしまっていたりしました。そうといって、組む相手がそういうタイプだからそっちに引っ張られるというばかりでもないようで、このあたりはなかなか定量的には量れないようです。

昔から新人研修などのOJTをペアプロ的にやることは行われていたと思いますが、わたしたちのチームでも、途中、翌年度入社予定(そういえばもう再来週くらいに入社してくるんですね)のインターンを迎えて、ペアプロに参加してもらったこともありました。もともとコードは書けたので、品質のことやプロセスのこと、顧客のニーズのことなど、ペアプロの間にいろいろなことを吸収して帰ってもらいました。たくさん宿題も与えてあるので、彼がやってくるのが楽しみです。

楽しくなくちゃXPじゃない−Second eXtreme Iteration

顧客のストーリー

そうこうするうちに、ビジネス側から次リリースに向けた要件が、ユースケースと画面仕様という形であがってきました。本来のXPであればストーリーカードを書いてもらうところでしたが、水谷と顧客のあいだでは、画面仕様をベースにユースケースの説明をする、という形で進めていたため、顧客チームにとってはいまさらストーリーカードに落とす必要がなかったためです。

開発チームは、出揃ったユースケースを前に、さてこいつをどうやって料理してやろうか、とわくわくしていました。まずはボリュームを量ってスケジュールを立て、ストーリーの割り振りをする必要があります。ユースケース一覧を元にExcelなどで管理をすることも可能でした。しかし、メンバーの全員が作業のボリュームを直感的に理解し、進捗を常に把握していくためには、アナログな紙ベースの管理に勝るものはありません。また、ユースケースの粒度は、視点としては揃っていたものの実装工数としては大小取り混ぜられたものでした。

また、カットオーバーの期日だけが決まっており、そこから逆算し、工程を均してできあがったようなスケジュールに何の信憑性もないことはわかっています。開発者たちは(不本意ながら!)そうした経験をたくさん積んできています。今回についていえば、コンサルタントによって実現性は検証され、ボリュームも直感的にいって現実的な範囲に絞られてはいたのですが、担当者がサインアップして見積もることで、スケジュールを押し付けられたものでないと感じることが大事だと考えました。

そこでわたしたちはユースケース一覧を前に、ストーリーカードを起こしていきました。ユースケースを分割したり、あるいは関連する小さいユースケースを取り混ぜたりして、ボリュームをそろえていきます。XPでは、「上司からの内線電話も鳴らず、総務や経理からの割り込みもなく、自分が一番仕事のしやすい環境で、ぶっ通しに集中してそのタスクに取り組める一日」を理想エンジニアリング日(注8)と呼んでいます。1ストーリーのボリュームとして、おおよそ3理想日程度に揃えていきます。だいたい1理想日のボリュームは、実際には3人日程度かかるものと考えられています。この辺はトラッキングして調整したりします。

基本的にストーリーカードを書くのは、そのストーリーにサインアップしようと思っているメンバーで、コーチはそれに助言を与えていきます。サインアップしたメンバーは、そのストーリーについて顧客の考えを充分に理解した仕様ホルダーになり、また全体の進捗の中で確実にそのストーリーを完了させることが求められます。仕様ホルダーとは、開発側のメンバーで、ある範囲の仕様について確実に把握している人、のことを指しています。ユーザから導き出される機能要件・非機能要件について、ユーザと同等以上に理解していなくてはなりません。他の開発メンバーが担当個所について疑問に思った場合や、プロマネが要求変更を把握したい場合などは、仕様ホルダーに対して問合せることになります。

XPでやった場合は、あるストーリーについてのプライマリの仕様ホルダーはサインアップした1名になります。仕様ホルダーとペアを組んだ人のそれぞれが、バックアップ系としてホールドしていくことになり、トラックナンバーが1にはならないようにします。

メンバーがストーリーを選ぶ基準はそれぞれでした。「自分がそれまでかかわっていなかった分野をやってみたい」あるいは逆に「熟知している部分だから自分がやるのが一番間違いないだろう」とか、「顧客にとってこの機能は重要そうだ」、「ここは技術的に面白いチャレンジができそうだ」など、思い思いの観点でストーリーを選んでいきます。ただ、わたしたちのチームは協調性がありすぎたのか、ストーリーの取り合いになるより譲り合いになることが多かったようです。「自分で仕事が選べる」ことに慣れていなかったためもあるでしょう。それでも、できる限り自発的にストーリーを選んでいくことが大事で、そうでなかったストーリーは、サインアップしたメンバーが仕様ホルダーになりきれなかったり、他のメンバーが持つストーリーのペアにかかりきりで進められなかったりもしました。

この作業は開発チームが行い、水谷はそれを隣で楽しそうに眺めながら自分の仕事をしています。なにか質問があればすぐ答えをもらえる状態で進めましたが、半日もかからずに全部のユースケースをストーリーカードにしました。この作業によって開発チームは顧客のニーズを汲むことができましたので、大変重要な工程だったと思います。水谷の表情が曇ったのはこのあとです。メンバーがストーリーを見積もってみると、彼の考えていた工数を大きく超えることがわかったからです。

ここでわたしたちは短い議論をしました。顧客のビューに立っている水谷にとり、実現できる機能が減ることが嬉しいわけはありません。しかも、彼自身の経験に照らしてこれならいけるだろうというまでに顧客と調整をしてきた結果なのですから、彼の見積りを否定されたようでもあり、顧客に合わせる顔がないとも感じたはずです。

しかし、開発チームとしては、これ以上ストーリーを詰め込んだ場合、充分な品質が保証できなくなるであろうと説明しました。スケジュールが厳しくなってくると、削減されるのはいつも品質向上の工数です。顧客としても月に500時間働いて書いたような品質のコードは無用ということで、イテレーションを短く取り結果をフィードバックすることで、今後の見積りの精度を上げていくことを条件に、当初よりは開発チームの見積りに近づいた線で同意ができました。

タスクカードを書いてみた。

ビジネス側の要件に沿ってストーリーがリストアップされましたので、次はサインアップ、タスクカード化に進みます。サインアップは前の工程で大体済んでいるようなものなので、各自が担当するストーリーを分割してタスクカードを作っていきます。

プライオリティの高いところから、開発チーム全体が集まってタスクカードにしました。初めてのことなので、どんなことをタスクにすればいいのかが今ひとつわからなかったためです。タスクは純粋にテクニカルなものと見なして、開発チームの作業量をはっきりさせるため、「ストーリーを完成させるために必要な作業」はすべてタスクに挙げることにしました。

そうすると、「自動ビルド環境を作る」とか「デザイナさんが作ったHTMLをチェックする」とか、特定のストーリーに紐付けにくいタスクがたくさん出てきます。わたしたちは、それらもどこかのストーリーに織り込みました。「自動ビルド環境を作る」のはプライオリティが高いので最初にやるストーリーに、「デザイナさんが作ったHTML」は後から届くので届く予定の時期に行っているはずのストーリーに、といった感じでした。これは少し失敗だった気がします。見積りが曖昧になってしまいますし、ストーリー間の依存関係が複雑になってしまいます。「技術的な準備を行う」といったストーリーを別途立てて、その中にタスクを入れていれば、開発のボリュームと付随する作業のボリュームを関連づけて計測できたかもしれません。

ビルドも自動化

わたしたちはCVS(注9)とant(注10)を併用し開発環境を構築していたので、それを利用してビルドも自動化していました。Linux上にCVSサーバを構築して、同じマシンのcronでCVSから最新版のチェックアウトとリビルドを行ったわけです。

開発者がソースをリポジトリにチェックインする際には、全テストケースを実行してエラーがないことを確認してから行う、というのが建前ではありました。しかし、データベースと連携して大量データのCRUDを試験したりJ2EE環境のテストがあったり、テストケースは日々充実してくるとともに重くもなってきます。このイテレーションの終わりごろには、全テストケースを実行するには小一時間かかるようになっていました。こうなってくると、ちょっと書いてちょっとテストしてすぐチェックイン、というリズムが失われてきます。

そこで開発チームは、手を入れた部分に影響を受けるはずのテストだけを実施すればよいことにしました。全体のテストケースの実行、テスト失敗時のエラーメール送信などをサーバマシンで定期的に行うことにしたのです。テストケースはCompositeパターンになっているので、たとえばパッケージ内のテストケースをまとめたテストスイートを作っていけば保守も容易になります。想定した範囲を超えて他のテストケースを失敗させるようであれば、それは依存関係が正しく保たれていないことを意味するわけですから、改修が必要な問題も検出できる......つもりでした。

実際には、テストケース自身のバグがあったり、テストケース同士に依存関係が生じてしまったり、それもコードレベルではなくテストデータを介した依存関係があったり、必ずしも原因追求は容易なこととばかりは限りませんでした。特に、テストデータを介した依存関係は非常に見つけにくいものでした。全体テストが失敗すると、ひどいときには一日以上も実装を止めて対処しなくてはならなかったこともあります。

これはテストケース自身がテストされることがない以上、簡単には解消できない問題と思われます。テストケースもペアプログラミングで書かれるものですし、既存のクラスを拡張する場合は、本体のコードよりもテストケースのコードによりよく目を通すものですから、コードの品質としてはそれなりのものになっていたはずです。

問題を一番難しくしていたのは、テストケース自身のモジュール分割がうまくいっていなかったことだと考えています。テストケースはその性格上、検査対象の値が多くハードコード(良くてもクラス定数として定義)されるものですので、保守はそれなりに難しくなるものです。複数のテストケースがテストデータを介して依存しあうのが問題だからテストデータを切り分けようといっても、実効のあるテストデータを毎回そんな大量に用意するのは大変ですので、できるものなら流用したいわけです。この問題について、わたしたちは決定的な解決策を見つけていません。読者の皆さんの中でよいアイディアをお持ちの方がいれば、ぜひわたしたちに連絡(注11)をください。

それでも全体テストとクリーンビルドの自動化には大きなメリットがありました。テスト時間が長くなりすぎてしまうという問題については、たとえば並列実行などの手段で回避できる場合もあるでしょう。わたしたちも次の機会には手法を改善して、皆さんにもまたお知らせできればいいと思っています。

リリースに向けて

全体スケジュール表をご覧になればおわかりいただけると思いますが、このプロジェクトでは、7ヶ月間の開発期間を大きく4回のイテレーションに分け、その中で通産10回のリリースを行いました。後述するシステムテスト工数も含め、他にも顧客のオペレータへ技術訓練を行ったり、データセンタへのインストールまで、そのたびに煩雑な作業が発生しました。定型的な作業であれば自動化してしまうところですが必ずしもそうでばかりはないですし、ここでトラブルがあれば、最悪の場合、施設に訪れていただいているエンドユーザの目に触れることになりますので、最後は結局人手になります。この作業が、当初の予想を超えてかなりな負荷になりました。段々に習熟してくるものとはいえ、物理的に削減できない時間もあります。スモールリリースを行う際には気をつけておきたいところです。

さて、年末に向けて最終リリースの開発が完了し、リリースパッケージを作成することになりました。顧客からは、次期開発があればまたわたしたちに頼むと仰っていただいており、先方としては技術ドキュメントは必要ない、とのことでした。最終版のユースケースとデータベース仕様書、各種マニュアルとインストーラだけを作ればよいわけです。これが最後のストーリーになります。

しかしXPといえども、回りつづけているプロジェクトであればこそドキュメント不要ということになりますが、何ヶ月かののちにテストケースやソースコードと走り書きのUMLの断片、ストーリーカードとタスクカードから記憶を掘り起こして追加開発を行うのは困難なことでしょう。そこで、内部向けドキュメントとして、ソースコードからリバースエンジニアリングしたクラス図、シーケンス図、パッケージ図などを作成しました。ドキュメント作成もメンテナンスの苦労さえなければ、それほどの工数はかかりません。

すべてがXPになる−eXtreme Project

できたこと、できなかったこと

今回わたしたちがXPをプロジェクトに適用してみて、XPのプラクティスとしてできたこととできなかったことがあります。(表3 12プラクティス実施結果 参照してください)

計画ゲーム、オンサイト顧客といった顧客が重要なアクターになるプラクティスについては、擬似顧客というロールを導入することで、ほとんど確実に行えました。ビジネス上のキーパーソンである顧客の担当者が、開発チームにつきっきりになるというのは、今の日本のビジネス慣習上ちょっと受け入れられにくいものでしょうが、今回の手法はそれに対する現実解であったものと思います。プロキシを置く以上ある程度のレスポンスの低下は発生しますし、擬似顧客自身が行ったり来たりで、100%オンサイトにはなりません。このあたりも二重化するなどの手段は取れそうです。

ただ、本来、ストーリーカードにはそれに対応した自動受入テストがセットであるべきです。今回わたしたちが実現できなかったプラクティスのうち、もっとも重要だったはずと感じているのがこの自動受入テストです。ユニットテストだけを自動化したところで、本当にリグレッションテストに通っているのか、リファクタリングした拍子に本来必要なクラスをテストごと失ってはいないか、という不安が残ったのです。自分が書いたコードが、本当に顧客の求めているものと一致しているのか、ストーリーが完了したと自信を持って云えるのはいつなのかわからなくなってしまったのです。

そのため「システムテスト」という独立した工程を準備する必要が生まれてしまい、イテレーションが進むにつれてその工数は膨らみました。「今日ここまでのところをリリースしてくれ」と云われてもそれは不可能になってしまったのです。これは実際に大きな損失でした。イテレーションの途中で、顧客が「突然だけど、来月イベントをやることになったんだ。それにあわせて、例の機能を盛り込んだバージョンをリリースしてくれないか? 他のの機能は後回しにしてもらっていいから、工数的にはそれで足りるはずだよね」といいました。これはXPの精神に照らしても顧客の正当な権利だったので、わたしたちは無理矢理システムテストの工程を割り込ませて、XPでなくとも許されないような残業もしましたが、そのリリースで予定していたいくつかのストーリーは後回しになってしまいました。後のイテレーションで取り返せたものもありますが、お蔵入りになってしまったアイディアもありました。リリース作業の工数のことも含めて、小規模リリースについては改善の余地があります。

それだけでなく、Kent Beckも最初のXPプロジェクトでシステムテストという工程を設けてしまい、それは大きな失敗だったと述べていますが、開発と試験を切り離すことは、開発者の中に「どうせバグがあったとしても後の試験で見つけてくれるさ」という気分を生んでしまいます。実際に落ちる品質ももちろんですが、本当の問題は別にあります。「いつでも顧客のビジネスに一致したものを最高品質で作り続けているんだ」という想いが開発者に誇りをもたらし、高いモチベーションを持って働きつづけることを可能にします。「どうせ使われるかどうかわからない機能だし」とか、「どうせ......」とつぶやきながらの仕事は、誰にとってもいいことがありません。こうした状況は早く打開すべきだったのです。

今回は、わたしたちの顧客自身はテストを書くことができませんし、それを代行できたはずの水谷はすでにオーバーワークでしたので、このうえ自動テストのスクリプトコードを書く余力はありませんでした。しかし、それで仮に開発工数が削られることになったとしても、わたしたちは開発チームから顧客をサポートして自動受入テストを書くメンバーを割く必要があったのです。

また、それに関連した失敗のひとつは、要求を管理するものとして、ユースケースとストーリーカードの二重管理になってしまったことです。本来であればストーリーカード自体を顧客がメンテナンスする(XP的には古いカードは破り捨て、新しいカードを書く)に越したことはなかったのですが、そうはいきませんでした。水谷がフルタイムで開発者と共にいられたわけではなく、むしろ本当の顧客のそばにいる時間を長く取る必要があったため、水谷はユースケースを持ち運んでいました。そのユースケースとストーリーカードの同期に漏れが生じたり時間がかかったりしたことがありました。

ストーリーカードやタスクカード、グラフといったアナログな紙ベースのツールというのは、メンバーが状況やボリューム、内容を把握するにはとてもいいツールでした。きれいなExcelの表を作る必要などまったく感じることはありませんでしたが、如何せんアナログの方が手間がかかる場面というのはあります。

大量のカードを、簡単にコピーしておき複数の版からdiffを取ってマージする、というのはなかなか困難でしょう。ネットワーク越しにやりとりするわけにもいきません。こうなってくると、やはり本物のオンサイト顧客を持つ体制のほうが、少なくとも便利ではあるなぁと思わざるを得ません。

だからといって本当のオンサイト顧客でやるしか手がないというのも残念な話です。この問題についてもさらに改善の手立てを探していこうと思います。いい手段を思いついた方はぜひわたしたちにも教えてください。

リファクタリングとシンプルデザインについては微妙なところです。過剰な設計を前もって行うことはしない、というYAGNI(You're NOT gonna need it)を心がけてはいましたが、結果としては重複コードを充分に排除しきれてはおらず、リファクタリングが不足した感があります。また、時折コード全体に影響のあるような大規模なリファクタリングが必要になることもありました。そうなると全体テストや継続的インテグレーションに失敗する状況が続いてしまいます。このあたりは、「必要充分な設計」を前もっては掴みきれないことによるものでしょう。わたしたちはフレームワークを持っていたことで、検討されたアーキテクチャ設計を流用できましたから、だいぶ助けられたと思います。しかし、わたしたちのプロジェクトからフレームワークへのフィードバックは簡単ではありません。フレームワークやコンポーネントといった流れとXPをどう連携させるか。これについては今後も実践の中で答えを探していかなくてはならなさそうです。

共同所有権については、CVSを利用することで実現できました。CVSについては、ソースファイルを編集する際に、リポジトリ内のファイルを排他制御しません。誰かが編集中のソースを他のユーザも編集できるので、編集したいファイルがぶつかってもボトルネックにはなりません。その代わり、ソースファイルをチェックインしようとすると、他のユーザの編集内容とコンフリクトすることがあります。機械的にマージしてすむというものでもないので、ともするとここで時間を取られることがあります。これはツールの使いこなしでずいぶん解消できることでしょう。

コーディング標準は、あまり強い縛りはもうけませんでした。Sunの提供するコーディング規約(注12)をそのまま利用しただけで、一番読みなれたソースコードであるJDKのソースコードに準拠する、というのが唯一の方針でした。それで一般的な規約としては充分でしたが、メソッドやクラスの命名について悩むことが多かったので、そのあたりにも少し指針を用意しても良かったように思います。事前の分析・設計工程を持たないため、そこで名前を検討するのが設計の代わりになったとも考えられるのですが。

比喩(メタファ)は、開発チーム主導ではほとんど使っていませんでした。顧客チームがビジネスを検討する際に、多くの比喩を出してくれていたのでそれに乗って議論・開発しました。もしそうでなかったなら開発チーム内で比喩を作ることは大事だったろうと思います。UMLやデザインパターンもそうですが、XPに限らず、コミュニケーションを円滑にするための道具を活用しなくては上手くいきません。

最後に、週40時間についてですが、ほとんど実現できませんでした(読者の皆さんの溜め息が聞こえてくるようです......)。全体をならすと週45時間~55時間といったところでしょうか。よく言われることですが、ペアプロはとても疲れますので、この稼動時間はちょっと辛いものでした。それでも「週40時間」という目標を置き、速度を測定しながらやったことで、ハードな時期には品質や効率が下がる、ということをまざまざと感じることができました。感覚的に云うと、普段8時間で100の分量、100の品質のものを作っているとしたら、12時間にしたときには75の品質で140の分量のものを作っている感じです。個人差もあるでしょうが、1.5倍の時間で1.5倍の量は作れませんし、品質×分量が単純な掛け算だとすると、わずか5%くらいの生産量向上になります。残業好きの管理者の方にはぜひこのあたりを理解してもらいたいと思います。

12のプラクティスより4つの価値

XPに興味を持つ人たちは、これらのプラクティスがXPの本質ではないことを理解する必要があると思います。ペアプロだとか週40時間のように、XPに興味を引くキーワードを散りばめているのは、XPの産みの親たちの上手い戦略です。わたしたちもまんまと乗せられましたが、戦略に乗せられてXPに眼を向けた後は、XPの本質である4つの価値に主眼を置くべきです。

XPでいう4つの価値とは「シンプルさ、フィードバック、コミュニケーション、勇気」を指します。

airplane rule(注13)を持ち出すまでもなく、シンプルであることは美しく堅牢という価値を持ちます。技術者にとっての美意識の問題のようですが、顧客にとっても、「支払った分だけ必要なものだけが手に入る」というシンプルさは、これまでのソフトウエア開発ではほとんど不可能だった価値です。それをどのように実現していくかを、顧客と開発者が共に考えることが大切なのでしょう。

日々新しいことに臨みつづけるソフトウエア開発の現場では、教科書どおりに行くことなどひとつとしてありません。顧客と自分たち自身、ソフトウエアそのものから、フィードバックを受けつづけていかねばなりません。XPも含め、各種の開発方法論は、その踏み台くらいのつもりでいたほうがよいでしょう。見積り精度向上のためのトラッキングも大事ですが、そればかりでなく、自分たちの新しいプラクティスを生み出す工夫・改善活動のために、実践からのフィードバックを受けつづけたいものです。

「変化ヲ抱擁セヨ(Embrace Change)」というのは素敵なコピーでした。変化は恐怖感を伴うために必ず抵抗を受けるものです。「ヨクないこともあるけど、いままでなんとかやってこられたじゃないか。ここでそんなことして、上手くいかなかったらどうするんだ?」そういって現状維持を求める人に、恐怖に打ち克つ勇気を与えてあげられるのがXPです。根拠のない勇気は蛮勇ですが、XPの掲げる勇気は、テスティングを始めとするプラクティスで武装されているのです。「テスティングで上手くいくこともあるのはわかったよ。でも、こんな危険だってあるじゃないか、それはどうするんだ」。そんな抵抗を受けることがあるでしょう。そのときは、あなたがXPに新しいプラクティスを付け加えるチャンスです。

そして、ソフトウエア開発は、開発者と顧客とで作り上げるチームが、それまでになかった解決策を創造する人間のプロセスです。工場の稼働率や生産効率を語るのと同じ文脈では語ることができません。プロジェクトチームを機能させるのは、メンバー同士の有機的な繋がりで、それはシナプスのように刺激を受けて成長します。堅苦しい会議やキレイに作った進捗管理表は、コミュニケーションの道具ではありません。それが必要なこともあるでしょうが、有機的なチームを成長させる役には立ちません。それよりも、タスクカードやストーリーカードを前に、キーボードを叩きながら、喫煙所でばったり出会ったときに、要するにほとんどいつでもチャットします。それが大事な刺激になります。リリースが無事に済んだときには、みんなでなにかおいしいものを食べて騒ぎましょう。そうすればきっと、明日からもっとうまく楽しくプログラミングできるようになります。

それでは、Happy eXtreme Programming!

表3 12プラクティス実施結果

プラクティス名 実践度合い
(5段階評価)
うまくいった点 反省点
計画ゲーム
The Planning Game
☆☆☆☆ 擬似顧客が顧客のプライオリティを把握して計画を立てることが出来た。 変更履歴を把握できていなかった。
(今回は問題なかったが、今後は把握していく必要があるだろう)
小規模リリース
Small Releases
☆☆☆ 顧客の要望するタイミング・機能で、10回に渡るリリース作業を行うことができた。 受入テストの不足やリリース作業工数の甘い見積りにより、開発工数への影響があった。
比喩 Metaphor ☆☆☆ 顧客チームの作ったメタファで統一して実施できた。
メタファの統一によってコミュニケーションが円滑になる効果はあった。
開発チーム主導でメタファを使うことが可能なのか、有効なのか。まだ未経験。
シンプルデザイン
Simple Design
☆☆☆☆ 過剰な設計は一切行わなかった。フレームワークに沿った設計であったため、モジュール分割は必要充分な範囲で適切に行っていた。 重複コードが残り、メソッド単位での冗長さなどが一部に見られた。
テスティング
Testing
☆☆☆ ロジック部分のユニットテストは100%実施、それによって潜在バグを未然に検出できた。 顧客レベルの受入テストや、HTTPレベルのテストについて不十分だった。
リファクタリング
Refactoring
☆☆ メソッドの引き上げやクラスの抽出など、スムースに実施できた。 工数が厳しい時期は積極的に行えず、結果として大規模なリファクタリングの必要性が高くなってしまった。
ペアプログラミング
Pair Programming
☆☆☆☆☆ コミュニケーション、教育、レビューといった多くの意味で効果をあげることができた。 キーボードとエディタの統一について、結論が先送りになっている。
共同所有権
Collective Ownership
☆☆☆☆☆ 版数管理ツールを利用し、ペアプログラミングを実施することで、コードの所有権を意識する場面は全くなかった。 CVSをはじめとして、ツールを使いこなしていけばさらに効率が上げられる。
継続的インテグレーション
Continuous Integration
☆☆☆ 日々の結合ビルドを行うことで、開発チームでは、全体へ責任感を持って目を配るようになった。 受入テストを自動化できていれば、開発チームはさらに安心感・自信を持てる。
週40時間
40-Hour Week
「週40時間じゃないと効率下がるね」という実感が得られた。 煮詰まったとき、難問にはまったときは、気分を切り替えて早く帰宅するのもいい手だった。
オンサイト顧客
On-Site Customer
☆☆☆ 顧客のビジネス面での責任者とよい関係が築けた。顧客の基準で判断できる擬似顧客となった。 擬似顧客として行き来しているためのレスポンスタイムの低下。自動受入テストを書かなくてはならない。
コーディング標準
Coding Standards
☆☆☆☆ 必要充分な範囲の規約で、「他人のソースだから読みにくい」ようなことはなかった。規約を守ること自体が開発者のオーバーヘッドになることもなかった。 命名規約などはもう少し充実してもよいか。

コラム:擬似顧客の声

XPを実践していくうえで、「オンサイト顧客」は重要な役割を果たすにもかかわらず、XPの多くの文献には「オンサイト顧客」に関する記述があまり見られないのも現状です。本コラムでは、これからXPを実践したい、XPの「オンサイト顧客」に挑戦したいという読者に少しでも参考になるよう、筆者が実際に「オンサイト顧客」の擬似顧客を実践した体験をご紹介していきたいと思います。

「業務屋」と「技術屋」の不幸な行き違い

XPを実践していくためには、要求を把握している顧客が「オンサイト顧客」という役割でXPに参画することが非常に重要となります。しかしながら、顧客は自分自身のビジネスは詳しいがシステムは詳しくない「業務屋」であり、逆にプログラマはシステムやプログラムは詳しいが顧客のビジネスは詳しくない「システム屋」であることが多い。ここに「不幸な行き違い」が存在しているのです。

XPの「オンサイト顧客」は、要求仕様書を作成する替わりにストーリーカードを書きイテレーションを決めるという責務を担っています。ストーリーカードでは記述しきれない詳細な仕様は、その場でプログラマとディスカッションしながら指示していくのです。一見簡単そうに感じられるかもしれませんが、「業務屋」にはこれはかなり難題となってのしかかります。

そこで登場するのがこの「不幸な行き違い」のギャップを埋める「擬似顧客」という役割です。平たく言えば、擬似顧客は業務屋の視点を持ったシステム屋です。プログラマからは擬似顧客=顧客と認識され、顧客からはシステム屋ではなく同業のパートナーとして認識されます。

顧客との信頼関係がポイント

顧客が「業務屋」であるがゆえ、システム化の細かい部分は「いいのか悪いのかわからない」というのが本音です。「君がそう言うのなら、そうしてくれ」と言ってもらえれば良いですが、「そうかもしれないが、君の言うことは信用できない」という関係になると、これは大変つらい作業になってしまいます。

ではいったいどのようにしたら、顧客に信頼してもらえるのでしょうか?筆者はシステムコンセプトが重要な役割を果たすと感じています。顧客は「こんなことをしたい」というコンセプトはしっかり持っているものです。そのコンセプトの生まれた背景、必要性、方向性、真の意味などを理解し、システムに対する価値感を共有するところからまず始めました。書類上だけの理解だけでなく、システムが稼動するであろう現場(今回はお台場の商用複合施設メディアージュ)に何度も足を運び、そこでシステムが使われるであろう光景や、システムを利用して楽しんでいる施設利用者の表情、知人との会話の様子、施設店員の振舞いなどを想像しながら、「なるほど、この状況のときにシステムによって来場者を楽しませたいのだろう」とシステム化の背景に迫っていくのです。

「どのようにシステム化するか」(How)をつい考えてしまいがちですが、その前に「何をシステム化したいのか、それはなぜか」(What, Why)をしっかり顧客と共有しておくことが、顧客の信頼を得るポイントとなります。

経験上意外と有効だったのが、会議室でかしこまって打合せをするというのではなく、いわゆる「チャット」を顧客と多く行うことでした。会議室だとなかなか言いにくい考えなども、喫煙所や廊下などで雑談をしていると「そういえば、思いついたんですけどこんなことはできないですか」と気楽にシステム化への思いなどを打ち明けてくれたこともありました。

ストーリーカードとユースケース

擬似顧客は、顧客と共同で仕様を決めてストーリーカードを書くのが主な役割になります(顧客がストーリーカードを書くことはありません)。このストーリーカードというのが実はクセモノです。いきなりストーリーカードを書き始めるとシステムの全体像がつかめず冗長な機能を作ってしまったり、ユーザーインタフェースが統一されていないという事態が発生します。いわゆる「木を見て森を見ず」状態です。筆者らは、概念モデルやデータベースのER図でシステムの全体像を捕らえ、それを踏まえてユースケースでシステムの振舞いを定義しました。このユースケース1つ1つが、1つのストーリーとなってストーリーカードに記述されていきます。

顧客とユースケースを記述していく際のポイントは、システム用語を避けて顧客の言葉を使うことです。それでも文字ばかりのユースケースは直感的にわかりやすいとは言いがたく、多くの場合はユースケースの内容を顧客にわかりやすいように図やフローで説明することになりました。なぜこうなるのか、こうしたほうがベターなのかを顧客に十分説明し、顧客と合意の上で仕様を決めていきました。

しかしながら顧客にわかりやすいユースケースだけでは開発チームに意図が伝わらないケースも存在します。そこで、ユースケースの粒度を「ユーザ目的レベル」と「サブ機能レベル」に分け、顧客と会話する場合には「ユーザ目的レベル」のみを、システム内部のイベントフローをある程度決めてしまう場合は「サブ機能レベル」のユースケースと使い分けることにしました。この「レベル分け」は意外と有効ですのでお試しになられてはいかがでしょうか。

顧客と開発チームの狭間で

顧客:「水谷さん、このスタンプ蓄積機能はどうしても実現したいんですよ」 開発チーム:「水谷さん、残りの工数で開発するには無理があります。ほら、次のイテレーションまで残りは4デューク(理想エンジニアリング日)しかない。この機能は見積もったら2つのストーリーで6デュークもあるじゃないですか」 擬似顧客をやっていると何度もこういった「板挟み」を味わいました。擬似顧客であるがゆえに、「この機能は必要だ」という顧客の思いも、「こりゃ間に合わない」という開発チームの思いも痛いほどわかります。

「顧客の希望を最大限に活かしながら開発工数を最小限に抑えるような代替案を顧客に提示する」、ここが擬似顧客の腕の見せ所です。顧客が希望している機能にも、実現のレベル(深さ)というものがあり、松・竹・梅の3レベルの案を擬似顧客が考えて作成します。ここでもポイントは、顧客の立場から顧客にわかりやすい用語、言いまわし、表現方法できちんと顧客に説明することです。ズバっと機能を簡略化・削減する場合でも、きちんとした理由ときちんとした説明があると顧客も納得してくれます。(これが意外と難しく、実際できていないプロジェクトが多いようです)。

逆に、開発チームを説得するケースもあります。なぜこの「スタンプ蓄積機能」が必要なのかを開発チームにもしっかり把握してもらうのです。システム化の背後にある思想、将来の事業展開プラン、収益モデルなどプログラミングとは関係ない話も開発チームと共有し、「なるほど確かに実装しないといけないなぁ」と打開策を検討していきました。

このような「板挟み」に遭遇した場合は、顧客と開発チームの両方に対して何回かディスカッションしながら決めていくのがポイントです。顧客と代替案で一番可能性のあるものを詳細化し、開発チームとコミュニケーションしながら工数を見積もり、それを持ってさらに顧客と詳細を詰めていくというプロセスを数回繰り返しました。

顧客名言集

ここでは、顧客とディスカッションしていった上でいくつか印象に残っている名言を集めてみました。それぞれのポイントを踏まえて、読者のみなさんも擬似顧客に挑戦してください。

名言1「やってみなけりゃわからない」
今回のプロジェクトのように「既存システムのリプレースではなく新規にシステムを構築する」ケースでは、仕様を決めてみたところで「やってみなけりゃわからない」という本音が出てきます。顧客自身もそれがいいかどうか判断しきれないのです。この場合、理想的な仕様は決めておきますが全てを実装しない(作り過ぎない)というのがポイントです。実際システムを稼動させて使用していただいた段階でレビューを行い、システム使用者から生の声を聞いた上で再度イテレーションを行うことになります。
名言2「そこまでは考えてなかったなぁ」
顧客はシステム詳細までは考えないものです。セキュリティやロジックに矛盾があることもしばしばあります。ユースケースを使って主シナリオを決めた後、しっかり例外シナリオまでフォローしておくことがポイントです。リスクを先送りにしないというメリットもありますがそれ以上に「おお、そんなところまで考えていてくれたのか。我々の熱い議論を冷静に判断してくれるこの人に任せておけば大丈夫だ」という顧客の信頼を得ることができます。
名言3 「さすが、いいアイデアを考えましたね」
顧客はシステムを活用したアイデアは考えにくいようです。また、あれこれ考えすぎてしまっているケースも多いようです。打合せの場で顧客同士の会話にじっくり耳を傾け、すぐに割り込まずに適当なタイミングで要点をまとめて発言するのがポイントです。システム化と関係なさそうな打合せにも積極的に参加するのも効果的です。もともと要件にない機能でも、「そこはシステムで実現できるのでやってしまいましょう」とか「JavaScriddtを使うと簡単にできますよ」というちょっとしたアイデアが顧客への好印象を与えます。
名言4 「お任せしますよ」
顧客は本来の業務も行っていますので、システム化作業に付き合いきれない場合があります。ある程度仕様が決まった後にこの名言が出た場合は「信頼された証」と捕らえてかまいませんが、それでも「こう決めました」としっかり報告することがポイントです。また仕様が決まっていない段階でこの名言が出た場合は、顧客の作業負荷が少ないタイミングを見計らってしつこくヒアリングすることを忘れてはいけません。
  • 注1:13館のシネマコンプレックスを中心としたアーバン・エンタテインメント・センター。http://www.mediage.co.jp/
  • 注2:UMLautは筆者らの所属するウルシステムズ独自のビジネス構築フレームワーク。システム開発のみならず、ビジネス構想から本番稼動までを一貫したオブジェクト指向技術によりサポートします。構築フェーズではソフトウエアフレームワークが高い開発生産性と設計品質をもたらします。
  • 注3:UXPの父のひとりKent BeckとデザインパターンのErich Gamma が作ったテスティングフレームワーク。オープンソースライセンスを採用し、フリーで提供されている。http://www.junit.org/
  • 注4:リファクタリングを行う場合は、自分が今、なにか新しい実装をしているのか、リファクタリングを行っているのかを明確に意識する必要があります。比喩的にリファクタリングの帽子と実装の帽子をかぶりなおすと云います。
  • 注5:これで解決できるのはかなり詳細なクラス仕様書やメソッド仕様書レベルのドキュメントだけです。基本設計書などはこれまでどおりに管理する必要があります。それでも、ボリュームの少ない概要資料などに比べて、詳細資料は実態とかけ離れたものになりやすいものですから、ここだけでもメンテナンスの手間が軽減されるメリットはあると思います。まぁ、後付けのドキュメントを作っている場合はあまり気にする必要はないかもしれませんが。
  • 注6:トラックナンバーとは、プロジェクトメンバーの何人がトラックにはねられると、人員を追加したとしてもプロジェクトが崩壊するかを表す数字で、最悪は1になります。「簡単に取替えが効くような、組織の歯車にはなりたくない」なんてことは思うものですが、簡単に取替えが効かないならなおさら代わりは用意しておかないと、風邪ひとつ引けなくなってしまいます。やっぱり重要な個所ほど冗長構成にしておかなくてはいけませんね。
  • 注7:http://java.sun.com/j2ee/ja/javamail/index.html
  • 注8:各開発チームで、この単位には好きな名前をつけるといいと言います。XP本にはチームのみんなが好きなお菓子から「グミベア」と名付けたりした例が出ています。わたしたちは、Javaのキャラクターに敬意を表して「デューク」と呼びました。「お、今週は予定より2デュークも進んでるぞ!」 Duke: http://java.sun.com/features/1999/05/duke.html
  • 注9:フリーのバージョン管理システムとしてデファクトスタンダードとなっている。 http://www.cvshome.org/
  • 注10:Unix/C環境におけるmakeに似た、Java用ビルドツール。さまざまなプラグインが提供されており、JUnitなどのテスティングフレームワークもantから実行できる。 http://jakarta.apache.org/ant/
  • 注11:冒頭のアドレスまで直接メールをいただくか、XP-jpなど関連するメーリングリストに投稿をいただけると嬉しく思います。
  • 注12:http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html
  • 注13:複雑になればなるほど故障が増えることを飛行機に喩えた言葉。二つエンジンを持つ飛行機は、単発エンジンの飛行機の二倍エンジンに問題を抱えることになる。http://www.tuxedo.org/~esr/jargon/html/entry/airplane-rule.html
アーカイブス一覧へ