真偽値を返す関数のネーミング

真偽値(Boolean、bool)を返す関数は、is で始めるのが一般的かと思います。
少なくとも C++ では。
ただし、英語的に、is 始まりが難しい場合もあります。

is で始められない関数名の名付け方を考えました。

2017/09/19 追記：
大前提として、言語やプロジェクトにガイドラインやルールがある場合は、そのルールに従うべきです。
以下の内容は、そのルールを破ってまで適用すべきものではありません。
今回は英語的な正しさを重要視していますが、どんな場合も英語的な正しさを優先すべきとは限りません。
他の人が書いた関数名に合わせたり、関数の関係性を重要視する場合は英語的な正しさを二の次にすることは正しい判断になると思います。


## 存在するか？

一番やりがちな失敗が「存在するか？」を is で始めようとするパターンです。
気持ちは分かります。
真偽値を返す関数が is で始まるのは気持ち良いですからね。
しかし、「存在するか？」という関数はどうしても is で始められないと思うのです。

```isExist``` という表現を見かけることが多いですが、個人的には使いません。
exist は動詞なので is と組み合わせることは英語的に有り得ません。
ただし、英語的な正しさよりも、真偽値がisで始まることが重要だと考える場合は、間違った名前ではないと思います。
十分意味も伝わります。

```isExistence``` だと「存在するか？」というより「存在か？」という感じで、意味が分かりません。

```isExisted``` もダメです。
exist は自動詞なので、英語的に有り得ません。
過去形になってしまっているので、分かりやすさという意味では ```isExist``` の方がマシです。

```isExisting``` や ```isExistent``` は微妙なところですが、やっぱりおかしい気がします。
私は以前、「真偽値を返す関数名は is で始めないと死んでしまう病」という奇病にかかっていたため、```isExisting``` を使っていました。
今となっては黒歴史です。

ということで、exist に関しては is で始めるのを諦めましょう。
無理です。

ではどんな表現にすべきかといいますと・・・```exists``` です。

世の中の API がこの表現を使っています。

PHP では

```php
bool file_exists ( string $filename )
```

Apple の NSFileManager クラスでは

```objectivec
- (BOOL)fileExistsAtPath:(NSString *)path
```

Microsoft の File クラスでは

```cpp
bool Exists( string path )
```

Android の File クラスでは

```java
boolean exists()
```

みんな ```exists``` を使ってます。
納得できようができまいが、```exists``` なのです。
ソフトウェアの世界では、Apple と Microsoft と Google が黒と言ったら黒です。
黙って従いましょう。

このように、関数名の表現に困ったら、世の中の API を参考にすると良いです。
非ネイティブの我々では思いつかないような的確な表現が見つかることもあります。


## 関数の名付け方

真偽値を返す関数は if 文で使われることが多いので、頭に if を置いて最もしっくり来る表現が良いと思います。
個人的には、真偽値を返す関数名を考えるときは以下のフォーマットに当てはめるようにしています。

**if オブジェクト名 関数名**

「項目が選択中だったら」なら "if item is selected" なので関数名は ```item.isSelected()``` となります。
同様に「項目が存在したら」なら "if item exists" なので ```item.exists()``` となります。
「リストに項目が含まれていたら」なら "if list contains item" なので  ```list.contains(item)``` または ```list.containsItem(item)``` となりますし、
「リストの項目を削除できるなら」なら "if list can remove item" なので ```list.canRemove(item)``` または ```list.canRemoveItem(item)``` となります。
最後の例はちょっと怪しいですが、こんな感じで関数名を考えています。
こうすると、関数名が ```exist``` ではなく ```exists``` になっていることも納得できます。

isEnabled() は一般的な関数名ですが "if is enabled" は英語的に変です。
その場合は、```isEnabled()``` が ```this->isEnabled()``` であることを思い出しましょう。
"if this is enabled" なら違和感はありません。
また、Item クラスで ```isItemEnabled()``` という関数名にすると "if this(Item) is item enabled" という違和感のある英語になってしまい、関数名が不適切だということが分かると思います。

もちろん、このフォーマットが当てはまらないケースも**多々**あります。

