アメリカのPivotal Labs, Incで働いている西嶋悠貴です。
日本人エンジニアにとって、苦手意識のある英語。本エントリでは、英文法とプログラミングの関係をやさしく紐解きます。今回は、英語の文法とクラス/メソッド名、命名規則について深く掘り下げてみます。
正しい英語を使うことでGitHubなどで海外エンジニアとのコミュニケーションも円滑になりましたし、実際、筆者はGitHubが縁でアメリカの会社に採用されました。本記事では、その影響の一部を紹介することで少しでも読者の方々のプログラミングの助けになればと思っています。
■ 目次 ■
1.プログラミング英語はシンプルでも問題ない
2.自動詞と他動詞の違いを理解しておくことが一番大事
2-1.そもそも自動詞・他動詞って?
2-2.自動詞・他動詞と命名規則との関係
2-3.自動詞・他動詞の単語に要注意!
3.自動詞をとるメソッド
3-1.第1文型はオブジェクト自身のみで実行可能なメソッドに使う
コラム.第1文型のメソッドに必須な引数を持たせる
3-2.第2文型は文字列オブジェクトやstaticな数値をとる
コラム.前置詞はイメージでとらえよう
4.他動詞をとるメソッド
4-1.第3文型はオブジェクトを指し示す
4-2.第4文型はオブジェクトのやりとりに使う
4-3.第5文型はオブジェクトの状態を変更したい場合に使う
5.肯定文も疑問文になる?
5-1.Boolean型を返すメソッド
コラム.不要な接頭語のisを使わないようにしよう
6.属性(attributes)の表現
6-1.名詞+名詞の表現
6-2.メソッド名に前置詞を使う表現
まとめ.常に英文を意識したコードにしなくてはならないか?
1.プログラミング英語はシンプルでも問題ない
プログラミング言語の表現は自然言語が基になっています。そのため、基となった自然言語の理解は必要不可欠です。
英語の文法って難しい、と思っている人も多いかもしれませんが、基本的に
プログラミングに使われる英文はシンプルな表現であることがほとんどです。wouldやmay、mightといった助動詞がコードの中に出てくることはまれですし、時制(過去形、現在完了形など)も強く意識する必要はありません。むしろ、複雑な英文表現を無理矢理コードで表現しようとすると、ほかのエンジニアがあとから読むときの障害となる可能性もあるため、シンプルな英文しか作れないことは
まったく問題になりません。
2.自動詞と他動詞の違いを理解しておくことが一番大事
みなさんはわからない英単語があった場合、辞書で意味を引くと思います。辞書は日本語と英語の意味をハッシュテーブルのようにまとめたものです。多くの場合は意味を調べるために使いますが、時として
意味を引くだけでは十分でないことがあります。次の英文の意味を考えてみてください。
He ran a coffee shop.
「彼はコーヒーショップを経営していた」
He ran to a coffee shop.
「彼はコーヒーショップへ走った」
ただ単にtoがあるかないかの違いですが、意味は大きく異なってしまいます。なぜこのような違いがあるのか?それは、runという単語に自動詞と他動詞両方の性質があるためです。
自動詞・他動詞の使い分けを知らないと、このように間違った読解につながってしまいます。ですから、辞書を引くときには、その動詞が自動詞として使われているか、あるいは他動詞であるかを考えなければなりません。
2-1.そもそも自動詞・他動詞って?
ところで、そもそも、自動詞や他動詞とはいったい何なのでしょうか? 英文法では、自動詞は主語(Subject)と動詞(Verb)によって英文が成り立ち、必要に応じて補語(Complement)をとる動詞を差します。一方、他動詞は主語(Subject)と動詞(Verb)の他に必ず目的語(Object)を必要とする動詞を差します。このような要素から、全ての英文は以下の5文型のいずれかに分類することができます。
Subject + Verb
- 第2文型 Subject + Verb + Complement
- 第3文型 Subject + Verb + Object
- 第4文型 Subject + Verb + Object + Object
- 第5文型 Subject + Verb + Object + Complement
なんだか学生のころに学んだ用語がたくさん出てきて難しくなってきました。
まず、主語にはプログラミング上のクラス、あるいはインスタンス化されたオブジェクトが当てはまります。英文法上の目的語は、プログラミング上でのオブジェクトと読み替えて問題ありません。補語には基本的に実体がなく、インスタンス化されたオブジェクトであることはあまりありません。Javaでは primitive で constant な値として、Rubyではシンボルで表現されることが多いです。動詞はもちろん、メソッド名となります。つまり、自動詞は1つのオブジェクトのみで処理が完結する動詞を指し、他動詞は処理を実行する1つのオブジェクトと、引数として与えられる他のオブジェクトを1つか2つ必要とする動詞を差します。
自動詞と他動詞の違い
2-2.自動詞・他動詞と命名規則との関係
では、自動詞と他動詞の違いがどのようにプログラミングの命名規則と関連してくるでしょうか? たとえば、先ほどの例と同じ考え方で、「Personクラスのオブジェクトである@personがコーヒーショップへ走っているか」を知りたいメソッドをRubyで次のように設計したとします。
Class Person
def running?(to)
# 実際の処理……
end
end
このメソッドを実際に使う際は、次のように使います。
@person.running?(@coffee_shop)
これは、一見すると正しい設計に見えます。しかし、このコードから連想される英文は、
Is the person running the coffee shop?
であり、
Is the person running to the coffee shop?
ではないのです。つまり、この設計だと、あとからこのコードを読んだ人は、「@personオブジェクトが @coffee_shopを切り盛りしているかを知ろうとしている」と解釈してしまいます。これでは、このコードを読んだほかのエンジニアを困惑させてしまいます。正しい意図を伝えるためには、次のような設計が良いと考えられます。
class Person
def running_to?(place)
# 実際の判定処理……
end
def running?(args = {})
place = args[:to]
running_to?(place)
end
end
この設計であれば、コードは、
@person.running?(to: @coffee_shop)
あるいは、
@person.running_to?(@coffee_shop)
のようになり、文法的に正しい英文を連想させることができます。
2-3.自動詞・他動詞の単語に要注意!
今回のように、実際のアプリケーションの中でRunという名前のメソッドを実装することがあるかと問われると、あまりその頻度は高くないかもしれません。しかし、Runという動詞のように、自動詞と他動詞の性質を併せ持つ動詞は多数存在します。
オブジェクト指向言語で開発される場合、ソフトウェアの中には多数のクラスやメソッドが存在することになりますから、同様の設計ミスがあっても不思議ではありません。
これまでは辞書を引くとき、意味だけを調べるだけだったかもしれません。ですが、これからは、調べている単語が自動詞なのか、他動詞なのか、しっかりと目を通しましょう。それは、時としてコードに大きな影響を与えます。どうしたら意味が解釈しやすいコードになるかを考えながら辞書を引くようにしましょう。
3.自動詞をとるメソッド
3-1.第1文型はオブジェクト自身のみで実行可能なメソッドに使う
第1文型(S + V)は
オブジェクト自身のみで実行が可能なメソッドを実装する際の名前として利用します。Rubyでは、次のような構成をとります。
class Subject
def verb
# 実際の処理
end
end
第1文型がよく使われる例としては、次のようなものがあります。
- xxxConverterやxxxEncoderに実装された#runメソッド
- バックグラウンドで動作するWorkerクラスに実装された#waitメソッド
- File型のオブジェクトの#closeメソッド
コンバータやエンコーダに実装された#runメソッドは、変換やエンコードを実際に行う処理を含みます。対象となる元のデータはコンストラクタで与えられることがほとんどで、#runメソッド自体が必須な引数を取ることは珍しいでしょう。File型のオブジェクトは一般的に、使い終わったら#closeメソッドをコールしなくてはいけませんが、これもよく見られる第1文型の例です。
たとえば、Workerクラスのオブジェクトである@workerを、ジョブ待ちの状態にする#waitメソッドを、次のようにWorkerのクラスメソッドとして実装したとします。
@worker = Worker.new
# ワーカーをジョブ待ちの状態にする
Worker.wait(@worker)
一見正しそうですが、このコードでは「Workerクラスが@workerを待つ」という表現になってしまいます。また、Waitには「遅らせる」という意味もありますが、「遅らせる」という意味で使うためには目的語として時間をとらなくてはなりません。この処理を英文法的に正しく実装するならば、
@worker = Worker.new
# ワーカーをジョブ待ちの状態にする
@worker.wait
としなければなりません。
コラム.第1文型のメソッドに必須な引数を持たせる
第1文型をとるメソッドが引数を取らないといっても、実際には引数を取りたくなる状況がしばしばあります。GoやLiveは、第1文型として最もよく使われる単語であると言えます。ですが、多くの場合、次のように場所を示す前置詞句とともに使われます。
He will go to Shibuya today.
Does he live in the united states?
このような英文をコードで表現したいときは、前置詞とセットでメソッドを定義しましょう。たとえば、上記の例をコードに直すと、
# The person will go to Shibuya.
@person.go_to(place)
# He lives in the united states?
@person.lives_in?("United States")
のようになります。#go_toメソッドはWillに続く動詞であるため、三単現のsは付きません。#lives_in?メソッドは、肯定文を質問文として解釈しているため、Livesとしています。真偽を返すメソッドの命名方法に関しては、後述の「Boolean型を返すメソッド」をご覧下さい。
また、英語では基本的に前置詞のあとには名詞がくるものと考えて問題ありません。前置詞で終わる文も存在しますが、プログラミングでは使うことがほとんどありませんので説明を省略します。「どの前置詞を使えばいいのか」という問題は非常に重要です。Goは、Go to ……のほかにもGo for ……、Go through ……など、非常に多くの前置詞を取る可能性があります。前置詞の種類で意味が変化する場合、英和辞典にはその意味が多くの場合明記されています。実際の挙動と一致した、正しい前置詞を選択するようにしましょう。
3-2.第2文型は文字列オブジェクトやstaticな数値をとる
第2文型(S + V + C)は、
1つの補語を必要とする動詞で成り立つ英文の型を差します。
第2文型とオブジェクトの関係
英文法上では、
形容詞と名詞が補語になることができます。
class Subject
def verb(complement)
# 実際の処理
end
end
補語には実体がないことが非常に多く、引数にオブジェクトを取ることはまれです。実際には、ある特定の状態を示すための文字列オブジェクトやstaticな数値を与えることはありますが、インスタンス化されたオブジェクトが渡されることはあまりないでしょう。たとえば、
The person went crazy.
The order just got shipped.
The person became a wizard.
という英文をRubyのコードにすると、
@person.go(:crazy)
@order.get(:shipped)
@person.become(:wizard)
のようになります。コードからもわかるとおり、状態に関連するメソッドは第2文型の動詞をメソッド名とするとよいでしょう。
コラム.前置詞はイメージでとらえよう
ところで、ここでは前置詞を取らない#goメソッドを定義していて、先述の「コラム.第1文型のメソッドに必須な引数を持たせる」では#go_toメソッドを定義しました。もしかしたら、一見しただけでは「前置詞があるかないかだけで挙動が変わってしまい、わかりにくい」と思われる方もいるかもしれません。しかし、前置詞だけで意味がまったく変わってしまうことは英語ではよくあることなのです。また、Goという単語をとにかく「行く」という意味でとらえていると、
He went crazy due to the bug.
「彼は、そのバグのせいでいらいらしてしまった。」
という英文を見たときに誤訳をしてしまう可能性があります。英語を母語とする人は、前置詞があるかどうかだけで意味を瞬間的に判断することができます。したがって、GoなのかGo to なのかで困惑することはあまりなく、それが問題になることは珍しいのです。前置詞は、日本人に馴染みの薄い概念であるため、慣れるまでたくさんのトライ&エラーが必要です。また、to 〜(〜へ)というように、前置詞に直接日本語訳を与えるのもよくありません。前置詞は多様な使われ方があるため、すべての訳をカバーすることは現実的ではありません。前置詞はイメージでとらえることが重要なのです。
4.他動詞をとるメソッド
ここからは、他動詞をとるメソッドの解説をしていきます。
他動詞とは、動詞の後に目的語を必要とする動詞です。自動詞は、インスタンス化されたオブジェクトが1つあれば処理として成立しましたが、
他動詞はもう1つ、あるいは2つのオブジェクトを必要とします。他に必要とされるオブジェクトの扱いが、オブジェクト指向プログラミングでは、引数という形で表現されます。それぞれの文型によって、どのようにメソッドを設計したらよいか解説します。
4-1.第3文型はオブジェクトを指し示す
第3文型(S + V + O)は、
1つの目的語を必要とする動詞で成り立つ英文の型を差します。
第3文型とオブジェクトの関係
オブジェクト指向プログラミングでは、
目的語(第1引数)はほとんどの場合、プログラミングの上でのオブジェクトです。次のようなスタイルのRubyのコードを見たことのある人は、非常に多いと思います。
class Subject
def verb(object)
# 実際の処理
end
end
@worker.perform(:calculation)
@person.say("Hello!")
@person.buy(@item)
このように、引数に1つのオブジェクトをとるメソッドの名前には、第3文型の動詞を使用します。この文型は、プログラミングの中でも最もポピュラーであり、みなさんも知らないうちにたくさん使っています。
では、多く使われているかといって、何も気にしなくてよいかというと、そうではありません。英語には複数の文型をとる動詞がたくさんあり、前述のRunのように単語1つで伝わる状況が一変してしまうこともあります。おや、と思ったら、辞書を引いて、第3文型をとる動詞であるか、使い方は正しいかどうか、確認しましょう。
4-2.第4文型はオブジェクトのやりとりに使う
第4文型(S + V + O1 + O2)は、
2つの目的語を必要とする動詞で成り立つ英文の型を指します。
第4文型とオブジェクトの関係
第4文型として使われる代表的な動詞がGiveです。オブジェクト指向プログラミングでは、
2つのオブジェクト間で、あるオブジェクトをやりとりするときが、第4文型の動作として該当します。
class Subject
def verb(object1, object2)
# 実際の処理
end
end
開発の現場で実際に使われている具体的な例としては、
- あるユーザがほかのユーザに送金を行う #sendあるいは #payメソッド
- あるユーザがほかのユーザにアイテムを送るための #giveメソッド
- 上記の両方の動作を実行する #buyメソッド
などが挙げられます。インターネット上でさまざまなやりとりを行うことが増えた近年では、ネット銀行での金銭のやりとり、ソーシャルゲーム上でのポイントやアイテムの譲渡など、
この文型に該当する処理は非常に多いのではないかと思います。
では、先ほども #buyメソッドを使った例を使いましたが、ここでも #buyメソッドを使った例を紹介します。Buyという動詞は、第3文型のほかにも第4文型をとることができます。たとえば、
The user will buy the user’s friend the item.
という英文をRubyのコードとして表現すると、
@user.buy(@friend, @item)
となります。このコードでは、第3文型の説明で使われいる #buyメソッドと比較して、
- @friendオブジェクトが@itemを所有することになる
- @userは @itemを所有しないが、お金は払う
という動作が期待されます。1つの英文で複数の意図を伝えることができるので、
煩雑になりがちなコードをきれいにまとめることができるようになるでしょう。また、#buyメソッドのように複数の文型を持つ動詞の挙動は、Javaではメソッドの多重定義によって、Rubyではメソッド内でクラスによって処理を分岐することで定義可能です。
4-3.第5文型はオブジェクトの状態を変更したい場合に使う
第5文型(S + V + O + C)は
、1つの目的語と1つの補語を必要とする動詞で成り立つ英文の型を差します。
第5文型とオブジェクトの関係第5文型とオブジェクトの関係
第2文型と同様に、Complementにあたる引数は、実際のオブジェクトをとることは珍しく、プリミティブな型であることがほとんどです。
class Subject
def verb(object, complement)
# 実際の処理
end
end
この文型では、
オブジェクトの状態を、ほかのオブジェクトが意図的に変更したい場合に使います。たとえば、あるユーザがサーバに対して名前付けを行う #nameメソッドがあります。
この文型は、挙動が第2文型と似ているために、実際のプログラミングで使われることはあまり多くありません。たとえば、サーバの名前の変更にはセッタを使えばよいわけですから、わざわざこの文型に合わせたメソッドを書くことは無駄に見えます。では、どういう状況で使うべきでしょうか。筆者は、「誰が何にどういう処理をしたかを追跡したいとき」にこの文型を使っています。#nameメソッドのコードを示すと、
@user.name(@server, "db-1")
となります。ここでは、@userオブジェクトが@serverオブジェクトに名前を付けた、という事実がはっきりしているため、どのユーザオブジェクトが、どのサーバオブジェクトにどういった名前を付けたのか、ということを追跡するには非常に便利なメソッドとなります。
5.肯定文も疑問文になる?
私たちは、肯定文を疑問文に変えるには、Be動詞を持つ文ならば、主語とBe動詞を逆に、通常の動詞であれば、主語によって “Do” や “Does” などを使うと習いました。非常に簡単な例を示します。
Does the array include 3?
Is the user logged in?
ここで、みなさんは、イントネーションによって、肯定文も疑問文として扱うことがある、という事実をご存じでしょうか? つまり、肯定文でも、次のように語尾を持ち上げて発音すれば、
The array include 3?
The user is logged in?
は、最初の例と完全に同義であり、日常の会話の中でも非常によく使われます。
5-1.Boolean型を返すメソッド
Rubyでは、
メソッド名の末尾に「 ? 」をとるメソッドを、Boolean型の値を返すメソッドとする習慣があります。また、Javaでは
肯定文の動詞以降を名前にとるメソッドを、同様に真偽を返すメソッドとする習慣があります。たとえば、上記の例では、
user.isLoggedIn
や、
array.include?(3)
のように書くと、わかりやすいコードだと言えるでしょう。実際、RubyのArrayクラスには、本例と同様のメソッドが実装されていますし、実際のアプリケーションの中でも非常によく使います。
コラム.不要な接頭語のisを使わないようにしよう
ここで注意したいことがあります。時折、「JavaでBoolean型を返すメソッドにはisを付ける習慣がある」という説明を見かけます。時にはこの説明が「真偽を返すなら接頭語としてとにかくisを付けなければならない」と解釈されてしまうこともあります。すると、意味的に不要な個所でisを付けてしまう可能性があります。isを用いている例がよくあるのは、そのケースが大多数を占めているだけであり、「後から英文に近い、理解しやすいコードを書く」「肯定文もイントネーション次第で疑問文となる」という基礎を忘れてはいけません。実際、JavaにおけるIterator#hasNextやHashMap#containsKeyも真偽を返すメソッドとして用意されています。そのときどきの状況に応じて、isを接頭語として使うべきかどうか考えてから名前を付けるようにしましょう。
6.属性(attributes)の表現
クラスにはたいていの場合、属性(attributes)が定義されています。
属性の命名は、英語における名詞句の成り立ちから派生していると考えると、もどかしい命名を避けることができるようになります。一見単純かもしれませんが、名詞句がどう構成されるかを理解しておけば、別のプロジェクトのコードを読む際にも役に立ちます。逆に、単純だからと軽視して、不自然な名前を付けてしまわないように気をつけましょう。
6-1.名詞+名詞の表現
名詞句は、名詞+名詞という構成をとることができます。
名詞句の表現とメソッドの命名規則
たとえば、ある製品の振る舞いをまとめたProductというクラスがあった場合、名前(name)や価格情報(price)を持っていることが多いでしょう。英語ではこの場合、
The name of the product
The name
のほかに、
The product name
のように言うことができます。多くのオブジェクト指向プログラミング言語では、クラス → メソッドの順に記述するので、#nameというメソッドを定義すれば良さそうです。単純ですね。
では、ユーザからの入力が保存されている属性のメソッドはどう設計したらよいでしょう。ブログの一つ一つの記事を表現するブログエントリ(Blog Entry)クラスについて考えてみましょう。BlogEntryクラスは、記事のタイトルと実際の内容を持っているとし、それらをそのまま返そうとした場合、次のようなクラスを書けば良さそうです。
class BlogEntry
def title
# ブログのタイトルを返す
end
def content
# ブログの内容を返す
end
end
ここまでは大丈夫ですね。では、ブログのタイトルが「English for engineers」だったときに「English For Engineers」(単語の先頭を大文字に変換して返す)を返すメソッドはどう設計したらよいでしょうか。次の例を見てみましょう。
class BlogEntry
def capitalized_title
# ブログのタイトルを、単語ごとに大文字にして返す
end
end
一見すると、この設計も問題なさそうです。ですが、このメソッドを読む際には、
blog_entry.capitalized_title
となり、名詞+形容詞+名詞という構成になります。
名詞句は名詞と名詞の間に形容詞をとることができませんので、英語としておかしくなってしまいます。また、ほかのクラスに同様のメソッドが必要になった場合、同じようなメソッド定義を複数書かなくてはいけなくなるため、実装としても適切でありません。このような場合は、クラスの外に#capitalizeメソッドを実装しましょう。
def capitalize(string)
# 与えられた文字列を、単語ごとに大文字にして返す
end
capitalize(blog_entry.title)
このようにすることで、名詞句表現に近い形で属性を扱うことができるようになります。
6-2.メソッド名に前置詞を使う表現
メソッド名の先頭には、動詞、あるいは名詞をとる例を示してきましたが、先のhash with indifferent accessという例のように、前置詞をとるとわかりやすくなるケースもあります。たとえば、さまざまな型の値を持つ配列を表現すると、
An array
(配列を連想させる)
An array without string values
(String型の要素を含まない配列を連想させる)
のような名詞、あるいは名詞句になります。このような句をコード上で表現しようとすると、次のようなメソッドが欲しくなります。
def without_strings
# Stringの値を取り除いて、返す
end
# without_stringsメソッドを使えば、先ほどの英語の例に近いコードを実現できます。
array = ["Ruby", 2.0, "Java", 7, "Python", 3.3]
array.without_strings # => [2.0, 7, 3.3]
ここまでくると、メソッド名には動詞も名詞も、前置詞までも来てしまうならば、なんでもありじゃないか、と思われるかもしれません。
命名で重要なのは、どのようなコードになると読みやすいか、であり、読みやすさを考えた結果が、メソッド名に動詞や名詞、前置詞が使われるということです。「
メソッド名は名詞、動詞、前置詞のいずれか」という事実を覚えたとしても、何の意味もありません。常に「どうしたら読みやすいコード」になるかを考えて命名しましょう。
まとめ.常に英文を意識したコードにしなくてはならないか?
ここまで、さまざまな英語表現とオブジェクト指向プログラミングの関係について説明してきました。たくさんの表現があると思いますが、ここで、1つ疑問が浮かんできます。それは、「常に英文を意識したコードにしなくてはならないか?」という疑問です。実際のところ、すべてのコードを極端に英文のように書く必要はないと思っています。
あまりに英文に近づけようとすると、大量のメソッドを定義する必要があり、結果的にクラスを肥大化させてしまいます。また、自動詞や他動詞の扱いは基本的な考え方であるため、執拗にこだわる必要もありません。
英語に近い文法でプログラミングをするという技法は、
他人が読んで理解しやすいか、あるいは、書いているプログラマが
気持ち良く書けるか、という美学とも言えるものに近いです。みなさんも、本エントリを読んで、少しでも書いていて気持ちの良い、わかりやすいクラス/メソッド名を付けられるようになっていただければ幸いです。
【あわせて読みたい!】
これからRubyを勉強する人が絶対読んでおきたい書籍9冊+α
プログラムができない僕でもWebサービスが作れる!WordPressプラグイン30選
著者
西嶋 悠貴 NISHIJIMA Yuki
2012年4月より米 Penguin Digital でソフトウェアエンジニアとして東京からリモートで働きはじめ、2012年9月 Shutterfly による買収後も同社でリモート勤務を続けた。2013年10月より Pivotal Labs のニューヨークオフィスで働く。
・Webサイト :http://yukinishijima.net
・twitter : @yuki24
・facebook : http://facebook.com/yuki24