この記事を読むのに必要な時間:およそ 1 分
良いクラス名
変数名やメソッド名と比べてクラス名は粒度が大きいため,適切で良いクラス名を付けることは重要です。良いクラス名は,名前だけで何を行うクラスかがわかります。
クラス名がうまく浮かばないときは,自分が作ろうとしているクラスの役割がちゃんと整理しきれていないことを疑ってください。1つのクラスに複数の責務を押し込んでいたり,役割があいまいだったりしていませんか? その場合,解決したい問題をじっくりと考えて,クラスを再設計する必要があるでしょう。「クラスの名前付け」=「設計」なのです。
クラス名のボキャブラリと設計能力
名前付けに関して,「自分が知らない表現・概念は,自分の中から(簡単には)生まれない」と思っています。より上位の表現をものにするには,いろいろなコードや書籍を読んだり,実際にコードを書いて試すことが重要です。その経験を通して,名前に関するボキャブラリが少しずつ増えていきます。図1は,「クラス名に対する成長の過程」を図式化したものです。
図1 習熟度別よく利用されるクラス名

※あくまで筆者の経験上の図なので,多少偏っているかもしれませんがご容赦ください。
①は駆け出しのころです。「*Bean」や「*Util」「*Action」などのクラス名は,プロジェクトで命名規則がありますので安心して書くことができます。背伸びをしてなんにでも「*Manager」という名前を付けて,マネージャだらけのコードにしてしまうのもこのころです。一方で,少し上の概念である「*Handler」や「*Adaptor」などは触れる機会も少なく,難しそうに思えるころでもあります。
オープンソースのコードを読んだり,デザインパターンなどを勉強するうちに,②の概念が理解できるようになってきます。特にGUIのアプリを書くと,このあたりの概念がGUIフレームワークに多く盛り込まれていますので,体で理解できるでしょう。
さらに難易度の高い設計を行ったりフレームワークを作成するようになると,③あたりの概念に興味が出てきます。
このように,クラス名のボキャブラリと設計能力は,車輪の両輪のように同時に高まっていくと思います。
Column Cubbyのクラス名の変遷
良いクラス名によって実際にコードの理解が進んだ例として,筆者が開発に関わるCubbyを紹介します。
CubbyはStrutsと同様のWebアプリケーションフレームワークです。特徴的な機能として,REST風のリクエストパスとアクションのメソッドを,アノテーションで簡単に結びつけることができるルーティングの機能があります。
public TodoAction extends Action {
private Integer id;
// パス「/todo/1」でアクセス可能。
// {id}の部分はフィールドidにセットされる
@Path("/todo/{id}");
public ActionResult index() {
...
}
}
表aに,Cubbyバージョン0.8.2とバージョン1.0.0のルーティング関連のクラス名をまとめました。バージョン0.8.2のころは,実際にCubbyを使ったアプリケーション開発をしてみたところ,名前が役割をきちんと表現できていなかったため,しっくりきませんでした。そこで,より良い名前を模索し,リファクタリングした結果がバージョン1.0.0のクラス名です。同時にクラスの分割も行いました。実際の責務に合った名前に変更したことで,より理解しやすく力強いコードになりました。
Cubbyは,一発で良い名前を付けることができなかった場合でも,考え続けリファクタリングすることで改善することができた良い例ではないかと思います。
表a Cubby 0.8.2と1.0.0でのクラス名
クラスの役割 | バージョン0.8.2のクラス名 | バージョン1.0.0のクラス名 |
ルーティングを行うServletFilter | UrlRewriteFilter | RequestRoutingFilter |
ルーティングを行うクラス | PathResolver | Router |
ルーティング情報 | RewriteInfo | Routing |
パスから対象のアクションを決定する | PathResolver | PathResolver |
内部遷移先のアクション情報 | ForwardInfo | InternalForwardInfo |