クラスの命名のアンチパターン

  • 2057
    いいね
  • 15
    コメント

昔から「名は体を表す」と言ひます。クラスの名前がクラスの果たす役割と一致してゐるかどうか常に考へ続けませう。

ImageInfo, AccountData, etc.

Info って何やねん? Data って何やねん? ImageInfo って Image とはどう違ふねん??

FooInfo や FooData よりも好ましいかもしれない名前の例:

  • FooAttribute, FooProperty, FooMetadata, FooDescription
  • FooConfiguration, FooSetting, FooParameter
  • FooResult, FooStatistics, FooSummary
  • FooBuffer, FooList, FooCollection, ...

ProductListItem, TranslationTableEntry, etc.

ProductListItem って要するにただの Product やろ?

ProductList を先に作ってから「項目を表すクラスも作らないとなー」とかやるとこの様な残念な名前のクラスを作りがちです。

といっても、リストとは関係の無い独立した Product と、リストの項目として付加的な (自分が何番目の項目なのかみたいな) 情報を持つ ProductListItem の様に、両立する場面もあり得ます。

Wrapper, Adapter, Proxy, etc.

手段と目的を履き違へるべからず。「ラッパーであること」や「プロクシであること」は何か他の目的を実現するための手段に過ぎないはず。

  • 可変配列をラップして不変配列に見せかけたい: ArrayWrapper → ImmutableArray
  • Cloneable インタフェースを実装してゐない Point クラスをラップしてクローン可能に見せかけたい: PointAdapter → CloneablePoint
  • 別プロセスにある Database を操作するためのプロセス間通信処理などをプロクシパターンの中に閉ぢ込めたい DatabaseProxy → RemoteDatabase

Helper, Utility, ...

Java の様に、クラスの外に直接関数を定義することができない言語では、関数を定義するためのプレースホルダーとしてクラスが必要になることもあります。Helper や Utility といった名前はその様な「静的メソッドしかないクラス」「インスタンス化する意味がないクラス」にだけ使ふ様にしませう。

もしそのクラスをインスタンス化することに意味があるのなら、そのクラスのインスタンスは何らかのモノを表してゐることになります。そのモノに基づいた具体的な名前を考へませう。(上の Wrapper, Adapter, Proxy, etc. も参照)

静的メソッドしかないクラスだからといって必ずしもクラス名に Helper や Utility を入れないといけないわけではありません。例へば Java や C# で sin や cos などの数学関数が置かれてゐるクラスは Math と名付けられてゐます。

Settings, Utilities, Contents, ...

クラス名は単数形にしませう。 → SettingGroup, Utility, Content

複数形のクラス名だと変数の名前がややこしいことになります:

  • 単体の Image → image
  • Image の配列 → images
  • 単体の Settings → settings
  • Settings の配列 → ???

DownloadManager, AnimationController, JobProcessor, etc.

Manager とか Controller の様な名前を持つクラスを作ると、「ダウンロードに関するコードは全部 DownloadManager クラスの中に書いとけばええんや!」となってどんどんクラスは膨れ上がり、新たなが誕生することとなります。

単一責任則に従ってクラスを分割し各クラスが明確な役割を持つ様にすると、具体的で分かりやすい名前を付けることが出来ます。

コツ:

  • 役割を「それがどんな処理をするか」といふ動詞よりは、「それが表してゐるモノ (中に持ってゐる情報) は何か」といふ名詞で考へる
  • 集合やイテレータなどの基本的なデータ構造・デザインパターンに帰着させる

DownloadManager の改名案

  • 実行すべき複数のダウンロードの順番を覚えておきたい → DownloadQueue
  • 同時に複数のダウンロードを実行すると回線を圧迫するので、ダウンロード数を制限したい → ダウンロードの量を制御する「調整弁」なので DownloadThrottle
  • ダウンロードが実行されるタイミングを調整したい → DownloadSchedule(r)
  • ファイルを一つダウンロードする度に Download クラスのインスタンスを一つ作る様になってゐる。同じファイルを何度もダウンロードするのは無駄なので、重複する Download のインスタンスを作らない様にしたい。DownloadManager の中でたくさんの Download のインスタンスをまとめて管理すればいいと思った。 → 「重複のない Download の集まり」なので、 DownloadSet

AnimationController の改名案

  • 絵が動いて見える様に、時間経過とともに絵の位置を変更したり絵を切り替へたりしたい → このクラスの役割はアニメーションをコントロールすると言ふよりもアニメーションそのものなので、 Animation (または Animator)。
  • 状況に応じて複数のアニメーションを切り替へたい → AnimationSwitcher または AnimationSelector1
  • いくつかのアニメーションが続けざまに実行される様にしたい → AnimationSequence または SequentialAnimation

  • 商品をデータベースに永続化したり検索したりする処理をまとめてカプセル化したい → ProductRepository (ドメイン駆動設計のリポジトリパターン)
  • 不要になった Foo を溜めておいて使ひ回したい → FooPool, FooBucket, FooCache

Type & Kind

状態や種類を表すオブジェクトや enum の型に ErrorType とか AnimationKind とか名付けたくなってしまったとき。

  1. "Type" や "Kind" を取っても意味が通じないか検討する。
    • DownloadMethodType → DownloadMethod
  2. "Type" や "Kind" をより具体化する。何の種類を表してゐるのか考へる。
    • Low/middle/high や small/medium/large の様に段階的な数量を表すもの → Level, Stage, Degree, Grade, Rank
    • 数量的でない、大雑把な分類 → Category, Group
    • 動作ややり方の種類 → Method, Mode, Protocol, Strategy, Pattern
    • エラーの原因 → ErrorCause, ErrorReason

  1. 例として「動詞+er/or」の形をした名詞をいくつか挙げましたが、これもあまり良いパターンではありません。オブジェクトが持つ内部状態に即した命名がより好ましいですが、そのためにはオブジェクトの仕様をより深く吟味する必要があるので、ここでは割愛します。