XPプログラミングの考察 その1 - テスト自動化

XP プログラミングという有名なソフトウェア開発手法があります。有名すぎて今更感もありますが、この XP について考えていきたいと思います。
ただし、 XUnit と呼ばれるテスティングフレームワークについてはいろいろ調べたことはあるのですが、 XP 自体については Wikipedia などのネットの拾い読み程度の知識しかないので、それを私なりに解釈したものです。

XP にとって大事なことは何かというと如何に変更に強く開発していけるかということです。
そのための重要なポイントは次の 2 つだと思います。
  1. テスト自動化
  2. ソースコード重視


テスト自動化


XP のテストといえばテストファーストといった感じですが、個人的にはテストが前か後かというのはたいした問題ではないと思います。 XP の最大のポイントはテスティングと呼ばれるテストの自動化にあります。

ただ、テストファーストも悪いとは思っていません。私も Redmine というバグトラッキングシステムを使っているとき、いっぱい上がっているバグのチケットをひとつづつ修正していくのが結構楽しいときもあるので、テストエラーを一つづつ潰して行くクリア的な楽しさは確かにあると思います。

しかし、やはり大事なのはテストの自動化で XP の多くのプラクティスはテストの自動化に支えられています。

リファクタリング


これはちゃんと動作しているコードでもだめなコードならどんどん修正していこうということです。これは一見あたりまえのようですが、テストの自動化ができていないと出来ません。
プログラマはこのコードひどいなと思っても、一応動いているのであれば普通、なるべく手を出しません。コード修正用の工数などまずもらえませんし、下手にいじって動かなくなっては困ります。そこで汚いものにはフタをすることにします。これは汚ければ汚いほどその傾向になります。
そこに勇気を与えてくれるのがテストの自動化です。
ただまぁ、次回説明するつもりですが、単体テストを入れている時点でそこまでおぞましいコードはできていないとは思います。

ソースコードの共同所有


誰が作ったソースコードでも、開発チーム全員が修正できるということです。これもテストの自動化がなければ、人のコードなど怖くて触れません

継続的インテグレーション(CI)


ビルドとテストをサーバーなどで定期的に行うことです。これはテスト自動化に支えれられているというよりもテスティングにおける"頻繁にテストを行う"というところをシステム的に実現させるものです。

YAGNI(今必要なことだけ行う)


必要な機能だけを実装するということです。これは余計なものを作らないことで早く作っていこうという考え方ですが、テスト自動化をしていない場合、逆に時間がかかってしまうことがあります。
というのも、機能を一つ追加した場合、その機能のテストだけでなく、その機能追加の修正によって他の機能に影響がないかをチェックする回帰テストが必要になってくるためです。テストに時間がかかる場合は機能を一度に追加して通しでテストを行った方がトータルの工数が減るわけです。
テスト自動化をしていればテストもすぐ終わるので、今求められているものだけを作ることができるようになります。 これにより 短期リリースも実現可能です。

XP は変更に強くすることが重要であり、また、変更に強くなっているということを基にした開発手法でもあります。そのため、変更に強くなっていなければ、 XP は破綻します。これがよく分かるのが、この YAGNI でしょう。

ただし、今必要なことに最適化してコーディングするということではないことに注意してください。
必要のない機能は実装しませんが、将来起こるであろう修正に対して柔軟に対応できるようにしておくということは重要です。これは次のポイントである良質のコードを書くということでもあります。


XP の部分的導入というのはよく耳にします。 XP の完全導入はハードルが高すぎて私もできるなんて思ったことは一度もないので、それが当たり前だと思います。ただし、そこで真っ先に導入すべきはテストの自動化です。テスト自動化の導入は大変なので、抜きでやろうということがあるかもしれません。しかし、 XP のほとんどのプラクティスはテストの自動化なしには実行出来ませんし、無理にやったとしても破綻します。
確かにテストの自動化、ユニットテストのコードの記述は面倒です。市販のテスト自動化ツールなどもありますが、それでも軽減されるだけで手間は手間です。しかし、それを超えてこそ XP の恩恵がでてくるのではないかと思います。

UNIXプログラミングの道具箱―プロフェッショナルが明かす研ぎ澄まされたツール群の使いこなしUNIXプログラミングの道具箱―プロフェッショナルが明かす研ぎ澄まされたツール群の使いこなし
(2004/06)
工藤 智行

商品詳細を見る


