!!!技術的雑談-プログラム開発プロジェクト未整理Tips !!環境 *プログラム開発現場 !!対象 *いわゆる「システム開発」に関わる人全て !!Tips !テストの妥当性をチェックするべき 往々にしてテストケースを書いて誰のチェックも受けずにそのまま本人がテストを実施して「OKでした」ということが多いですが、テストが終わってからテストそのものの妥当性を論じても手遅れです。 テストケースを書く時には'''「テストケースの妥当性」'''の他に'''「テスト密度の妥当性」'''もチェックしてからテストを始めるようにするべきです。 プロジェクトリーダーはテストケースを書き始める前にテスト密度の目標値をメンバーに周知するべきです。 ''ToDo : テスト密度の目標値をどうやって決めるか?'' !3人以上のプロジェクトにはアーキテクトが必要 アーキテクトとは、実装方法・実現方法の方向性に関して責任を負う人の事です。 全体を俯瞰するアーキテクトを定めないで作ったコードは結合段階でコーディング段階と同じだけの工数を要することになります。 !機能とコードグループは必ずも一致しない 「機能」は上流工程からの要件とリンクしている分類。 「コードグループ(アセンブリ、ネームスペース、ビルド単位、DLL単位)」は実装的な要因による分類。 異なるのが当然です。 それを顧客報告や品質チェックの為に機械的に集計するのは本来無理がある話です。 その為には品質管理者やプロジェクトリーダーが上向けの「機能」と下向けの「コードグループ」を紐付けるロジックをプロジェクトごとに制定する必要があります。 自然発生的にそれが解決するのは幸運な場合を除いて普段はありえません。 共通部品を別機能として分類すれば整合性が取れるようになる可能性がありますが、上流工程の人は往々にして「共通機能」という概念を忘れがちです。 !リーダーはタスクを担当者にアサインできなくてはならない リーダーの仕事は「決定すること」の他に「タスクをメンバーに振る」というものもあります。 情報収集→状況分析→決定→タスク作成→タスク振り→タスク進捗管理→結果確認→次のタスクの決定 のサイクルを保つのが「タスクを振る人」の使命です。 !テストは繰り返すことができなくてはならない テストはコードに変更がある度に、仕様に追加・変更がある度に'''「全てを」'''繰り返せる必要があります。 実際問題として、多人数でのプロジェクトの場合、テストの消化と平行してコードの修正が必要になります。 すると、最初のテストを行った時と最後のテストが終わった時でテスト対象のコードは既に同一のものではなく、最終的なコードはもしかして最初のテストをパスできないものになっているかもしれません。 理想的には、単体テスト、結合テストはHudson、ContinumなどのCIサーバを利用して'''「機械的に」'''、'''「誰でも」'''、'''「いつでも」'''、'''「何度でも」'''繰り返せるべきです。 テストは「その一つのテストケースがOKだった」事が大事なのではなく、「全てのテストがOKだった」事に意味があるのです。 !「タスク」に必要なパラメータ タスクには「担当者」「報告先」「目的」「手段」「使用リソース」「次のタスク」「前のタスク」「期限」が必要です。 すぐに終わらないタスクにはマイルストーンを設定して進捗を管理できるようにするか、マイルストーンが不要になるまでサブタスクに分割するべきです。 得にプログラム開発などの場合、テストサーバやハードウェアデバイスなどの「使用リソース」の割り当てを忘れることが多いです。 !コードの担当者、機能の担当者を明確に保つ ソースコードにシグネチャを入れるだけでは不十分です。 それはファイル単位での管理でしかありません。 もっと大きなスコープでの「担当者」を設定する必要があります。 多人数プロジェクトでは複数のメンバーが1つの機能を担当したり、複数の機能の一部を一人の担当者がコーディングしたりしますが、コードグループや機能の担当者は常に全体像を把握しておくべきです。 !6人を超えるプロジェクトには1人以上のテスト・品質専任管理者が必要 テスト密度の管理、全体進捗の把握、コード規模の集計など、自動化するにせよしないにせよ、それを行う担当者が必要です。 一般的に、プロジェクトのメンバーが多いほどコードの規模も機能の数も多くなるので、「全体の」管理を行う為の工数が大きくなります。 従って、兼任でテスト・品質管理担当をするには工数が大きくなりすぎます。 「あまった人手を管理に振る」のではなく、「あまった管理者を作業に振る」方が正確性と効率の上で優れています。 !結合テストの前にインストール手順書が必要 結合テストでは自分の作ったコード以外も動かす必要があり、その為には他人のコードをどのような環境でどのように稼動可能な状態にするかの手順書が必要です。 また、明確に要件から除外されている場合を除いて、「インストールとセットアップ」というのは要件段階で最も見落とされやすい(もしくは暗黙的に要求される)機能の一つです。 機能である以上テストが必要で、テストが必要である以上設計と実装が必要です。 また、結合テストでは本番環境と異なる為に「特殊なセットアップ」が必要になることも多いです。 その「特殊なセットアップ」をテストチームの中で明文化して共有する必要があります。 これは特にテスト工数が予想以上に必要になってリソース(マシン)や人手を追加投入する際、もしくはプロジェクト内で人員の配置換えをスムーズに効率的に行う為の重要な鍵になります。 インストールマニュアルを納品直前に行うのは実はテストが限定的で無意味だったことの証拠です。 !境界で問題が出た時は両担当者にタスクを振る プログラム間、システム間、もしくはインターフェース間で問題が発生した場合はとにかく両方にタスクを振りましょう。 問題が出たということは双方の認識にズレがあったということです。 実装や運用の対応を考えるよりも合意の(再)確認と担当者間での認識合わせが重要です。 そこにアーキテクトを関与させるのも重要な点です。 さらにシステム境界では対向が自分たちのプロジェクト外の事もあります。 その場合にも相手に対してタスクを振れるようにしておきましょう。 !仕様書にもバグがあることを忘れない 仕様書は目的を文章化したものですが、実証されたものではないので必ず見落としや矛盾があります。 実装作業は仕様の検証作業でもあります。 コーディングやテストの時に「仕様にもバグがあるかもしれない」と考えるように心がけましょう。 !ソース規模はいつでも簡単に確認できるようにしておく テスト密度、バグ発見密度などの品質は結局のところソース規模を分母として計算されます。 頻繁に参照されるべきパラメータなのでいつでも簡単に算出できるようにしましょう。 ステップカウンタープログラムやプロジェクトによってコメント行のカウント方法や空行、宣言文のカウント方法などに違いがあります。 全員で共通したツールで、どのようにソースコード規模をカウントするかルールを決めた上で内部用のスクリプトにしてしまうのがよいかと思われます。 !テストでバグが出た時は前工程のテストも必ず再実行する テストは繰り返せるようにとの部分と重複しますが、後の工程のテストで問題が出た場合、なぜその問題が前の工程で検出されなかったのかを分析し、前の工程に反映させる必要があります。 仮に結合テストでバグが発見された場合、そこで行うコード修正は'''「全ての」'''単体テストがパスする事を確認するべきです。 さらに、単体テストの項目に必要であれば今回の問題の単体レベルでのテストケースを追加するべきです。 !口頭で1分以上説明に費やすタスクは「難しいタスク」 「難しいタスク」を口頭で伝えて実行させるのはトラブルの元になるのでやめましょう。 口頭説明が1分を超えたら10分後にはもう双方その正しい内容を思い出せません。 後からそのタスクが正しく行われたのかを検証するのが不可能になります。 時間の無駄です。 !方式を論じる前に目的の合意を取る 設計段階の後の工程で問題が起きた場合、問題の解決の為に'''「修正方法」'''を議論してしまう事が多いですが、まず'''その問題が阻害しているシステム本来の目的'''を確認しましょう。 そうしないとシステム本来の目的にかなった合理的な修正が行えず、結果的に「テストをしながらコードをダメにしていく」ことになりかねません。 !カテゴリー分け自体にも不備がある可能性を忘れない カテゴリー(機能、コードグループ)も工程の進捗、コード自体の成長・成熟にあわせて 変化する、もしくは変化させたほうが良いこともあります。 かたくなにその時決められているカテゴリーを死守する事は必ずしもシステム全体の品質や進捗にとってプラスにはなりません。 管理にとって使い勝手が悪ければカテゴリー分け方法を見直す事も視野に入れましょう。 その為にもテスト・品質管理専任を置くことは有用です。 また、設計段階で決めたカテゴリー分けをコーディング、単体テストでも使い続けるには無理がある場合が多いです。 コーディング、単体テスト用のカテゴリー分けを作成し、設計段階でのカテゴリーと複数対複数で紐付けておくほうが合理的で簡単です。 !議事録を取らない会議はやらないほうがマシ 口頭タスク1分ルールと同じ理由で、議事録を取らない会議はやるだけ時間の無駄であるばかりではなく、会議が行われてしまったが為に各自の曖昧な認識を正当化してしまう材料にもなります。 (言った・言わないの水掛け論) !「納品物作成」の期間を忘れずにスケジュールする 何を納品する必要があるのか、どのような形で納品するのか、その為にどれだけの時間がかかるのかを必ず見積もりましょう。 逆算して、いつ納品する為にはいつから納品物作成を行えばいいのかリミットを決めておけば納品前にゴタゴタする原因を一つ減らすことができます。 !「開始処理」「終了処理」「初期導入処理」の設計を忘れない 少なくとも結合テストに入る前には「開始処理」「終了処理」「初期導入処理」を'''「機能として」'''仕様化しておきましょう。 その際、各機能やコードグループの依存関係を整理しておくことも大事です。 !「テスト環境」もバージョン管理する テストに必要なデータファイル、INIファイル、手順書、項目書、DBのバックアップもテストケースコードと一緒にバージョニングして管理しておきましょう。 環境依存バグやテスト者個人依存バグの追跡や再現に効果的です。 テスト環境の追加、再構築などの工数節約にも繋がります。 また、テスト環境が複数台ある場合にそれらの環境を合わせるのにも必要です。 !単体テストフレームワークを使う時は「最初から」使う 後から泥縄式にJUnitなどの単体テストフレームワークを使おうとしても単に工数を食ってしまうだけです。 経験則的に、ある100行のクラスをテストする為には300〜500行の単体テストを書かなくてはなりません。 しかも仕様変更が起こったときにはその単体テストのソースもメンテナンスしなくてはなりません。 単体テストフレームワークを「使う」場合には計画段階からその為の工数をスケジュールに含めましょう。 !単体テストフレームワークのコードは本番コードと同時に書かないと意味が無い 既に他のコードと結合している状態で「動いてしまっている」コードに後から単体テストを書くのはナンセンスです。 また、そのような状態の時は詳細設計の仕様があいまいである事も多いです。 意味のある単体テストは正確な詳細設計とペアであるべきです。 そうでない場合は工数の割りに効果が薄いです。 ! カバレッジの測定を行わない単体テストはナンセンス 単体テストの考え方においてカバレッジの高い低いにかかわらず、カバレッジそのものを計測しない事はナンセンスです。 先の工程に進めば進むほど全経路を網羅させる事は難しく、かつ、通っていない経路には必ずといっていいほどバグがあります。 また、カバレッジ測定によって「通りようの無いコード」も明確になり、実装上の無駄も明確にできます。 !!履歴 *2009/01/21 -- 初版 *2009/03/08 -- 追記 [[技術的雑談]]へ戻る !!突っ込み {{comment}} [[技術的雑談]]へ戻る {{trackback}} [[技術的雑談]]へ戻る