関数名が混乱する例
ブール値を返す関数では、「Is○○」という名前を良く見かけます。例えば、中身が空っぽかどうか、の判定をする関数には、IsEmptyという名前が良く使われます。MFCのCStringクラスや、JavaのListインターフェースなどにも、IsEmptyという名前のメンバー関数が用意されています。
空っぽかどうかを調べる関数なら、おそらく混乱はないでしょう。しかし、次のようなケースでは、どうでしょうか。
ファイルを表す、Fileクラスを作るとしましょう。OpenやCloseといった関数の他に、『そのファイルが存在するかどうか』を調べて、真か偽を返す関数も、メンバー関数に加えることにしましょう。さて、貴方なら、どのような名前を付けますか?
『存在するかどうか』を調べることから、existという単語が思い浮かびます。しかし、同じexistという単語を使っても、人によって、いろいろな名前の関数ができてしまいます。
A君 | bool IsExist ( ); |
---|---|
B君 | bool DoesExist ( ); |
C君 | bool Exist ( ); |
D君 | bool CheckExistence ( ); |
E君 | bool CheckIfExist ( ); |
A君の解答は、IsEmpty関数の真似をしたものです。しかし、ここでは、「IsExist」という名前を付ける訳にはいきません。emptyは形容詞ですので、「is」を付けて「IsEmpty」とするのは、英語の文法としても正しくなっていました。しかし、existは動詞です。「IsExist」では、英語の文法が間違ってしまいます。
『存在しますか?』という英文は、『Does it exist?』です。そこで、「is」の代わりに「does」を付けたのが、B君の解答です。つまり、『ブール値を返す関数は、疑問文の形にする』という命名規則を定めた訳です。しかし、ソースコードに頻繁に「Does」という文字が現れることになります。
C君の解答は、ふつうの関数と同じように名前を決めたものです。この方法は良く見かけますが、これだと、関数が何かを実行するものなのか、判定をしてブール値を返すものなのか、分かりにくくなってしまう、という欠点があります。
D君とE君のように、「Check」などの動詞を使った名前を付けるケースも、よく見かけます。しかし、IsEmpty関数には「Check」を付けていないのですから、統一感はなくなります。また、単に判定をするだけでなく、何か処理も行っているかのような印象も与えてしまいます。
Java言語の命名規則
Java言語のAPIでは、ブール値を返す関数の名前は、ある1つの命名規則に従って付けられています。私も、PIXYシステム2の開発では、Java言語のAPIと同じ命名規則を採用しています。
Java言語の命名規則では、Fileクラスの『ファイルが存在するかどうか』を調べる関数の名前は、次のようになります。
bool Exists ( );
Java言語では、ブール値を返す関数の名前は、三人称単数の形になります。これを私は、次のように解釈しています。
『ファイルが存在するかどうか』を調べる関数の説明を、英語で書いて見ると、次のようになります。
This function returns true if it exists.
この関数は、これ(ファイル)が存在するならば、真を返す。
このスタイルで説明を書けば、判定をしてブール値を返す関数の名前が三人称単数の形になることが納得できます。
「Is○○」という名前の関数も、同じように解釈できます。例えば、ListインターフェースのisEmpty関数については、説明を英語で書いてみると、次のようになります。
This function returns true if it is empty.
この関数は、これ(リスト)が空っぽならば、真を返す。
主語と述語
Java言語に倣って、ブール値を返す関数の名前を、三人称単数の形にすると決めても、注意しないと、間違った名前を付けてしまうこともあります。
例として、複数のデータを持つリストボックスを表す、ListBoxクラスを考えます。リストボックスの中に、あるデータが存在するかどうかを調べる関数を作るとしましょう。
何人かに考えてもらったところ、次のように、いろいろな名前が提案されました。
a君 | bool IsIn ( String data ); |
---|---|
b君 | bool Exists ( String data ); |
c君 | bool Contains ( String data ); |
d君 | bool Has ( String data ); |
貴方ならどれを採用しますか?
いずれも、三人称単数の形になっていますし、それっぽい名前になっています。しかし、前述の解釈で考えると、間違っているものがあります。
4人の解答について、それぞれ、関数の説明を英語で書いてみましょう。
a君 | This function returns true if it is in the data. |
---|---|
b君 | This function returns true if it exists the data. |
c君 | This funciton returns true if it contains the data. |
d君 | This funciton returns true if it has the data. |
a君とb君の解答だと、英文の意味がおかしいですね。ですから、ここではc君またはd君の解答が、正解ということになります。
a君とb君は、主語と述語を逆に考えてしまっています。主語と述語を逆にすると誤りであることは、この関数を呼び出す側のコードを想像してみると良く分かります。
c君の解答では、次のようになります。
if (listbox.Contains("abc") { : }
一方、a君の解答では、次のようになってしまいます。これでは、『listboxが"abc"の中にあるか』と読めてしまいます。
if (listbox.IsIn("abc") { : }
主語と述語を逆にした誤りは、よく見かけますので、注意してください。
引数が主語になるケース
メンバー関数の主語と述語に関して、もう1つの紹介しましょう。
リストボックスで、あるデータが選択されているかどうかを調べる関数を作るとしましょう。この関数の名前を、次のようにしてしまう人がいます。
bool IsSelected ( String data );
しかし、この関数の説明を英語で書いてみると、
This function returns true if it is selected the data.
となり、意味が通じなくなります。主語と述語が逆になっていますので、これは誤りです。
ところが、このケースでは、リストボックスを主語にすると、適当な単語が見つかりません。関数の説明を英語で書こうとすると、
This function returns true if the data is selected.
のように、どうしても、引数を主語にせざるを得ません。
Java言語のAPIでは、このようなケースでは、関数の名前を、次のように付けています。
bool IsDataSelected ( String data );
関数の名前の解釈
ところで、OpenやCloseといった、ふつうの関数は、何故このような名前になっているのでしょうか。
私は、ふつうの関数の名前についても、ブール値を返す関数と同じように、説明を英語で書く、という方法で解釈しています。
例えば、『ファイルを開く』という操作をするOpen関数の説明を、英語で書いて見ると、次のようになります。
This function is to be called to open it.
この関数は、これ(ファイル)を開くために呼び出す。
この英文では、動詞は原形のままとなります。
人によっては、関数の名前は命令形だと考えているかもしれません。例えば、SetSizeという関数は、『サイズをセットしろ』という命令文だと解釈する訳です。
しかし、命令文では解釈できない関数もたくさんあります。例えば、GetSizeという関数は、『サイズを取れ』という解釈では、動作と一致しません。命令文で考えるのであれば、『サイズをよこせ』ですから、GiveSizeなどの方が良い、ということになってしまいます。
関数の説明を英語で書く、という方法であれば、どちらも次のように解釈できます。
- SetSize
-
This function is to be called to set the size.
- GetSize
-
This function is to be called to get the size.