JavaやKotlinのコーディング規則ではよくコンパイル時定数や実質的に定数として扱っているものをUPPER_SNAKE_CASEとする命名規則が取られていますが、UPPER_SNAKE_CASEは致命的に読みにくいので辞めようっていう話です。
※JavaやKotlinに限った話ではないです。
※定数に限った話でもないです。
なぜ読みにくいのか
さまざまな命名規則
プログラムコードの命名規則にはいくつか種類があると思いますが、ここでは以下のものについて触れます。
- UPPER_SNAKE_CASE(以下SNAKE_CASE)
- lower_snake_case(以下snake_case)
- UpperCamelCase(以下CamelCase)
- lowerCamelCase(以下camelCase)
命名規則通りの表現をしているので、どのようなものか?については文字通りになります。 また、SNAKE_CASEとsnake_caseを合わせてスネークケース、CamelCaseとcamelCaseを合わせてキャメルケースと表現することにします。
大雑把に分けたらアンダーバーを入れるスネークケースと大文字にすることで単語を区切るキャメルケースに分かれます。 (アッパーキャメルケースについてはパスカルケースとも呼ばれることがあります。)
読みやすさランキング
結論から言うと以下のようになります。
snake_case ≧ キャメルケース >>>>>> 越えられない壁 >>>>>> SNAKE_CASE
と言ってもsnake_caseとキャメルケースの読みやすさはの違いは大してないと思います。どちらを採用するかは「好きな方をどうぞ」でいいレベルです。
なぜsnake_caseはキャメルケースより読みやすいのか
普段我々が読む英語の文章から考えてみましょう。
I am application engineer.
こういう文章があったとして、単語と単語の間はスペースで区切られますよね?
それをそのままsnake_case, camelCase, CamelCaseにすると
i_am_application_engineer
iAmApplicationEngineer
IAmApplicationEngineer
このようになります。
普段読み慣れてる英文をより忠実に(スペース含め)再現度の高いのはsnake_caseとなります。また、キャメルケースでは単語の区切りは大文字です。iの大文字とLの小文字(I,l)ってぱっと見区別がつきにくいです。
なので、snake_caseのほうがキャメルケースよりは経験上読みやすくなるだろうということです。 “だろう”というのは通常の英文の単語にも固有名詞の場合は大文字スタートなどがあるので、大文字区切りのキャメルケースでも大差はないでしょうということです。
また、snake_caseはアンダーバーの分文字数が増えるのも難点です。そのあたりを加味するとsnake_caseとキャメルケースは大差がない、どれを使うかは個人の好みの範疇と言えます。(私はキャメルケース派です)
なぜSNAKE_CASEは致命的に読みにくいのか
普段我々が読む英語の文章がすべて大文字ということは滅多にないことです。
I am Application Engineer.
はあったとしても
I AM APPLICATION ENGINEER.
と書くことは滅多にないでしょう。あったとしても強調している場合。
普段英文で読まない記法が、プログラムのコードで読みやすいわけがないのです。
そもそも強調ですべて大文字にするというロジックは「読みにくい形にすることで一文字一文字じっくり読んでもらう」というものではないでしょうか?
読みにくい形にして強調するスタイルならSNAKE_CASEはわかります。ただ、それだからこそSNAK_CASEは致命的に読みにくいのです。
定数は強調する必要あるのか
定数であることがわかるときの美味しさ
定数であるということは定数の利用者側からしたらreadonly(Javaで言うfinal)かつimmutable保証があるということです。 つまり値が変わらない(だから定数って呼べる)
よく防御的プログラミングでnullチェックをするということがありますが、writableだったりmuttableであったりすると防御的なコードを書かなければ安全が担保できない場面はあるかもしれません。(否定も肯定もできない)
また、そういった点を人間によるコードレビューで漏れを起こしにくくするために定数であることがわかると美味しいこともあるんじゃないの~~~ぐらいはわかるでしょう。
しかし、SNAKE_CASEだから定数であることは保証されない
定数であることがわかると美味しい場面があるかもね、はわかったかと思いますがしかしながらそれがJavaやKotlinの「定数はSNAKE_CASEとする」には結び付きません。 Kotlinのconst valを除いてJavaのstatic finalやKotlinのcompanion object/object内のvalにconst(定数)保証はありません。
いくらconstをSNAKE_CASEという命名規則にしようが、もし実装者が変数をSNAKE_CASEとして実装してしまったら、定数であることがわかるときのうまみがゼロになってしまいます。(むしろ変数が混入することでデメリットの方が大きくなる)
定数/変数であることが区別できるうまみがあるなら他のも区別できるようにしよう
もう一つの視点から話すと、定数であることがわかるうまみがあるなら他の属性もわかったほうがうまみありますよね。 Kotlinに限った話にはなりますが、valとvarは区別できた方がいいですよね?定数より使用頻度高いので優先度は高いですよね?
でも、実際には言語仕様・命名規則では区別せずに、Jetbrains IDE(Kotlin Pluginの機能だと思う)のコードハイライトによって区別されます。(たしかvarにはアンダーラインが付く)
必要なのはIDE・言語仕様によるアシスタント
もし、定数であることがわかるうまみがあるのなら、IDEが定数であると認知してくれるような機能を提供するだけでいいんです。(実際にないかは知りません) 言いたいことは、命名規則という確証のとれないもので区別するようにしてはいけないということです。
もっとも、定数であることがわかるうまみが大きいのなら、言語仕様レベルで定数を使うときはconst修飾子が必要にするとかにしましょうよ。
println(const HELLO_WORLD)
みたいな感じで。
まぁ既に述べた通りSNAKE_CASEは致命的に読みにくいのでsnake_caseかキャメルケースにしましょうってのもありますが。
こういう風にしないのはそこまでうまみがないということなんでしょう、きっと。
それか当初の言語設計が悪く、今さら追加できないか。
結論
SNAKE_CASEは読みにくいし、わざわざ定数であることを区別しなくてもいいので、定数も他の変数みたいにcamelCaseみたいにしましょうよ。
以上、SNAKE_CASE絶対許さないマンの記事でした~~