例えば、Item クラスのメンバ変数に ```name``` という文字列があり、その文字列が空かどうか判断する場合は ```isNameEmpty()``` という名前を付けると思います。
フォーマットに当てはめると "if this is name empty" となり、おかしいです。
this を省略しても "if is name empty" となり、これもおかしいです。
それでも、関数名は ```isNameEmpty()``` が一般的だと思います。

2017/09/10 追記：
```isNameEmpty()``` ではなく ```hasEmptyName()``` の方が英語的に良いというアドバイスを頂きました。
それだと "if this has empty name" になるのでフォーマットにも当てはまります。


## is で始まらない表現

is 以外で始める場合は、動詞か助動詞を使いましょう。
それ以外の品詞で始まるのは変です。

動詞始まりで真偽値を返す表現の例：

- exists (存在するか)
- contains (含まれているか)
- has (持っているか)
- needs (必要か)

助動詞始まりで真偽値を返す表現の例：

- can (できるか)
- should (すべきか)
- need (する必要があるか)


## can = is 〜able

可能かどうかは can 始まりにします。

- canRemoveItem(item)
- canUpdate()
- canStartTimer(timer)

しかし、英語的には can は is 〜able に置き換えることもできます(たぶん)。

- isItemRemovable(item)
- isUpdatable()
- isTimerStartable(timer)

「真偽値を返す関数名は is で始めないと死んでしまう病」の方は、こういう表現を使うという手もあります。
私も一時期、この表現を使っていました。
しかし、目的語は関数の最後にあった方が気持ちがいいので、個人的には isUpdatable 以外は can の方の表現を使いたいです。
あと、〜able は造語になってしまうので、辞書に載ってない英単語になることもあります。
英語が得意な人なら意味を理解できるかもしれませんが、英語が苦手な日本人にとっては理解が難しくなります。


## is以外のbe動詞を使いたい場合

「全てのアイテムが削除済みかどうか」を確認する関数を作成した場合、どんな名前にすべきでしょうか？
深く考えずにパッと思いつくのは以下の２つです。

- isAllItemsRemoved
    - isで始まっており真偽値を返す関数名としては気持ちいいですが、名詞が複数形なので英語的には間違っています。
- areAllItemsRemoved
    - 英語的に正しいですが、areで始まることに違和感があります。

「関数名的に気持ち良い表現を優先するか」「英語的に正しい表現を優先するか」ということに関しては意見が分かれると思います。
私個人としては、英語的な正しさを優先するので、上記２つのどちらかを選ぶとすれば are の方です。

ただ実際には、「全アイテムが削除済みかどうか」を関数にする場合、上記２つではなく以下の関数名にすると思います。

- isEveryItemRemoved
    - 細かいことを言えば、all と every は英語的にニュアンスが違うとは思いますが、is始まりだし、英語的にも正しいので分かりやすいです。
    - ただし、Every が「全ての」という意味だということは、All ほど認知されていないような気もします。
- itemExists
    - 「存在するか」に表現を変えることで、気持ちいい関数名にします。

こんな感じで、関数名に迷ったら別の表現を検討するのも良い手だと思います。

is vs are の議論は以下でも行われています。
<https://stackoverflow.com/questions/12960554/java-boolean-getters-is-vs-are>
<https://stackoverflow.com/questions/2691463/is-or-are-to-prefix-boolean-values>


## 真偽値を設定する関数

今までは真偽値を返す関数(以下、getter)のことを書いてきましたが、最後に真偽値を設定する関数(以下、setter)についても書いておきます。

基本的に is を set に変えるだけです。
getter が ```isSelected``` なら、setter は ```setSelected``` とします。
必ず ```isXXX``` と ```setXXX``` がペアになるようにしましょう。
その方が分かりやすいです。

is で始まらない場合は、頭に set を付けます。
```canRemove``` なら ```setCanRemove``` とします。
```exists``` なら ```setExists``` とします。
英語的にはおかしい表現になりますが、英語の正確さよりも関数の関係性の分かりやすさを優先します。

この辺のルールは Apple の Naming Guidelines を参考にしています。
<https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html#//apple_ref/doc/uid/20001282-1004202>

というか、私が関数や変数の名前を真面目に考えるようになったのが、iOSアプリ開発に携わるようになってからなので、私のネーミング思想は Apple の影響が強いです。

<br>

ということで、Apple の Naming Guidelines オススメです！
(Objective-C なので注意)
<https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html>