kagamihogeの日記

kagamihogeの日記です。

出力パラメータはやっぱ良くないんだろうなぁ

出力パラメータというのは、例えばこんな感じ。


public void setHogeList(List list, Hoge hoge) {
list.add(hoge);
}
2007/08/23 追記 ソースコードの間違いを修正


引数で渡されたオブジェクトが、メソッド中で状態変更されるよーなコード。C 言語なんかではポインタ使うしかないんで、C ではしょっちゅう見かけるタイプのコード。

このテの「メソッド呼んだら引数で渡した変数の状態が変わる」ってコードは案外追うのが厄介だったりする。とはいえ、リリースされてしまったコードに悪態ついても詮無きこと。しがないサラリーマンプログラマーである身としては、ただひたすらバグの原因を追求・解析・修正するしかない。


というわけで今回の失敗談。

まず、こんな感じのメソッドがある。UserInput てのはユーザが入力した何らかのデータで、それを Config という何らかの設定情報を統括するオブジェクトに追加する、というイメージ。やっぱ文脈伏せると説明がしにくいなぁ・・・


public static void setConfig_Hoge(Config config, UserInput input) {
config.add(input);
}

この config に input を set するメソッドは 3 種類ほどあり、3 つ並べて使用されていた。


ConfigNantoka.setConfig_Hoge(config, input);
ConfigNantoka.setConfig_Are(config, input);
ConfigNantoka.setConfig_Sore(config, input);

こんな感じ。

んで、この 3 つのメソッド読んだあとの config の状態がおかしかった。Hoge,Are,Sore で追加されているハズの情報が欠落する。それぞれのメソッドをざっと見た感じでは単に config.add(input) してるだけなので、漏れが出るってのはイマイチ腑に落ちなかったのだが・・・ふと、メソッドを呼ぶ順番を入れ替えたらどうなるか?と思ったのでやってみた。


ConfigNantoka.setConfig_Are(config, input);
ConfigNantoka.setConfig_Hoge(config, input);
ConfigNantoka.setConfig_Sore(config, input);

すると、追加されていてほしい情報がちゃんと反映されている。どうやら Hoge,Are,Sore の間には暗黙の呼び出し順序がある模様。一番初めに呼ぶ必要があるらしい setConfig_Are を丹念に追う事にする。


public static void setConfig_Are(Config config, UserInput input) {
....
config.clear();
....
config.add(input);
}

メソッド名に set とか付いてるクセに clear するって。「わかるかボケ!」とつい口に出してしまった俺は悪くない・・・よね?

setConfig_Are の責務は 2 つあり、config の初期化と Are な設定追加だった。2 画面以上スクロールするからって最初にテキトーに流し読みしたのが敗因だったか・・・。

おそらく、コレを書いた人物は「setConfig_Are は最初に呼ぶべし」という俺ルール全開で書いたのだろう*1。初期化処理を別にくくり出すのがメンドくなって混ぜこぜにしたんだろう、多分。


そんなわけで。「メソッド呼んだら引数で渡した変数の状態が変わる」ってコードは本質的に読み辛さを抱えてるのかもなぁ・・・と思ったのでした。

*1:メソッド間に呼び出し順序が出てくる自体は、まぁ良いかなと。グチャグチャになったら facade 設けて逃げればいいし