kなんとかの日記 このページをアンテナに追加

2008-07-10

クラス設計の常識に反して、クラス名を動詞に、メソッド名を名詞にする

| 22:05 |  クラス設計の常識に反して、クラス名を動詞に、メソッド名を名詞にする - kなんとかの日記 を含むブックマーク

クラスを作るとき、ふつうはクラス名を名詞に、メソッド名を動詞にする。

class FileLoader {     // クラス名は名詞
  def load(name) {     // メソッド名は動詞
    ...
  }
}

しかし PHPフレームワーク CodeIgniter では、一部のクラスでこれが逆になっている。つまり、クラス名が動詞で、メソッド名が名詞なのだ。

class Load {
  function model($name) { ... }
  function helper($name) { ... }
  function library($name) { ... }
}

CodeIgniter では、このクラスのインスタンスが、クラス名と同じ名前で $this に設定される。そのため、実際使うときはこんな感じ。

$this->load->model('User');        // モデルをロード
$this->load->helper('Ajax');       // ヘルパーをロード
$this->load->library('Session');   // ライブラリをロード

こうしてみると、英語として自然だ。少なくとも、$this->modelLoader->load('User') なんかよりはずっといい。

もちろん CodeIgniter 以外で使うなら、クラス名は名詞である必要はなく、インスタンスを入れる変数が名詞であればいいだけなんだが、それでもこの命名方法は面白い。

どんな場合にこの命名方法がハマるだろうかと考えたが、クラス名が「名詞+動詞+er」の形になっているときがそうなのかなと思う。

## 従来の命名方法
class MusicPlayer {   # 名詞(Music) + 動詞(Play) + er
  def play(...) {     # 動詞
    ...
  }
}

player = MusicPlayer()
player.play(...)      # 主語.動詞(..目的語..)

## CodeIgniter 式の命名方法
class Play {          # 動詞
  def music() {       # 名詞
    ...
  }
}

play = MusicPlay.new(...)
play.music()          # 動詞.目的語

あれ、主語がないよ?


こうしてみると、今までの命名方法は「クラス名を名詞に、メソッド名を動詞に」していたわけじゃなくて、「クラス名を主語に、メソッド名を動詞に」していたわけか。

そして、CodeIgniter 方式は「クラス名を動詞に、メソッド名を名詞に」したわけじゃなくて、「クラス名を動詞に、メソッド名を目的語に」したといえる。


あと、この命名方法だと多態(polymorphism)は使えないな。結局は、普通の手続き型言語と変わらないことになりそう。

## 例えばこんなのは
class Player {
  def play();    // abstract method
}
class MusicPlayer extends Player {
  def play() { ... play music ... }
}
class GamePlayer extends Player {
  def play() { ... play game ... }
}

## CodeIgnier 方式では使いにくい
class Play {
  def music() { ... play music ... }
  def game() { ... play game ... }
}

やっぱり、OOP言語で手続き型をしたいときにはハマりそう。でもそれって、設計が間違っていることなんじゃね?

うーむ。