Rubyを256倍使うための本 極道編Rubyを256倍使うための本 極道編
(2001/01)
助田 雅紀

商品詳細を見る


eXtreme Programmingテスト技法―xUnitではじめる実践XPプログラミング (OOP foundations)eXtreme Programmingテスト技法―xUnitではじめる実践XPプログラミング (OOP foundations)
(2001/11)
日本XPユーザグループ

商品詳細を見る


CppUnitによるXP‐eXtreme Programming‐実践テスト技法CppUnitによるXP‐eXtreme Programming‐実践テスト技法
(2003/07)
大月 美佳

商品詳細を見る
スポンサーサイト
 

XPプログラミングの考察 その2 - コード重視

XP では、ドキュメントをいらないとは言いませんが、それよりもソースコードの方を大事にします。
このソースコード重視が 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 での生成はソースから作るので設計と実装が逆になるという人もいるかもしれませんが、もともと設計書などのドキュメントは自分のために書くものではありません。ドキュメントは人に見せるために書きます。例えば完全に自分のためにツールであれば、ドキュメントの必要性はまったくありません。それを公開するなど人に使ってもらおうとするとヘルプ、操作説明書が必要になります。これが仕事になってくると
  1. 仕様を明確にするため
  2. レビューなど情報共有用にソースコードの理解を助けるため
といった感じで増えてきますが、すべて人のために書きます。
設計書は自分が設計するのに必要なものではなく、プログラムの内容を人に説明するためのものです。覚書や考えをまとめるためのダイアログなど使うことはあると思いますが、そういったものは残す必要はありません。逆に残すのであれば、整合性を取る必要があります。読み込み機能のある 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)Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
(2006/04/29)
スコット・メイヤーズ

商品詳細を見る


C++ Coding Standards―101のルール、ガイドライン、ベストプラクティス (C++ in‐depth series)C++ Coding Standards―101のルール、ガイドライン、ベストプラクティス (C++ in‐depth series)
(2005/10)
ハーブ サッター、アンドレイ アレキサンドレスク 他

商品詳細を見る
 

C++ 国際化

C, C++ で使われている国際化(initialization, i18n)について書いてみたいと思います。
細かいところは結構はしょって書いたのですが、いろいろ書いてしまって結構長いです。

国際化というのは主に言語(地域)ごとにメッセージを切り替えることを言います。 他にも通貨記号($)や時間の表し方も言語ごとに違いますし、少数点などはヨーロッパでは, . の使い方が逆だったりしてそれにあわせることなども含みますが、 今回はメッセージの切り替え中心です。

Un*x


C ではこの国際化は標準ライブラリにローケルという名前で古くからあります。
これはメッセージファイルに番号ごとのメッセージを書いておいて、 コード中では最初に言語を設定し、この番号を指定すると設定した言語のメッセージが取得できる という仕組みです。 普通はコード中に番号を直接書くことはしないでしょうから、 番号に対して define や列挙型をヘッダに記述しておいてそれを使うことになります。

この標準ライブラリはそのまま使おうとするとすごくめんどくさいです。 そのため、せっかくあるのになかなか使われず、国際化が進みませんでした。 そこでで出てきたのが GetText です。
これはベースは標準ライブラリを使用しますが、使いやすくなります。
プログラムを作る側は今まで英語メッセージを文字リテラルとして書いていたところを次のように _で囲むだけで済みます。
printf(_("Helow World.!!\n"));
このように書いたソースに対してツールを通すとメッセージファイルを作ってくれます。
訳す人はツールでメッセージが抜き出されたものができるので、それに対応する訳を書いて、 また、ツールを通すとその言語用のメッセージファイルが出来ます。

これで国際化が進んで、普通に日本語でアプリケーションが使えるようにとても良かったのですが、 個人的にはこの GetText はあまり好きではありません。
というのも、メッセージやアイコンなどはリソースというのですが、 このリソースはソースと分けて一括で管理したいためです。
翻訳用のメッセージはまとまっているのですが、デフォルトの言語(大抵は英語) はソースコードのあちこちに散らばることになりますし、修正する度にビルドのしなおしが必要となります。

今は国際化するのが当たり前になってきたので、もう GetText はいいんじゃないかと思うのですが、 Linux ではこれが主流です。
統合デスクトップ環境である gnome で使われえている GTK+ は GetText を使っていますし、 KDE の Qt は GetText ではなく独自の国際化を持っているのですが、これも GetText 方式です。

