作成日 2008/3/22
最終更新日 2011/7/26
[ Japanese | English ]

オブジェクト指向設計と試験性

 オブジェクト指向設計する際、クラスの凝集度や結合度に注意を払ったり、エンティティを正規化したり、クラスの責務をどうしようとか、に頭に入れる必要のあることがいくつかあります。そのなかに、試験性に注意を払うというのも入ると思います。

 早い話、テストがしやすい設計にしましょうということです。

1.試験性とは
2.試験性を考慮した設計にする
3.参考文献など


1.試験性とは

 試験性という言葉は聴きなれない言葉だと思いますので、説明します。

 ソフトウエア品質特性(ISO/IEC9126(JIS X 0129)) に6つ品質特性が定義されています。そのうちの1つに「保守性」というものがあり、「試験性」はその「保守性」の品質副特性の1つとなっています。
 具体的には「試験性」は「改訂したソフトウエアの妥当性の確認に必要な労力に影響するソフトウエアの属性」と定義されています。
 品質特性についての詳しいことは参考文献 の1番を参照してください。

 例えば、プログラムを修正した場合、再テスト(※1)が必要となりますが、このときテストが自動化されている場合は、自動化されていない場合と比べテストに要する労力が少なくてすむので試験性が良いということになります。

 この試験性があまりにも悪かった場合は、以下のような聞きたくもないことが起こりえます。
  1. テストでバグを発見。
  2. バグを修正。
  3. バグを修正したときに、バグを作りこむ。もしくは、バグを修正したことによって、今まで顕在化していなかったバグが顕在化する。
    (バグが2つあり、1つのバグがもう一つのバグを発見しにくくすることは良くある)
  4. 1に戻る。
  5. いつまでたってもバグ曲線が収束しない・・・。
  6. デスマーチ(※2)へ

-----
※1:
 修正したところはもちろんテストすると思いますが、実際には修正していない箇所もテストする必要があります。
これは、修正したことによって他の箇所に影響がなかったことを確認する必要があるためです。このために行うテストを回帰テストと呼びます。
※2:
 デスマーチになる理由は試験性の不良とは限りません。いや、むしろ、プロジェクトマネジメント(※3)上のミスの方が大きいと思います。
 納期切迫、コスト超過、要員の技術力不足(例えば、新人が担当したとき)、度重なる仕様変更により、試験性が悪くなり(試験性をよくする活動が出来なくなるため)、デスマーチになると思います。
※3:
 具体的には、スコープ管理、進捗管理、コスト管理、品質管理、組織要員管理、リスク管理、調達管理、コミュニケーション管理、統合管理の9つの管理です。
詳細はPMBOKの勉強をしてください。
このページのトップへ

2.試験性を考慮した設計にする

 ということで、試験性を考慮した設計にしましょう。
 以下に考慮すべき点を挙げます。

  1. 設計時、テスト(特に単体テスト)の自動化がしやすい箇所としにくい箇所を明確にし、自動化がしにくい箇所を極力少なくする。
     だるまの経験では以下の箇所がテストの自動化がしにくいです。
     ・画面系(※1)
     ・処理に時間がかかる箇所(例えば、ネットワークが関係する箇所)(※2)
     ・外部からデータを読んだり、外部へデータを保存する箇所(DBアクセス、ファイルアクセス、標準出力・・・)(※3)
    です。

  2. テスト用のスタブやドライバが作成しやすい設計にする。
     スタブとはテスト時において、テスト対象クラスが使用しているクラスの代わりとなるクラスのことです。
     1番ではDBアクセスを使用しているクラスを使っているクラスはどうやってテストするのかという問題になります。そのようなときはモックオブジェクト(※4)を作成して対応します。その際は、テスト対象のクラスがモックオブジェクトを使用してテストが出来るような設計にしておく必要があります。

     ドライバとはテスト時において、テスト対象クラスを呼び出すクラスのことです。
     例えば、ある属性に対してsetter(※5)だけがある場合、テストプログラムからこのsetterを呼び出すことになりますが、これだけではちゃんと値が設定されたのかがわかりません。このようなときはgetterも作成してください。

  3. 変更が発生しやすい箇所と、変更が発生しにくい箇所を明確にする。また、変更が発生しにくい箇所を極力増やす。
     可能な限り共通化を行った方が良いということです(※6)。
     それから、データは処理に比べて安定(変更がかかりにくい) ですので、分けておくと良いと思います。

  4. 双方向の関連や双方向の依存を避けます。双方向の関連は単方向の関連に出来ないか、双方向の依存は単方向の依存に出来ないか、再度確認します。
     ちなみに、双方向の依存が特にやばいです。
     
     双方向の関連(双方のクラスがもう片方のクラスのオブジェクトを保持しあう)は、ガーベッジコレクションのアルゴリズムが参照カウント方式の場合に面倒です(何もしないとメモリリークになる)。
     
     双方向の依存(双方のクラスがもう片方のクラスのメソッドを呼び出しあう)ですが、単体テスト時にクラス単位で単体テストが実施できず、2つのクラスを同時に行うことになるので、テストがしにくくなります。
     ※クラス図的に双方向に依存してなくても、内容的に双方向になっているのもダメです(これはさらにまずい)。単体テスト時は問題なくても、後で(仕様変更時など)影響範囲を洗い出すのが大変になります。
     

  5. トレースログ(デバッグログ)の埋め込み
     単体テスト時はトレースログがなくても何とかなりますが、結合試験以降はトレースログが入ってないと、問題発生時、解析が困難になります。
     さらに、詳細なことを言うと、一般にログの出力先や出力レベルは設定ファイルに設定することが多いのですが、この設定ファイルの厳格なチェックも必要です。
     ※単に困るだけでなく、セキュリティ上の問題もある。

     以下も必ず確認しましょう。
     ・ログの設定ファイルは解析可能か?
      →解析不能ならアプリケーションを起動させない。
     ・ログの設定ファイルに指定された出力先は存在するか?書き込み可能か?容量は大丈夫か?
      →ダメならアプリケーションを起動させない。


  6. 設定メソッド(setter)などでの厳格な引数チェック、状態チェック
     共通クラス、ライブラリ作成時は厳格にチェックしましょう。
     その他、画面や外部ファイルからの入力データも厳格にチェックし、NGの場合は画面にてユーザに知らせる、ログに出力する(もちろん、どこが悪くて、どのように対処すればよいのかが分かるように)といったことが必要です。
     オブジェクト指向の3大要素の1つであるカプセル化はこのためにあるといっても良いくらいです。
     これが行われていると単体試験でより不具合を検出でき、結合試験以降のバグ発生を抑え、工数を減らすことができます。

  7. いくらテストをしても、全パターン試験はできないことを意識する
     意識する前に、知らなかった人は、まず、上記の内容を知るところから始めてください。
     ホワイトボックスにて命令網羅、条件網羅などがありますが、仮にそれで全網羅させても、それで網羅させただけです。
     たとえば、
     a = b / c;
     というプログラムがあったとき、c=0のとならないように作成されていなければバグですが、これだけでは命令網羅・条件網羅のいずれでも、c=0のパターンは出てきません。
     他にも、マルチスレッドプログラミングの場合、すべてのタイミングを網羅するなど、パターンが多すぎて無理なのですが・・・。

     なので、「いくらテストをしても、全パターン試験はできないことを意識する」ことが重要なのです。
     上記を意識すると、もちろん、設計工数、プログラミング工数が増大します。しかし、オブジェクト指向設計、プログラミングはそうでない設計、プログラムよりはその増大する工数を抑えられると思います(カプセル化は特に役に立つ。)。

