※「達人プログラマー システム開発の職人から名匠への道」は、同じ著者の別の本です。
3部構成で、バージョン管理をCVS、ユニットテストをJUnit、自動化をAntとCruiseControlを使って説明しています。自動化は、ビルド、リリース、デプロイ、監視まで扱っています。
バージョン管理
本書では、CVSを使って説明しています。チェックアウト、コミット、マージ、タグ、ブランチの考え方は、gitでも同じです。
生成した成果物は格納しない
基本的に、他のファイルから再構築できるファイルは格納しません。
ただし、ツールのライセンスが一つしかなく、各開発者ごとに生成できない場合や、作成処理に時間がかかる場合は、成果物をチェックイン(コミット)します。
CVSキーワードは使用しないほうがいい
ソースファイル中の"$Author$"や"$Log$"などのCVSキーワードを書くと、CVSが作成者やログメッセージを自動挿入します。しかし、キーワードを使用しないことを推奨します。
1つ目の問題は、"$Log"はコミットするたびに長くなります。コード本体にたどりつくまえに、大量のログメッセージを読み飛ばさなければなりません。
2つ目の問題は、CVSキーワードの自動挿入された部分が、ブランチ間でコンフリクトしやすくなり、マージが難しくなることです。
ログメッセージには「なぜ」を書く
ログメッセージ(コミットメッセージ)には、その変更を「なぜ」したのか、について書きます。
バグ追跡システムがあるなら、バグレポートの番号だけで充分です。
ブランチとタグ
名前をつける対象 | 形式 | 例 |
リリースブランチ | RB_(バージョン) | RB_1_0 |
リリースタグ | REL_(バージョン) | REL_1_0 REL_1_0_1a |
バグ修正前タグ | PRE_(バグ番号) | PRE_1234 |
バグ修正後タグ | POST_(バグ番号) | POST_1234 |
実験ブランチ | TRY_頭文字_yymmdd | TRY_DT_030631 TRY_AH_021224 |
プロジェクト内の構造
README | 解決すべきビジネス上の問題、使用されている基本技術など、簡単に説明しましょう。 |
BUILDING | ビルド手順。ビルドスクリプトがある場合は、ビルドコマンド。 |
GLOSSARY | プロジェクト固有の専門用語集。クラス名、メソッド名、変数名を決めるときの指針。 |
doc/ | ドキュメントすべて。メモや電子メールも含めます。 |
data/ | プロジェクトのデータ。例えば、各種のルックアップテーブルに必要な情報。 |
db/ | データベースのスキーマ。スキーマの更新、データ移行するSQLスクリプト。 |
src/ | ソースコード。 |
util/ | または tools/ プロジェクト固有のユーティリティ、ツール、スクリプト。 |
vendor/ vendor/lib/ vendor/include/ | サードパーティのライブラリやヘッダーファイル。 |
vendorsrc/ | サードパーティのソースコード。 |
ユニットテスト
データファイルの使用
テストデータが大量のときは、テストコードに書くよりも、データファイルにします。データファイルにテストの値と期待する結果を記述して、ユニットテストで読み込ませます。
テストする内容:Right-BICEP
Right(適切)
コードが正しく実行されたと、どうすればわかりますか。
Boundary(境界)
境界条件を考える略語 CORRECT
Inverse(逆の関係の確認)
論理的に逆の処理をして確認する。
Cross-check
他の方法によるクロスチェック
Error conditions
エラー条件を強制する。メモリ不足、ディスクの空き容量不足など。
Performance (パフォーマンスの特性)
データ個数が大きくなったとき、処理時間がはどうなるかのテストを用意しておき、1日1回実行する。
境界条件:CORRECT
Conformance(適合性)
文字列の書式チェック、データ構造のチェック。
Ordering(順序)
検索対象がコレクション内の最初にあったり、最後にある場合。
Range(範囲)
年齢は20000歳まで生きる人はいないなど、属性がもっている範囲。配列インデックスの下限と上限など、データ構造がもっている範囲。
Reference(参照)
メソッドがメソッド外の何かを参照していないか。外部依存性。クラスが保持している状態。
Existence(存在)
渡す値や保持する値が、null、空白、0の場合。
Cardinarity(モノの数)
フェンスポストエラー。0−1−nの規則。
Time(時間)
メソッドの呼び出しの順序。タイムアウト。1日の長さは24時間ですか。マルチスレッド。
良質なユニットテスト A-TRIP
Automatic(自動)
テスト呼び出し。テスト結果の確認。
Thorough(徹底)
コードの網羅性。コードカバレッジ。
Repeatable(繰り返し可能)
すべてのテストが任意の順序でくり返し実行でき、同じ結果であること。データベースやWebサーバを開発者ごとに分離します。
Independent(独立)
どのテストも他のテストに依存しないこと。どのテストも任意の順序で実行できること。
Professional(専門的)
ユニットテストのコードは、本番コードと同じくらい専門的な標準で作成し、保守します。テストコードも共通のコードを抽出し、機能をメソッドに抽出します。
自動化
ビルドスクリプト
コードのビルドとテストを実行するビルドスクリプトを作ります。シェルスクリプト(Windowsならバッチファイル)や、Antなどのビルドシステムを利用します。
ビルドスクリプトでロジックを表現したい場合は、Antとスクリプト言語を組み合わせます。
プロジェクトの初日から、ビルドスクリプトを作ります。
定期ビルド
開発者のモラルに頼るより、ビルド専用マシンを用意して、誰かがコミットしたら、自動ビルドが走るようにします。
リリース手順のスクリプト
masterブランチをチェックアウトして、ビルドとテストします。
masterブランチからリリースブランチを作成し、チェックアウトします。
リリースブランチをビルドとテストします。
リリース配布ファイルを作成します。リリースブランチから、ソースファイルやテストコード、開発ツールを除外して、zipパッケージにします。
配布ファイルをテストします。
ファイル内容の比較
配布ファイルを展開したファイルと、リリースブランチのファイルを比較します。
アプリケーションの実行
展開したファイルが壊れていれば失敗するようなスクリプトを実行します。
テストの実行
CLASSPATHを修正して、本番クラスに対して、リリースブランチのテストを実することができます。
リリースバージョンのタグをつけます。
ファイルの納品。本では、QAチームへ配布ファイルを渡すというシナリオなので、共有ディレクトリにコピーしています。
インストールと配置
インストールアプリケーションの診断テストを作成します。診断テストは、Javaバージョン、環境変数、インストールディレクトリ、カレントディレクトリ、ファイルやディレクトリの読み書きモードなどを検証します。
インストールアプリケーションの自動更新を用意します。
サーバーアプリケーションの診断用Webページを用意して、バージョンなどを表示します。診断用Webページにアクセスして、バージョンが正しいか検証するプログラムを作ります。
サーバーアプリケーションの自動デプロイの最後に、検証プログラムを実行します。
監視
定期ビルドの失敗の通知。関係者に通知する手段として、電子メール、携帯電話のテキストメッセージ、RSS、ビルドモニター、緑と赤のラバランプ、Ambient Orbなど。
Webアプリケーションのチェック。スクリーンスクレイパーを作成して、ページ内容に Error や Exception があるかどうか調べます。
ログファイルの監視。例えば、すべてのエラーメッセージがローカルのエラーログファイルに出力されるとします。エラーログファイルの更新日時をチェックすることで、エラーを監視します。
log4j。外部の設定ファイルを変更するだけで、ログイベントを捕らえることができます。
デバッグページ。バージョンやシステム情報などを表示するデバッグページを用意します。スクリーンスクレイプして、健全性を監視します。Jettyという組込み可能なWebサーバを利用することもできます。