Linux ではない商用 Un*x の世界はというと、こちらの GUI は Motif というライブラリが古くから使われていて、これで CDE (gnome や KDE のもとになっているもの) も作られています。 Motif はさらに古い GUI ツールキットである Xt ライブラリの上に出来ているのですが、 こちらはきちんとリソースが分けられています。
Xt ではテキストファイルであるリソースファイルに以下のような行を書きます。
FooApp.FooDialog.OkButton.label : 了解 
キーになる方は親子関係で書くことができ、これを Widget の部品の名前とあわせておきます。 そうすると、アプリケーションは起動時にリソースファイルをロードして言語にあわせたラベルになります。
ただ、これは GUI 専用のところがあって、 エラーメッセージのようなコード中で決める文字列は C の国際化を使用する必要があります。

他に有名な国際化ライブラリで ICU というものがあります。
これはリソースの国際化だけではなく、文字コード変換などの機能も含んだ大掛かりなもので、 クロスプラットホームで動作します。 しかし、文字コード変換などは Boost からも使われるようになって、広く使われているのですが、 リソース管理という面ではそれほど使われていない気がします。
これもリソースを分離するタイプでよく考えられていると思うのですが、 やはり、 GUI ツールキットとセットではないと広まりにくいのかも知れません。

Windows


Windows の場合、 .NET 以前は基本的に C の標準ライブラリのようなもので、 番号(ID)に対して文字列を指定し、 ID を指定して文字列を取得します。
ただ、 Visual Studio のような IDE で作るのが普通なので、 メッセージファイルの作成と番号の define 定義が同時にできるような感じになっていて、 そんなに使いづらくもないかなと思います。
.NET では番号を define したものではなく、 'Foo.Bar.Ok' のような文字列で取得できるようになっています。

Windows ではリソースは exe や dll などのバイナリファイルに埋め込んでしまいます。 なので、翻訳がない場合に問題が出てきます。
Un*x 系では言語の指定は環境変数 LANG で行いますが、 Windows では WIN32API などの OS が提供するライブラリでユーザーが設定している言語を取得してきます。
商用アプリなど売るところが決まっている場合は問題ないのですが、 フリーウェアなどの場合はリソース用の dll などで追加して、 言語の設定を自動で行うのではなく、アプリの設定でユーザーがどの言語を選択するかを指定するといった工夫が必要になります。

Un*x 系はというと翻訳ファイルやリソースは分かれているのが普通なので、 翻訳ファイルの置き場所に翻訳ファイルおいてなければデフォルト言語(英語)で表示して、 翻訳を追加したければ、そこにファイルを置くという方式が多いと思います。

ちなみに Qt はクロスプラットホームなので、アイコンなどのリソースを Un*x でも、がんばって取り込む仕組みを持っています。 ただ、翻訳ファイルは別ファイルになっていて、 Un*x のような追加方式にすることもできなくはありません。
できなくはないというのは、見つからなかったら英語にする仕組みはないので、 その辺はアプリ側で実装する必要があったりします。


といった感じが C++ での基本的な国際化の方法じゃないかと思います。
どれも一長一短といった感じで、これだっと言うものはないです。 強いて言えば、 .NET が良いと思うのですが、クロスプラットホームではないです。
(Linux でも動くんじゃないかって話はありますが)

それでクロスプラットホームの大規模のアプリの中には自前で国際化の仕組みをもったものもあります。
例えば、 firefox, thunderbird の Mozilla では テキストファイルである プロパティファイルや DTD を使った Java っぽい国際化ができるようになっています。

 
このページをシェア
アクセスカウンター
アクセスランキング
[ジャンルランキング]
コンピュータ
24位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
3位
アクセスランキングを見る>>
カレンダー(アーカイブ)
プルダウン 降順 昇順 年別

02月 | 2017年03月 | 03月
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 -


はてな新着記事
はてな人気記事
ブロとも申請フォーム
プロフィール

yohshiy

Author:yohshiy
職業プログラマー。
仕事は主に C++ ですが、軽い言語マニアなので、色々使っています。

はてブ:yohshiy のブックマーク
Twitter:@yohshiy

サイト紹介
プログラミング好きのブログです。プログラミング関連の話題や公開ソフトの開発記などを雑多に書いてます。ただ、たまに英語やネット系の話になることも。