-----
※1:
 画面系の試験はUWSCで自動化は可能です。
 しかし、一般には、画面系とロジックは一緒にしてはいけないです(再利用という観点からも)。可能な限り切り分けてください。
※2:
 一般に単体テストは繰り返し実行します。テストに時間がかかるようになると、面倒くさくなってくる・・・。
 たとえ、システムの仕様上、遅くても良い処理があったとしても(お客さんから遅くても良いといわれていたとしても)、テストのことを考えると工数をかけてでも、速く動作するようにした方がいい場合もあります。
※3:
 必ずしも自動化できないことはないと思います。ただし、テストプログラム側にてDBのデータを用意したり、出力されたファイルをチェックする必要が出てきます。それが結構手間だったりする。
 標準出力については、後から出力された文字列を取得する方法をだるまは知らないです。同時にバッファ(Javaならjava.lang.StringBufferクラス、VBAならString型)にも書き出すようにする必要が出てくると思います。
※4:
 モックオブジェクトはスタブの一種です。
※5:
 setter、getterとはクラスのprivateな属性の値を設定したり、値を取得したりする関数のことです。VBAではProperty Let、Property Set、Property Getプロシージャを使用して実現します。さらに詳しいことは、「カプセル化と属性と操作 - だるまのエクセルVBA 」を参照してください。
※6:
 ただし、今までのだるまの経験では共通化を行ってくれる人はなかなかいないです。共通化されたものを使用する人はたくさんいますが・・・。

このページのトップへ

3.参考文献など

 このページでは、試験性を考慮したオブジェクト指向設計について紹介程度しかしていません。
できれば、下のページも読んでほしいです。

番号

リンク先の名称

リンク先の説明

リンクした日

1

ソフトウェア品質特性 ソフトウェア品質特性(ISO/IEC9126)の解説が書かれています。 2008/3/22

2

@IT:開発プロセス再入門(7) 回帰テストとテストの自動化について書いてあります。 2008/3/22

3

第4回 単体テストの問題解決「テスト駆動型開発」:ITpro 7つの単体テストのテクニックが紹介されています。
とくに、モックオブジェクト、ログに関するテストは非常に参考になると思います。
2008/3/22
Prev Up Next  Top
このページのトップへ

このページの利用によって発生した、いかなる損害について、このホームページの作成者は責任を負いません。
このページの間違いや嘘を見つけた方、このページに書いて欲しい情報がある方はメールをお願いします。

Microsoft 、Windows 、Visual Basic および Excel は米国Microsoft Corporationの米国およびその他の国における登録商標または商標です。
ここではExcel® をエクセル、Visual Basic® for Applications をVBAと表記する場合があります。
Mac 、Mac OS 、Mac OS X は米国Apple Computer,Inc.の登録商標または商標です。
Sun、Sun Microsystems、サンのロゴマーク、Java、及び、Sun/Solaris/Java に関連するすべての商標およびロゴマークは米国 Sun Microsystems, Inc. の米国およびその他の国における商標または登録商標です。
PMBOKは米国PMI(Project Management Institute)の登録商標です。
その他、社名および商品名、システム名称などは、一般に各社の商標または登録商標です。

このホームページの作成者はこれらの会社とはいっさい関係がありません。