【負けパターン】 シリーズでは

現場でソースを見ていて、これが良くないよね というパターンを見ていきます。


さて、以下のソースを見てほしいのですが


--------------------------------------------------


Map userInfoMap = new HashMap();


 中略


test1Mes(userInfoMap );


--------------------------------------------------


test1Mes()メソッドは何をするメソッドで引数からどんな値を取得しているのでしょうか?


じーーーー と見つめましょう


・・・・・


はい、わかりません。 なので以下を見てみます。




public void test1Mes(Map userInfo){


   String username = (String)userInfo.get("username");
   String age = (String)userInfo.get("age");

   System.out.println("ユーザ名 =>" + username);
   System.out.println("年齢 =>" + age);
}


--------------------------------------------------


あー マップに username と age が格納されていて標準出力に出力されるんだな~ なるほど


では、次を見ます。


--------------------------------------------------


 

    UserInfoDTO dto = new UserInfoDTO();

 

     中略


    test2Mes(dto );



public class UserInfoDTO{


   private String username;

   private String age;


   public String getUsername(){ return username;};

   public String getAge(){ return age;};


    public void getUsername(String username){ this.username = username;};

   public void getAge(String age ){ this.age = age;};


}


--------------------------------------------------



さて、


test2Mes()メソッドは何をするメソッドで引数からどんな値を取得しているのでしょうか?


  何をするものかわかりませんが、たぶん username と age を取って何かをするものなのでしょう。


 

というふうに、メソッドの中を追わなくても外側からの見通しがよくなります。

 

 さらに、Mapオブジェクトにセットするキーのスペルを間違えたとします。


 map.put("userneme","たれみみ"); // aをeにしてしまった。


 これはコンパイルエラーになりません。ランタイムエラーになってしまいます。


   しかし


 dto.setUserneme("たれみみ"); // これはコンパイルエラー


マップオブジェクトは値をプットするときはエラーになりません。

これがエラーとして検出されるのは、値を取り出すときです。


実際にあったのですが、某大手IT会社のテストケースに 


   データバインドのキーは小文字で "u" "s" "e" "r" "n" "a" "m" "e"

   であることを目視で確認すること!


   デバックモードでブレイクポイントを張ってオブジェクトの中身を確認すること!

 

 と堂々と書いてありました。 う~ん 繰り返しの試験をすることになったらキツそうです。


 

 逆にマップを使ったほうがいい場合を考えると


   ・キー と 値 の組み合わせが不定である場合

   

   ・不定ではないがいくつものパターンがある場合


 このような場合は仕方がないので、マップを用いて重点的にテストするべきでしょう。



 あらかじめ、username とか age とか わかっている場合は ValueObject や DataTransferObject

 を作って値を出し入れするべきです(2つだけなら引数2つのメソッドでもいいと思いますが)。

 

 そのようにすると、スペルミスをコンパイルエラーにしてくれるだけでなく、型を指定すれば型のチェックもできます。

 (例えば age を int 型にすれば 数字にできないものは入りません あるいは 数字にできないものを

 入れようとしたところでランタイムエラーになってくれます。)


 ValueObject や DataTransferObject(厳密にはそれぞれの意味は微妙に違いますが) を作る手間を

 省略すると、結合テストの手間が増えるとともに 本番環境のリスク が増加します。言い換えると、


 ValueObject を書くのがめんどいので、テスターさん ヨロシク ! と言っているようなものです。



 最後に 実際に遭遇したソースのご紹介


--------------------------------------------------


 map.put("NAME","testman");


testMes1(map);


if(kubun == 1){

map.put("TEL1","0000-0000");

map.put("TEL2","0000-2222");

} else if(kubun == 2){

map.put("TEL1","0000-0000");

//  kubun == 2 は TEL2 イラナイんだー?

}


testMes2(map); // 実際 NAMEは無視してました。


if(kubun == 3){

map.remove("TEL1");

}


testMes3(map); // 今度は NAMEだけ使ってました っていうか String name って引数に変更しようよ


ひとつのMapオブジェクトを複数のメソッドで使いまわしてる・・・


  ・・・ 以下省略  


ごめん。レビュー とんずら したいんですが (心の叫び)・・・



やたらとマップをVO、DTO の代わりに使いまくると テストエンジニアが かわいそう

っていうか、うちの現場にもマッパーがいたかも・・・と思った方は ↓をクリック



人気ブログランキングへ

機会があれば↓の本の内容について書きたいと思います。

プログラムがわかり始めた頃のエンジニアさんにはオススメです。



バグ攻略で極めるWeb開発のツボ 現場で必要不可欠なバッドノウハウ/山城 拓明
¥2,940
Amazon.co.jp

俺流amazonの作り方―Amazon Webサービス最新活用テクニック/水野 貴明
¥2,730
Amazon.co.jp