2015/07/12 このエントリーをはてなブックマークに追加 はてなブックマーク - 神クラスにどう向き合うか考えてみる

神クラスにどう向き合うか考えてみる




最近、仕事で今見ているソースコードが
めっちゃHogeUtilとかFugaUtilとかだらけで、
ドメインのプレフィックス + Utilつけりゃなんでも良いのかよ…とか思って考えてます。

そんで、これはいわゆる神クラスというやつだなぁと。
そこに立ち向かうにはどうしたら良いのか、
(どうリファクタリングしたら良いのか、クラス設計したら良いのか)
みたいなことを考えてみます。











そもそも、神クラスってなんだってところから。
調べてみると、どうやら語源は
Object-Oriented Design Heuristicsという本らしいです。


Object-Oriented Design Heuristics
Object-Oriented Design Heuristics



参考URL
http://c2.com/cgi/wiki?GodClass


簡単な意味の理解としては、このWikipediaに書いてある神オブジェクト
とほぼ同じと思って良いでしょう。多分。


設計の一部分(クラス)に、過剰に機能を集中させること


(Wikipediaより引用


余談ですが、このWikipediaのアンチパターン集、結構眺めてると面白いですね。





JavaにおけるUtilとは多分、
「処理中にあふれた共通的な処理を集約しよう」
という意識の表れではあり、インスタンス化不可(privateコンストラクタ)の
staticメソッドのみを持つクラスです。


UtilはGoFのデザインパターンには分類されてないようですが、
Apache Commons由来で広く知られているクラスのパターンです。

参考URL
サルでもわかる 逆引きデザインパターン第4章 逆引きカタログユーティリティクラス




だがしかし、「よーし、お父さんUtilクラス作っちゃうぞー」となるのは
素直にGOサイン出せないというか。ちょっと待ちましょうか、一旦。と思います。



Utilは多分もっと明確なクラス定義が必要なんでしょうけど、それがされてないと思うので、
抽象的なクラスの責務に対して具象的なメソッドが生える場所になってしまいがちです。


また、共通的な処理メソッド置き場みたいになってしまうところを何度か
システム開発の中で見てきました。
クラスに対して実装者が一人ではなく、複数人(5〜6人とか)が付け足していく。
そうなると、クラスの完全性が伴わずチグハグなものになってしまいがちです。




そうなると、それはSOLIDじゃないな、と。
単一責任の原則は守らないと色々崩壊が始まります。



また、クラス名以上に様々なドメインというか色んな所と依存しあって
密結合になってしまうこともよくあります。


こういったことが起こりがちなのは、XXXUtilの他にもXXXHelperや
XXXManagerといったクラスがあります。




安易に作ってはいけないと思うのであって、絶対作るなという意見ではないです。

Utilクラスを作ることを検討するのは

・Apache Commonsにないか確認する
・状態を持たない処理に限定する
・特定の対象(クラス名に含む対象)に対しての操作のみ行う

場合とかじゃないかなぁと思います。
Apache Commonsに限った話ではなくて、
車輪の再発明の可能性も高いので色々注意が必要なとこだと思います。

日付操作、文字列操作、数値操作のみのUtilならまだ精神衛生上良いです。
個人的には。

型名Utilなら、その型のインスタンスを対象とした操作のみに集約されるので。





クラスの分割に際しては、やれるだけやっちゃった方が良いんじゃないかと思います。
というのも、クラスが小さくてガッカリする人よりも
クラスが大きくてガッカリする人の方が多いと思うから。


個人的には1クラスは300ステップぐらいが読みやすいです。
1kステップとかになってると、どっかクラス設計が悪いんじゃないかなと思っちゃいます。


分割の観点としては
・深いネスト
・長いメソッド
・多い引数

とかのリファクタリングから見ていきます。


そうすると意味のかたまりがなんとなく見えてきます。
Utilクラスにいるけど、本来はここにいるべきじゃないかな、とか見えてくるはず。
逆に言うと、デザインされていても良いようなクラスが
存在しないからUtilになってしまってると思います。




クラスの分割に際しては、この方のスライドとか僕の考え方に近いなーと思います。

オブジェクト指向できていますか? - Moriharu Ohzu(SlideShare)
というか、出典も明確でぼんやり考えてる程度の僕よりも全然立派なものなんですけどね笑


このプレゼン資料はThoughtWorksアンソロジーという本の規約を忠実に守る感じですね。
かなり規約でしばってる感じはします。

ThoughtWorksアンソロジー ―アジャイルとオブジェクト指向によるソフトウェアイノベーション
ThoughtWorksアンソロジー ―アジャイルとオブジェクト指向によるソフトウェアイノベーション









正しいデザインが出来れば、Utilの名前も変わってくるかもしれません。
実際の処理に対して抽象度の高すぎるUtil名(例えばHogeSystemUtilとか)は
そのユーティリティが何に対してのユーティリティか分かりません。


そういったリファクタリングからの再設計の検討で
業務ドメインに落とし込めるのではないかなぁと思います。

※汎用性の高い処理は抽象的な名前になるとは思うのですが。




Parser#parseとかNormalizer#normalizeとか最近は好きですね。
それだけしか俺はやらんぞって気持ちが溢れてる感じがします(厳密には違いますが)。





ということで、神クラスって何かってところから始まり、
神Utilにどう立ち向かうかを考えました。

で結論としては以下の様な感じです。


・Utilクラスは安易に作らないほうが良い
・作るとしても命名は気にしたほうが良い
・神Utilはリファクタリングから処理を分解して意味のかたまりにする
・意味のかたまりが増えてきたら新しいクラスを作るなどクラスデザインをもう一度考える


作らない方が良いとか、命名規約とかは実装段階での話で
そういう方向に実装が突き進んで行きそうな場合方向転換することで
新しい神様を誕生させるのは避けようという自戒というかアレです。

リファクタリングとクラスの再設計はもうすでにFatなUtilクラスが存在した場合の対処法。


ということで、僕のプロジェクトでは神はもうたくさんいるので
リファクタリングから始めようかなぁーと思います。。






0 件のコメント:

コメントを投稿

GA