やはりお前らの真偽値メソッド名は間違っている。 〜「Xxx できる?」系メソッドの命名〜

晒すつもりではありませんが、Facebook で友人のとある投稿を見かけて最初は「三単現にしないと💢」という軽い気持ちで返答したのですが、よくよく考えて見たらこれ思った以上のクソ命名でしたので、とりあえず流れのスクショを上げときます:

スクリーンショット 2017-12-07 2.30.18.png

はい、今回の記事はマサカリです。あしからず。

見ての通り、最初は友人の後輩ちゃんが isCanUseSkill という明らかにアレな命名をしてきたので、友人がそれを指摘をするも、まさかの allowSkill という更にダメな名前をつけてきた件。isCanUseSkill はまだ「なんだこいつの英語はwww」という意図はわかるから笑って済ませそうな名前ですが、allowSkill は「これは命令なのか Yes-Or-No 質問を間違えて命令にしちゃったのか💢」という、書いた本人がもし友人じゃなかったら絶対引きずり出して小 1 時間殴りたいレベルのクソ名前です。しかも戻り値は真偽値だからマジでわからない。Yes-Or-No 質問かもしれないし、許可を出すようにしてる命令だけど成功したか失敗したかを示す戻り値の可能性も微レ存だから。

このような「Xxx できる?」系のメソッドは確かにたまに我々非英語圏のプログラマを悩ませることがあります。真偽値を返すメソッドはなんか isXxx で統一したい気持ちもあるけど「Xxx できる?」は明らかに isXxx に直すのはおかしいです。しかしそれをわかってもついつい isCanXxx の名前をつけちゃう人は確かに少なくないです。でもそんな心配しなくても大丈夫、canXxx も真偽値を返すメソッド、つまり「Xxx できる?」のメソッドの名前として使って OK なのです。みんなこうしてます。詳しくはこの記事にもたくさん書いてありますのでここでは割愛します。

ところが今日はこの「Xxx できる?」に使っている can を、もうちょっと深く掘ってみたいと思います。

英語で「can」を使うときは、少なくとも 2 通りの意味がありますので、文脈で判断する必要があります。

まず一つ目は「能力的に Xxx ができる」という意味です。例えばよく耳にする(?)「I can fly!(私は飛べる!)」の can は、「私は飛ぶ能力があります!」という意味で使われています。

そして二つ目は「権利として Xxx をできる」という意味です。例えば「You can drive at 60 km/h on this road(あなたはこの道で時速 60 キロのスピードを出せます)」は、「あなたはこの道では 60 km/h までのスピードを出す権利があります」という意味で使われています。つまりあなたがたとえフェラーリを乗っていても、60 km/h 以上のスピードを出してしまったら取り締まる対象になってしまいます。

この二つ目の意味はまさに、友人が付け直した allow 系の意味です。

ところが、ここで一つ注意してほしい。たとえ二つ目の意味だったとしても、can の主体はその権利を手にしたものです。この例文では「You」です。しかし allow の主体はその権利を与えるものです。ここの例文では登場していませんが文脈で「法令」と読み取れます。つまり「The law allows you to drive at 60 km/h on this road(法律があなたにこの道で時速 60 キロを出す権利を与えています)」です。

そう、友人がつけた名前は、意味としては後輩ちゃんがつけた名前と、真逆と言わないまでも実は全く別なことを言っています。

ではどんな名前をつけるべきか。友人はゲームエンジニアですので、ここの命名もおそらくゲームプログラムの一部でしょう。そして後輩ちゃんがつけた isCanUseSkill は文脈から察するに、ゲームキャラクターがスキルを使えるかどうか、を判定するためのメソッドになります。他の情報がないので、ここの can は上記の二つの意味のどちらを指しているかが不明ですのでとりあえず一旦両方考えてみましょう。

