現象
クラス名の最後に、やたらManagerやController、Handler、Supervisorといった名詞が加わっている。
状況
で?このUserAuthorityManagerの役割はなんだって?
え?UserのAuthorityプロパティを見て、その値から判断してアクセスできるデータを選別してるんだって?
なんでそのAuthority自身が主体的に動いてないのさ?え?Authorityはintだって??
で、このUserManagerは?
え?Userを生成するときの構成を管理したり?Userが画面に遷移可能か管理したり?あとUserへのサービス構成の管理もやってるんだって??
…それ、ちゃんとクラス設計してる?
解説
まあ、上記の状況は極端すぎるとして。
HogehogeManager(いくつか名前があるので、代表でManagerを使う)、じつにお手軽で付けやすい名前なので、ついつい使いがちだ。そして雑多な「関連しそうなメソッド」は、すべてこのManagerクラスが吸収していくようになる。
しかし、こういった名前が付くクラスは大概の場合において「クラス分析が十分行なわれていない」代償として表面化する場合が多い。たいていの場合は「別の何か」の代弁者になっている。じっくりクラス関係を眺め、よーく考えてみよう。
業務用システムなんかでこの手のクラスが頻繁に出てくる場合は、たいていデータ分析・正規化が不十分にしか行なわれていないという状況が多い。
このクラス名、本当にそういった名前が相応しい場合もある。よーく考えて結局「どうしても必要」と判断せざるをえない場合も(とくにフレームワークやユーティリティ周りなどで)ある。
対策
JavaやC++等でのプリミティブ型や一項目(プロパティ)に対して、項目名を司るようなManagerクラスが出てきた場合
- たいていの場合はクラス分割が足りていない。Manager部分を取ったクラスを作り、対象のプリミティブ型をそのクラスに置き換えてみよう。
- データベースのテーブル内のいち項目であるプリミティブ型の場合、データ分析・正規化段階でテーブルが丸ごと抜けている可能性がある。その「ロジック」、じつは「データ関連」で十分表現可能かも知れないよ。
一項目ではなく、他のクラスに対してこれをコントロールするManagerクラスが出てきた場合
- 対象となっているクラスにメソッドを移してみよう。まずたいていの場合はこれで上手くいく。
- それでも若干のメソッドは違和感があるかもしれない。その場合、対象となるクラスを本当に管理しているクラス(部分と全体の関係にある−よく言う、タイヤクラスに対応する車クラスのような)にメソッドを移すべきかもしれない。
- それもまた苦しい若干のメソッドは、じつは親クラスにあるべきメソッドなのかも。
- 可能性は低いが、メソッドによっては横関連しているクラスに移すときれいに収まる場合もある。
それでも対処不可能な場合もある。あきらかにメソッドを移そうとしているクラスが機能過多になったり、そのクラスに移すと越権行為メソッドになってしまう場合がそれだ。その場合はさらに次の分析を試みる。
- オブジェクト生成に関わるメソッドは「XxxBuilder」や「XxxFactory」といった名前のクラスにまとめる。
- オブジェクトの生存、委譲や遷移等に関わるメソッドならば、よりその役割に相応しいクラス名のクラスにまとめる。
これはできあえのクラス(標準ライブラリや「他開発チームの管理下にあって手出しできない」等)に対する操作の場合も有効だ。
以上のようにメソッドをその役割を見極めてきちんと整理していくと、自然とManagerクラスは消滅するはずだ。
うまくクラスがまとまらない場合、デザインパターンを意識してみると、すんなりとうまくクラス構成がはまる事が多い。
とにかく、クラスの役割をシンプルにまとめる事が基本だ。