XPプログラミングの考察 その1 - テスト自動化
ただし、 XUnit と呼ばれるテスティングフレームワークについてはいろいろ調べたことはあるのですが、 XP 自体については Wikipedia などのネットの拾い読み程度の知識しかないので、それを私なりに解釈したものです。
XP にとって大事なことは何かというと如何に変更に強く開発していけるかということです。
そのための重要なポイントは次の 2 つだと思います。
- テスト自動化
- ソースコード重視
テスト自動化
XP のテストといえばテストファーストといった感じですが、個人的にはテストが前か後かというのはたいした問題ではないと思います。 XP の最大のポイントはテスティングと呼ばれるテストの自動化にあります。
ただ、テストファーストも悪いとは思っていません。私も Redmine というバグトラッキングシステムを使っているとき、いっぱい上がっているバグのチケットをひとつづつ修正していくのが結構楽しいときもあるので、テストエラーを一つづつ潰して行くクリア的な楽しさは確かにあると思います。
しかし、やはり大事なのはテストの自動化で XP の多くのプラクティスはテストの自動化に支えられています。
リファクタリング
これはちゃんと動作しているコードでもだめなコードならどんどん修正していこうということです。これは一見あたりまえのようですが、テストの自動化ができていないと出来ません。
プログラマはこのコードひどいなと思っても、一応動いているのであれば普通、なるべく手を出しません。コード修正用の工数などまずもらえませんし、下手にいじって動かなくなっては困ります。そこで汚いものにはフタをすることにします。これは汚ければ汚いほどその傾向になります。
そこに勇気を与えてくれるのがテストの自動化です。
ただまぁ、次回説明するつもりですが、単体テストを入れている時点でそこまでおぞましいコードはできていないとは思います。
ソースコードの共同所有
誰が作ったソースコードでも、開発チーム全員が修正できるということです。これもテストの自動化がなければ、人のコードなど怖くて触れません。
継続的インテグレーション(CI)
ビルドとテストをサーバーなどで定期的に行うことです。これはテスト自動化に支えれられているというよりもテスティングにおける"頻繁にテストを行う"というところをシステム的に実現させるものです。
YAGNI(今必要なことだけ行う)
必要な機能だけを実装するということです。これは余計なものを作らないことで早く作っていこうという考え方ですが、テスト自動化をしていない場合、逆に時間がかかってしまうことがあります。
というのも、機能を一つ追加した場合、その機能のテストだけでなく、その機能追加の修正によって他の機能に影響がないかをチェックする回帰テストが必要になってくるためです。テストに時間がかかる場合は機能を一度に追加して通しでテストを行った方がトータルの工数が減るわけです。
テスト自動化をしていればテストもすぐ終わるので、今求められているものだけを作ることができるようになります。 これにより 短期リリースも実現可能です。
XP は変更に強くすることが重要であり、また、変更に強くなっているということを基にした開発手法でもあります。そのため、変更に強くなっていなければ、 XP は破綻します。これがよく分かるのが、この YAGNI でしょう。
ただし、今必要なことに最適化してコーディングするということではないことに注意してください。
必要のない機能は実装しませんが、将来起こるであろう修正に対して柔軟に対応できるようにしておくということは重要です。これは次のポイントである良質のコードを書くということでもあります。
XP の部分的導入というのはよく耳にします。 XP の完全導入はハードルが高すぎて私もできるなんて思ったことは一度もないので、それが当たり前だと思います。ただし、そこで真っ先に導入すべきはテストの自動化です。テスト自動化の導入は大変なので、抜きでやろうということがあるかもしれません。しかし、 XP のほとんどのプラクティスはテストの自動化なしには実行出来ませんし、無理にやったとしても破綻します。
確かにテストの自動化、ユニットテストのコードの記述は面倒です。市販のテスト自動化ツールなどもありますが、それでも軽減されるだけで手間は手間です。しかし、それを超えてこそ XP の恩恵がでてくるのではないかと思います。
![]() | UNIXプログラミングの道具箱―プロフェッショナルが明かす研ぎ澄まされたツール群の使いこなし (2004/06) 工藤 智行 商品詳細を見る |
![]() | Rubyを256倍使うための本 極道編 (2001/01) 助田 雅紀 商品詳細を見る |
![]() | eXtreme Programmingテスト技法―xUnitではじめる実践XPプログラミング (OOP foundations) (2001/11) 日本XPユーザグループ 商品詳細を見る |
![]() | CppUnitによるXP‐eXtreme Programming‐実践テスト技法 (2003/07) 大月 美佳 商品詳細を見る |
XPプログラミングの考察 その2 - コード重視
このソースコード重視が XP のテスト自動化に並ぶポイントであり、私がもっとも共感した部分です。
前回も私なりの解釈で書いたものだったのですが、今回はもっとひどくなっていて、 XP はといいながら、ほぼ私の勝手な意見になってます。
なぜドキュメントが要らないのか、何がいらないのか
設計書なしなんてありえないという人も多いと思います。 XP でもまったく要らないといっているわけではなく、不要なところを削ろうということです。
例えば、次のような構造体と関数があったとします。
typedef struct foo_tag {
int a;
int b;
char d[32];
char c[256];
} foo_t;
void barfunc(foo_t *foo);
この foo が IO タイプの引数、すなわち一部のメンバに値を設定して関数に渡し、他のメンバに関数が値を入れることになってたとします。普通、関数を使おうとした場合、まずインプットが何で、アウトプット何かということが必要になります。また、その情報は関数がどんな機能を持つのか判断するのに重要な情報となります。
このとき、入出力のメンバについて何もドキュメントがなかった場合、それを調べるには関数の実装の中身を注意深くみていく必要があります。そんなことを関数一個一個に対して調べるのは大変なので、関数と機能と使い方はしっかりとドキュメントにまとめておきなさいということになります。
もっとひどいのになると関数は引数をとらず、 static 変数や他のデータ取得関数を使って、入力パラメータを取得します。そうなってくるとごちゃごちゃしてきてソースを読み解けないので、ドキュメントに関数の呼び出し関係をイラストにでもして、わかりやすくまとめておくと助かります。やっぱりドキュメントって大事だねってことになります。
XP はそこに待ったをかけて、そのドキュメントほんとにいる ? と言ってきます。
確かに不要です。関数を次のように書けばすむ話です。
void barfunc(int a, const char *d, int *b, char *c);
これで関数の入出力パラメータは何か一発で分かりますし、入出力が分かって関数名もわかりやすければ、ほぼ関数の使い方も分かります。
コメントの不要なコードがいいコードであるということはよく言われます。 XP ではそれを進めて、ドキュメントに頼らないとプログラムの内部が理解できないのは、コードがだめだからで、良質なソースコードであればドキュメントなんてほとんど要らないという考え方です。
これは "ちゃんとドキュメントをかけ"という前に、"ちゃんと const つけろ"といっているようなものです。実に実際的で現場のプログラマの方から XP が熱狂的に受け入れられたのもうなずけます。
ドキュメントには何を書くか
ただ、XP もドキュメントをまったく要らないといっているわけではありません。では、ドキュメントにかかなければいけないものは何でしょうか?
それを考えるために逆に明らかに要らないものを考えてみます。例えばソースコードの内容とまったく同じことを日本語になおしただけのような説明は不要でしょう。ソースコードがちゃんと読めるものであれば、同じことを 2 回書いていることになるわけです。プログラマは同じことを 2 回書くことを嫌います。また、ソースを直すと整合性をとるためにドキュメントも修正することになり、変更に対してなるべくコストを下げるという XP の根本からはずれてしまうことになります。
つまり、ドキュメントにはソースコードに書かないまたは書けないことを書くということが基本になります。例えば次のような内容でしょう。
- プログラムの目的、背景
- 計算式のような専門技術
- 難解な処理に対するイラストなどを使った説明
まだまだいろいろありますが、こういった内容に対してはドキュメントは要らないとは言いません。ちゃんと書いておくべきでしょう。
また、 CASE ツールを使った UML なども書いてもいいでしょう。 CASE ツールであれば、クラス図などはソースを読み込んで整合性を保つことができるので、 2 度書きになりません。
CASE ツールがなければクラス図などは Doxygen などで生成でするものでいいと思います。
Doxygen での生成はソースから作るので設計と実装が逆になるという人もいるかもしれませんが、もともと設計書などのドキュメントは自分のために書くものではありません。ドキュメントは人に見せるために書きます。例えば完全に自分のためにツールであれば、ドキュメントの必要性はまったくありません。それを公開するなど人に使ってもらおうとするとヘルプ、操作説明書が必要になります。これが仕事になってくると
- 仕様を明確にするため
- レビューなど情報共有用にソースコードの理解を助けるため
設計書は自分が設計するのに必要なものではなく、プログラムの内容を人に説明するためのものです。覚書や考えをまとめるためのダイアログなど使うことはあると思いますが、そういったものは残す必要はありません。逆に残すのであれば、整合性を取る必要があります。読み込み機能のある CASE ツールなどがなければ、設計のとき手書きなどでクラス図をかいて、残すドキュメントは Doxygen で生成したものにするわけです。
ソースの質を上げるためののプラクティス
このドキュメントを不要とするためにはコードの質を上げ、開発メンバ全員がソースコードを読む技術を持つ必要があります。 XP ではドキュメントをほとんどいらないとするかわりにこのコードの質を上げるためのさまざまなプラクティスを用意しています。これがソースコード重視ということです。
ソースコードを読む技術に関してはあまりない気もしますが、どうやったらいいコードになるかということを意識して書けば、自然とソースを見てどうしてそういうように書いたのかということは推測しやすくなります。(読むコードがだめなら何したいのかまったく意味がわからないということはありますが)
もちろん、良質のソースコードはプログラムを変更しやすくするものであり、変更コストを下げます。また、プログラムの品質向上や保守性の向上にもなります。
コーディング規約
コーディング規約といえば、インデント幅、ブランク"{"の位置などのスタイルをまず思い浮かべる人も多いかも知れません。もちろん、読みやすさといった点ではそういったものが統一されていた方がいいです。
それよりも重要なのは『 Effective C++ 』や『 C++ Coding Standards 』のようなコーディングの禁止事項や指針をまとめた規約です。
const をつけろ、コピーガードをかけといったコーディングの熟練者が考えた規約を守ってコーディングすることによってプロジェクト全体のコードの質が向上します。
用語集
用語集はもともとチーム全員(開発者・管理者・顧客)の使用する用語とその概念の不一致を解消するためのものです。もちろんそういった意味での用語集は重要です。
それ以外にもコードの読みやすさといった点からも重要です。ある用語に対して使用する単語を統一するための用語集です。例えば file という単語をある人はファイルパスに使って、ある人は std::fsream のようなファイルクラスに使ってということになると読むとき混乱してしまいます。
こういったものはコーディング規約の命名規則のようなところに記述することもありますが、最初の目的での用語集が必要なように新しい分野の仕事が増えるたびにどんどん増えていきます。チーム全員で共有して追加できるようなものが望ましいです。
私が Redmine で用語集プラグインを作ったのは主にこういった目的のために使える用語集が欲しかったからです。
ペアプログラミング
ペアプログラミングとはコーディングしているのをペアのもう一人がずっと見ていることです。奇抜なアイデアであるため XP では有名なプラクティスの一つですが、大事なのは XP ではコードレビューを重視している点です。
コードの質の向上にはコードレビューが行うことが重要です。その究極の形がペアプログラミングというだけです。ペアプログラミングという奇抜なものを取り入れることはなかなか難しいと思います。そういった場合は何もしないのではなく、コードレビューを頻繁に行うことです。
というよりも私としてはコーディング中ずっと人に張り付いていられるというのは性格的に無理なので、導入されてもなぁと思ってたりします。
コード共有
これもコードレビューを一歩進めたものです。プロジェクトのコードを全員で監視してだめなところを見つけたらすぐ直します。チーム全員で責任をもつため、人のコードも注意してみることになります。
リファクタリング
だめなコードを見つけても、それをそのままにしておいたら、コードの質はあがりません。コードの質をどんどん上げていくために必要なものがリファクタリングです。
テスティング
前回の単体テストを行うということです。実はこの単体テストの導入というのはコード品質向上という意味でも非常に効果的です。
単体テストをするためには単体テストをしやすいコードを書かなければいけなくなります。単体テストしづらいクラス、関数というのは static 変数や共有メモリなどを使った他の部分と密接に絡み合ったものです。単体テストを書くことを習慣づけることによって、単体テストしやすい、すなわちモジュール性の高いコードを書くことになります。これで粘土細工のような全体で絡まったプログラミングから積み木やプラモデルのように部品を組み合わせて作っていくプログラミングに変わってきます。
いろいろ書いてきましたが、コード重視で不要なドキュメントは書かないというのは、私が実現できているかというとそんなことはないです。2 度手間の設計書を書いたり、CASE ツールで上手くソースが生成できなくて、逆に 3 度手間になったりということもあります。
ここで書いてきたものはこうしていけらたなという私の願望が結構入ってます。
![]() | Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES) (2006/04/29) スコット・メイヤーズ 商品詳細を見る |
![]() | C++ Coding Standards―101のルール、ガイドライン、ベストプラクティス (C++ in‐depth series) (2005/10) ハーブ サッター、アンドレイ アレキサンドレスク 他 商品詳細を見る |