読者です 読者をやめる 読者になる 読者になる

kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

「レガシーコード改善ガイド」読書メモ(その2)

Java メモ

「レガシーコード改善ガイド」という書籍を読み、自分の解釈した内容をメモしています。

前回は、コードを改善する考え方をまとめました。
今回は、実際のテストコードについて書きます。

書籍では、テストコードの書き方について、第2部、第3部で書かれていました。第2部は多くのページを割き、実際の開発現場における数々の実例を端的に説明していて、面白かったです。第3部は、第2部で色々説明していた内容を「手法」としてまとめ、リファレンス的に説明していました。

主に第3部の内容について、利用頻度が高そうな「手法」をメモしました。

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

テストコードの書き方

命名ルール

テストコードを書くときに作成する各種クラスについて、おすすめの命名ルールとして、次のようなルールが紹介されていました。実際にクラス作成する際に、迷うのも手間なので、こういうルールを覚えておくと便利ですね。

  • テストクラス:XxxTest
  • テスト用サブクラス:TestingXxx
  • モッククラス:FakeYyy

※「Xxx」はテスト対象のクラス名です。「Yyy」はテスト対象クラスから呼ばれるクラスの名前です。

手法一覧

テストコードを書くときに、しばしば問題となるのは、テスト対象クラスと、他のクラスとの依存関係です。依存関係を排除する手法が、24個紹介されていました。

各手法について、個人的な感覚になりますが、利用頻度を3段階で表し、どんな依存を解決する手法なのかまとめました。(利用頻度が低いと思う手法は、少々説明を省略しています。)

No. 名前 頻度 解決する依存箇所
25.1 パラメータの適合 引数(アプリケーション外クラス)
25.2 メソッドオブジェクトの取り出し コンストラクタ/メソッド
25.3 定義の補完 × (省略)※リンク切り替え。混乱を生む。
25.4 グローバル参照のカプセル化 グローバル変数
25.5 静的メソッドの公開 コンストラクタ
25.6 呼び出しの抽出とオーバーライド メソッド
25.7 Factory Method の抽出とオーバーライド コンストラクタ
25.8 getメソッドの抽出とオーバーライド × (省略)※C++特有
25.9 実装の抽出 × (省略)※命名を妥協すれば不要
25.10 インターフェースの抽出 引数(アプリケーション内クラス)
25.11 インスタンス委譲の導入 staticメソッド
25.12 静的setメソッドの導入 メソッド
25.13 リンクによる置き換え × (省略)※リンク切り替え。混乱を生む。
25.14 コンストラクタのパラメータ化 コンストラクタ
25.15 メソッドのパラメータ化 メソッド
25.16 パラメータのプリミティブ化 (省略)※理解できませんでした
25.17 メソッドと変数の引き上げ × (省略)※クラス設計を混乱させそう
25.18 依存関係の押し出し × (省略)※クラス設計を混乱させそう
25.19 関数ポインタによる関数の置き換え × (省略)※C/C++特有
25.20 getメソッドによるグローバル参照の置き換え グローバル参照
25.21 サブクラス化とメソッドのオーバーライド コンストラクタ/メソッド
25.22 インスタンス変数の入れ替え × (省略)※C++特有
25.23 テンプレートによる再定義 × (省略)※C++特有
25.24 テキストによる再定義 × (省略)※Ruby特有

手法の使い処

上述の手法のうち、利用頻度が高い手法について、使い処を考えてみました。あまり細かくパターン分けしても、私には使いこなせないので、ざっくりと分けてあります。

  1. テスト対象クラスのインスタンス生成が必要であるが、インスタンス生成が難しい場合(コンストラクタに依存あり)
    1. テスト対象のメソッドが、インスタンス変数に依存していない場合
      25.5 静的メソッドの公開
    2. コンストラクタ引数に渡すインスタンスの生成が難しく、引数のクラスがアプリケーションの外部で定義されている場合
      25.1 パラメータの適合
    3. コンストラクタ引数に渡すインスタンスの生成が難しく、引数のクラスがアプリケーション内で定義されている場合
      25.10 インターフェースの抽出
    4. コンストラクタ内の処理において、他クラスのインスタンス生成部分が困難な場合
      25.14 コンストラクタのパラメータ化 または 25.7 Factory Methodの抽出とオーバーライド
      ※この2つの使い分けがいまひとつ理解できませんでした。
    5. コンストラクタ内の処理において、一部処理が困難な場合
      25.6 呼び出しの抽出とオーバーライド
  2. テスト対象のメソッドを動作させるのが難しい場合(メソッドに依存あり)
    1. メソッド引数に渡すインスタンスの生成が難しく、引数のクラスがアプリケーションの外部で定義されている場合
      25.1 パラメータの適合
    2. メソッド引数に渡すインスタンスの生成が難しく、引数のクラスがアプリケーション内で定義されている場合
      25.10 インターフェースの抽出
    3. メソッド内の処理において、他クラスのインスタンス生成部分が困難な場合
      25.15 メソッドのパラメータ化 または 25.6 呼び出しの抽出とオーバーライド
      ※この2つの使い分けがいまひとつ理解できませんでした。
    4. メソッド内の処理において、一部処理が困難な場合
      25.6 呼び出しの抽出とオーバーライド

おわり

書籍の内容で理解できなかった部分がありました。解釈が間違っている部分もあるかもしれません。それでも、自分のために、個人的な感覚で、まとめました。

あと、利用頻度の高い手法についてだけでも、具体的実装方法までまとめたかったのですが、またの機会にします。

読書メモは、これにて、終わりとします。