英語の文章のようにプログラミングをする方法についてのまとめです。

はじめに書いておくと、今回の記事の元ネタは以下の2つです。

メソッド名と引数は文法にこだわるべし

まずは、オブジェクト指向と英語の5文型との関係性について。

S(Subject主語)はオブジェクト、V(Verb動詞)はメソッドに対応する。

第1文型 S + V

第一文型は、S+V。 誰・何は、どうする、SはVする。

Vには、自動詞が使われる。主語と動詞で文が完結する。

go、wait、start、listen、work, begin, come

class S
  def V
    #
  end
end

第一文型の動詞には、前置詞+名詞の形をした副詞句が続くことが多い。

よって、より英語っぽくコーディングするには、

前置詞をメソッド名に、名詞を第一引数にするべし。

def go_to(place)
  #
end

def wait_for(girlfriend)
  #
end

def live_in(town)
  #
end

第2文型 S + V + C

第2文型は、S+V+C。 誰・何は、なんだ。S=Cの関係がなりたつもの。

形容詞と名詞がCになる。Vには、大抵be動詞がくる。

class S
  def V(C)
    #
  end
end

しかし、be動詞をメソッドにするには具体性がない。

be動詞以外で動詞にくる名詞を以下に列挙。

よって、より英語っぽくコーディングするには、

第一引数に状態を入れるべし。

第3文型 S + V + O

第3文型は、S+V+O。SはOをVする。Vは他動詞。Oは目的語。

Objective、Objectiveですよ!Objective!大事なことは3回書きます。

つまり、Oはオブジェクトがくる。オブジェクト指向万歳。

class S
  def V(O)
    #
  end
end

よって、より英語っぽくコーディングするには、

オブジェクトか名詞を引数にするべし。

class Bob
  def study(@ruby)
  end
  
  def read(aBook)
  end
end

しかし、Oにくるものはなにも名詞ばかりでない。

不定詞(to xxx)、動名詞(xxxing)、名詞句、名詞節もOとなり得る。 このケースはメソッドの引数とするにはすこし難しいな。

第4文型 S + V + O + O

第4文型は、S+V+O(人)+O(物)。Sは

ボイントは1つめのOは人、2つめは物。

give, show, send, buy

人というのは、モジュールに置き換えるのがよい。

xxxManager, xxxListener, xxxController, xxxObserver..etc.

オブジェクト間のやりとりでつかえる。

class Bob
  def send(@Manager, @message)
  end
  
  def give(@girlfriend, @present)
  end
end

よって、より英語っぽくコーディングするには、

第一引数をやりとり先のオブジェクト、第二引数をデータにするべし。 英語を意識するならば、順番にこだわるべし。

ちなみに、第三文型と第四文型は、変換可能。

Tom shows hoge to him. / Tom shows him hoge.

前置詞がともなうと引数の形にしずらいので、 第4文型として引数を2つとるほうが英語っぽい。

第5文型 S + V + O + C

第5文型は、「S+V+O+C」(主語+動詞+目的語+補語)。O = Cの関係がなりたつ。

第ニ文型との対比に注意。第二文型はS=Cだが、5はO=Cの関係。

Oには、オブジェクトがくる。Cには状態がくる。 Sオブジェクトの指示でOの状態を変化させる。

make, call, appoint, drive, find, keep, turn, notice,

こうやって、動詞をならべてみると、実際に利用できそうなものはあまりないな。

メンタルマッピングを避けるべし

メンタルマッピングとは、あたまの中での対応付け。 コードの中で、変数名はなにかを略されることがおおい。

cntl -> controller, mgr -> manager, sn -> serial number

しかし、略すと英語として読み取れなくなる。よって、メンタルマッピングには反対だ。

コメントを書く代わりにメソッドの抽出をするべし

コメントはコードを雑然させる。そして、度々間違っている。

こんなときはコメントを書く代わりに、その部分を戻り値なしのメソッドに抽出する。

たとえば、

for (int i=0; i < 9; i++) {
  for( int j=i+1; i < 10 ; j++)
     if( a[i] < a[j] ) {
        swap(i, j);
     }
  }
}

これはこうリファクタリングする。

void sort(Data *a) {
  for (int i=0; i < 9; i++) {
    for( int j=i+1; i < 10 ; j++)
      if( a[i] < a[j] ) {
        swap(i, j);
      }
    }
  }
}

メソッド名を文章にすることで、コードが文章に近づくのだ。素晴らしいテクニック。

if, else, while文は一行で書くべし

if, else, whileを一文で書くことで、より英語の文章に近づく。

if(isdangerous()) stopApplication() else restartAplication();

この際、条件式もメソッドに抽出する。

javaでは is(条件)、rubyでは(条件)?というスタイルが好まれる。

説明的変数を導入すべし

説明的変数を導入すると、可読性が上がる。

ぐちゃぐちゃした論理は説明的変数またはメソッド抽出でわかりやすい文章に変える。

bool isSuccess = () & () && () || ()

ここでも、if文を一行にまとめるという規則と合わせると、より文章らしくなる。

if (isSuccess()) startMusicAndSingingASong();

まとめ

英語のようにコーディングするにあたって、最大の関心事が、「実行速度」だ。

メソッドを細かくすると、それだけ遅くなるのではないか?

大丈夫、コンパイラは進化しているので、細かいメソッド分割はコンパイラによって最適化される。詳しくは以下参照。

本当にコンパイラを信じていいの?迷信ではないか?

いや、実のところ、自分でも不安だ。どこかに書いてあったことをそのまま信じてだけだ。自信がない。

じゃあ、ということで、コンパイラについて勉強してみよう。今日から始まる courseraの コンパイラの講義に挑戦だ!