中規模開発でのエクストリーム・プログラミング

アジャイル開発のエクストリーム・プログラミング(XP)は好きなんですが、開発規模が大きくなった時に、どうやるんだろう、と最近考えていて、考えをメモします。

開発規模の定義として、僕は、100行=小規模、1万行=中規模、100万行=大規模と定義します。それぞれの規模でベストな手法が違います。大規模で、100人以上のメンバーがいる場合は、どうやってグループを管理するかという問題とかもあります。僕は、ほとんどが中規模開発なので、今回は、これ限定です。

エクストリーム・プログラミングを説明した最も有名な本は1999年に出た、XPエクストリーム・プログラミング入門―ソフトウェア開発の究極の手法 ですが、年々微妙に変化していて、最近の著者さんのスタンスを一番反映しているのは、http://www.extremeprogramming.org/ での説明かなと思います。

設計の終焉? でマーチン・ファウラーさんも指摘していますが、この手の手法がうまくいくかどうかは「変更コストは開発が進むにつれ増大しない」これにかかっています。古典的には、変更コストは増大する、とされているので、事前計画、つまり、設計や分析をしっかりやって、将来発生するかもしれない問題は事前にとっておこう、という発想です。それに対して、エクストリーム・プログラミングは「増大しないための工夫」を十分施こし、事前計画よりも柔軟性を重視した方が効率的である、という考えです。

問題は、「増大しないための工夫」というのが、XP本に書いてあるだけでは不完全で全てのレベルでやる必要があると思います。特に規模が、中規模以上になってくると、注意が必要です。

理論的には、規模をnとして、O(1)の変更を加えた時に、変更コストがO(1)でなければならない、というのがエクストリーム・プログラミングが成立するための前提条件です。しかし、これ、簡単に O(n) とかになりかねないです。開発にはたくさんの工程がありますが、その全ての工程でO(1)でなければいけません。一つでも、O(n) が入ると、全体が O(n) になります。ただし、nが小さい場合は、実際は O(n) であっても、それを0と見なすことで回避できちゃいます。しかし、n が大きくなるとそういう逃げは効かなくなります。

まず、わかりやすいテストから。エクストリーム・プログラミングでは自動テストを重視しています。しかも、1999年当時よりも今の方がますます自動化を重視しています。ユニットテストホワイトボックステスト)と受け入れテスト(ブラックボックステスト)にわけ、どちらも、自動テストすべしとなっています。例えば、受け入れテストで、90%が自動化されていて、10%が手動の場合、この工数は、O(0.1 * n) = O(n) となり、XPの前提条件が破綻します。10%の手動テストが量が凄く少なければ0と見なせます。しかし、多いと、O(n) です。

さらに、自動テストの待ち時間も O(n) です。ここも、理論的には O(1) でなければなりません。継続的インテグレーションのためのコンピュータを用意することが推奨されていて、そちらで自動テストをやろうということになっているのですが、例えば、自動テストが複数のコンピュータで分散できるとして、待ち時間を O(1) にするには、n × 開発者数分のコンピュータが必要で、そのためのコストは、O(n * 開発者数)であり、コンピュータの代金が無視できるくらい小さいなら問題ないですが、一人あたり1万台のコンピュータとなると破綻します。(まぁ、これは考え過ぎかな)

次に、設計。今やっている作業で、どこに影響が及ぶのだろうと、コード全体を見直したら、O(n) です。XP2002カンファレンス でも間接的に触れられていますが、モジュール間がちゃんと疎結合になっていて、自分がやっているモジュールだけ考えれば良いという状態になっていないと破綻します。

実装においても、メソッド名を変更した時に、それがプログラム全域で使用されていて、それを全文置換で変換したら O(n) です。XPの前提条件を成立させるには、統合開発環境によるリファクタリングが有効である必要があります。

また、ありがちなのが、データベースのカラム名の変更。これもやっかいです。カラム名がプログラム全域に散らばっているコードは多いと思います。統合開発環境によるリファクタリングが効けばいいですが、SQLなどはできたりできなかったりします。できない場合は、DAOとして、テーブル操作を一カ所にまとめられたら、そこをいじるだけなので O(1) ですが、JOIN やサブクエリーなど複数のテーブルをまたぐ操作があると、DAO群全域に散らばってしまうので、テーブル数が O(n) とすると、変更箇所が O(n) になります。

さらに、データベースから読んだのを JSON にして、XmlHttpRequestJavaScript に渡して、jQuery テンプレートで表示する、というフローはありがちですが、ここまで追っかけてリファクタリングしてくれる統合開発環境はないと思います。O(n) になりかねないです。

規模が大きくなるにつれ、無視できない O(n) がどんどん増えていきます。全ての工程が O(1) であることを要請するエクストリーム・プログラミングはかなり工夫と注意が必要です。

O(1) をあきらめた時にとれる方法の一つがウォーターフォールのように事前計画をしっかりやる方法ですが、計画通りに全てを遂行できるのは単純労働ですが、そういうのは過去に作ったことあるのと同じような物を作る場合なのですが、ソフトウェア業界の場合、そのようなケースでは過去のコードをいじるなり、コピー&ペーストするなりしてしまうので、業界の仕組み的に単純労働にならないため、完璧なる事前計画をねらうのも、破綻します。

完璧なる O(1) も完璧なる事前計画も難しいです。