ユーティリティクラスの憂鬱
ユーティリティクラスみたいなのを作って、そこにクラスメソッドを集めるのはよくあることだと思いつつ、悩ましいコードを眺める。
利便性のためにユーティリティクラスを作るという趣旨はわかるんだけど、クラスメソッドにすると安易にどこからでもアクセスしやすい状況ができてしまう。ユーティリティクラスにはいろんな機能が追加され、どんどん巨大化する。巨大化したユーティリティクラスのクラスメソッドは、プログラム全体のあちこちから呼び出されることになる。
で、そうやってできたプログラムをリファクタリングしようとしているところ。
ユーティリティクラスに突っ込まれたメソッドを眺めると、機能的にも異なるカテゴリのものが集まってるので、本来はいくつかのクラスに分割すべきだと気付く。さらに整理してみると、本来はそれなりにインスタンスがあって、そのインスタンスメソッドとして提供した方が、設計上もうまくいくことが分かる。
で、そこらへんをリファクタリングするには、かなり手間がかかるということに気付いた。
というのは、クラスメソッドのアクセス容易性にかき消されて、本来はそこに存在しているべき依存関係が存在していないのである。ユーティリティクラスを作ってしまうと、そこはオブジェクト指向じゃなくなりつつあると思ったほうがいいのかもしれない。
ユーティリティクラスを作るとすると、どのような場合が適切なのか考えてみる。
プログラムは、通常はいくつかのパッケージに分割されているはず。それに関しては、かなり前に書いた記憶があるんだけど見つけきらん。orz
それっぽいのは見つけたけど、これとは違うのを書いた記憶があるんだけど。。。
≫http://d.hatena.ne.jp/satoshis/20040526/p1
話しがそれた。
ユーティリティクラスは、パッケージを分割したときに、パッケージ内のどのクラスにも含めることができないけど、パッケージ内部で頻繁に使われるような共通の処理をまとめるような場合に限って作るべきじゃないかと思う。そして、そのユーティリティクラスは、新たに別のパッケージに対する依存を持ち込まないように注意しなければいけない(もともと存在する依存はOK)。
クラス名も、パッケージ名が hoge なら、HogeUtilities みたいなクラス名にしてやるのが最低限。単に Util なんてクラス名で作ってしまうと、「とりあえずそこに入れてしまえ!」みたいに安直に追加してしまう危険性がある。でも、HogeUtilities なら hoge パッケージとは無関係のメソッドは追加すべきではないとの判断できる可能性が高くなる。
プログラムのメイン部分にあたるパッケージに、Util みたいな名前のクラスがある場合は要注意だ。