まず能力的にできるかどうか、これはすでにコメントの 1 番目に返信した友人の友人が指摘した通り、isAbleToXxx の名前が使えます。AbleAbility の形容詞で、つまり「Xxx の能力がある」という状態を意味します。もし「能力的に Xxx ができる」という意味でしたら、can 以上に isAbleTo の方がふさわしいと言えるのかもしれません。

次に権利的にできるかどうか、これは友人が出した allow の案を使いますが、もちろん直接 allowsXxx を使うわけにはいけません。先ほど説明した通り、allow の主体は「権利を与える方」です。ゲームにおいては主にゲームルールもしくはゲームシステムが司るでしょう。ですのでここは isAllowedToXxx の名前を付けるべきです。英語としては Character is allowed (by the game system) to xxx もしくは Game System allows (character to) xxx です。ちなみにプログラムにおいてはその都度問い合わせる必要があるのでしたら、おそらく Delegate を通してやることになるかと思われますが、その際は delegate.characterAsksPermissionToXxx(this) 的なデリゲーションメソッドになるんじゃないかと思います。

ところが、逆にいうと can は上記両方の意味を備え持っているからこそ、両方成立しているということも指すことができます。実際のプログラムコードでも、canXxx は「能力的にも権利的にも Xxx ができる」を指すことがほとんど[要出典]です。ですので、今度「Xxx できる?」系のメソッドと出会ったら、このように名前の変更を検討できるかと思います:

  • 能力的にできる? → isAbleToXxx
  • 権利的にできる? → isAllowedToXxx
  • 能力的にも権利的にもできる? → canXxx { return isAbleToXxx && isAllowedToXxx }

追記

「文脈から察するに、ゲームキャラクターがスキルを使えるかどうか」と書いてましたが、ここでは暗黙的に「ゲームキャラクターのメソッド」だと考えていました。ところが逆にもしこれはゲームシステムのメソッドでしたら、確かに allowsSkill は命名として正しいです。Game System allows (character to) xxx ですから。(それでも allow はダメですけどね)

ですので、このメソッドがゲームシステムのものか、キャラクターのものかによって、名前が変わりますね。


さらに追記

元タイトル:「Xxx できる?」系メソッドの命名
せっかくなのでマサカリアドベントカレンダー作ったのでタイトル名変えました。みなさんもたくさんのマサカリを投げ合いましょう。


またさらに追記

おかげさまでこの記事が予想以上の反響をいただいており、たくさんの方から様々な感想をいただいており大変嬉しい極まりです。ここで一つのご感想をシェアさせていただきたいと思います:

本記事のメインテーマとしている「Xxx できる?」系の命名ではないですが、isXxx の命名についてのご感想ですので共有させていただきました。

もちろんチームのコーディング規約などにもよると思いますが、本記事は「canXxx でも大丈夫!」と言いました。それはつまり「is から始まらなくても大丈夫!」ということも意味しています。

もしチームのコーディング規約にどうしても「真偽値メソッドは is で始まらなきゃダメ!」と書いてあればそれを従う方が無難かと思いますが、ただ実際多くのフレームワークやライブラリーはそんなにこだわっておりません。例えば昔の Objective-C の時代の iOS 開発で、UIView の「不可視」を意味するプロパティーは isHidden という名前でした。しかし現在 Swift ではそのプロパティー名は hidden になりました。is がなくなりました。今シェアしたツイートの通り、過去分詞なので真偽値であることは自明だからです。逆でした、Objective-C は hidden のプロパティーでゲッターが isHidden で Swift もプロパティー名が isHidden でした。頭痛しんどい😇

ですので、まとめとしては、もしチームコーディング規約があればそれに従い、なければ使っている言語やライブラリーのコーディングに従えばいいと思います。そのライブラリーに真偽値メソッドを is で始まることを強要しなければ開発者も別に絶対 is で始まる単語を死ぬ気で絞り出さなくてもいいと思います。なんならそのライブラリーの既存のメソッドやプロパティーの名前をリストアップしてそれっぽいものを見つけ出してそれに合わせて名前付ければいいと思います。