17 Mar 2014, 12:20

How to write a code like English(英文のようにプログラミングをする方法)

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

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

[toc]

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

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

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

第1文型 S + V

<div class="outline-text-3" id="text-1-1">
  <p>
    第一文型は、S+V。 誰・何は、どうする、SはVする。
  </p>

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

  <p>
    go、wait、start、listen、work, begin, come
  </p>

  <div class="org-src-container">
    <pre class="src src-ruby"><span style="color: #f92672; font-weight: bold;">class</span> <span style="color: #66d9ef; font-weight: bold;">S</span> 

def V # 自動詞 end end

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

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

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

  <div class="org-src-container">
    <pre class="src src-ruby"><span style="color: #f92672; font-weight: bold;">class</span> <span style="color: #66d9ef; font-weight: bold;">Bob</span>

def go_to(place) end

def wait_for(girlfriend) end

def live_in(town) end end

第2文型 S + V + C

<div class="outline-text-3" id="text-1-2">
  <p>
    第2文型は、S+V+C。 誰・何は、なんだ。S=Cの関係がなりたつもの。
  </p>

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

  <div class="org-src-container">
    <pre class="src src-ruby"><span style="color: #f92672; font-weight: bold;">class</span> <span style="color: #66d9ef; font-weight: bold;">S</span> 

def V(C) # be動詞 + 形容詞 end end

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

  <p>
    be動詞以外で動詞にくる名詞を以下に列挙。
  </p>

  <ul class="org-ul">
    <li>
      状態系 be, look, seem, keep, remain
    </li>
    <li>
      変化系 become、get, turn, go
    </li>
    <li>
      感覚系 feel、sound、
    </li>
    <li>
      <a href="http://www.elm-lab.com/CCP040.html">第2文型をとる動詞</a>
    </li>
  </ul>

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

  <p>
    第一引数に状態を入れるべし。
  </p></p>
</div></p>

第3文型 S + V + O

<div class="outline-text-3" id="text-1-3">
  <p>
    第3文型は、S+V+O。SはOをVする。Vは他動詞。Oは目的語。
  </p>

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

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

  <div class="org-src-container">
    <pre class="src src-ruby"><span style="color: #f92672; font-weight: bold;">class</span> <span style="color: #66d9ef; font-weight: bold;">S</span> 

def V(O) # 他動詞 + オブジェクト end end

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

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

  <div class="org-src-container">
    <pre class="src src-ruby"><span style="color: #f92672; font-weight: bold;">class</span> <span style="color: #66d9ef; font-weight: bold;">Bob</span>

def study(@ruby) end

def read(aBook) end end

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

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

第4文型 S + V + O + O

<div class="outline-text-3" id="text-1-4">
  <p>
    第4文型は、S+V+O(人)+O(物)。Sは
  </p>

  <p>
    ボイントは1つめのOは人、2つめは物。
  </p>

  <p>
    give, show, send, buy
  </p>

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

  <p>
    xxxManager, xxxListener, xxxController, xxxObserver&#x2026;.etc.
  </p>

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

  <div class="org-src-container">
    <pre class="src src-ruby"><span style="color: #f92672; font-weight: bold;">class</span> <span style="color: #66d9ef; font-weight: bold;">Bob</span>

def send(@Manager, @message) end

def give(@girlfriend, @present) end end

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

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

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

  <p>
    Tom shows hoge to him. / Tom shows him hoge.
  </p>

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

第5文型 S + V + O + C

<div class="outline-text-3" id="text-1-5">
  <p>
    第5文型は、「S+V+O+C」(主語+動詞+目的語+補語)。O = Cの関係がなりたつ。
  </p>

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

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

  <p>
    make, call, appoint, drive, find, keep, turn, notice,
  </p>

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

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

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

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);
     }
  }
}

<p>
  これはこうリファクタリングする。
</p>

<div class="org-src-container">
  <pre class="src src-C++"><span style="color: #66d9ef; font-weight: bold;">void</span> <span style="color: #a6e22e;">sort</span>(<span style="color: #66d9ef; font-weight: bold;">Data</span> *<span style="color: #fd971f;">a</span>) {

// ソートする。 for(int i=0; i < 9; i++) { for( int j=i+1 i < 10 ; j++) if( a[i] > a[j] ) { swap(i, j); } } }

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

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

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

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

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

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

説明的変数を導入すべし

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

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

bool isSuccess = (条件1) && (条件2) && (条件3) || (条件4)

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

<div class="org-src-container">
  <pre class="src src-C++"><span style="color: #f92672; font-weight: bold;">if</span> (isSuccess())

startMusicAndSingingASong();

まとめ

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

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

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

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

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

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