プログラムの命名規則

命名規則とは?
  • 変数や関数の名前の付け方
  • 複数名で開発を行う際は必須
  • 一人で開発する場合も一貫性があって良い
  • 大規模プロジェクトではドキュメントがある場合も

プログラムなんて動けばいいじゃないかと思われるかもしれませんが、命名規則というのは開発の効率とメンテナンスの事を考えると確実に守った方が良いルールになります。

開発効率

命名規則が無い場合、それぞれの開発者が好き勝手に名前をつけるため、例えば5人開発者がいると、各々が別名で同じものを呼ぶ事があります。

その場合他の開発者が書いたコードは他人から見て読み難い名前がつけられているコードになるので、可読性が低くなります。

ひとつの例

例えば誰でも一緒になりそうな「魚」であったとしても開発者の数が多くなればなるほど一致させることは難しくなります

魚という誰でも同じになりそうなモノや事象でも異なる場合がある

例えばプロジェクトの途中で他の方が書いた部分を修正しなくてはいけなくなった場合、名前のルールが違うといちいち調べなくてはわからず開発効率がどんどん下がっていきます

一人の開発でも規則性は合ったほうが良い?

命名のバラツキはコードが長くなればなるほど可読性が下がります。
最終的には「もう触りたくないコード」となりバグの巣窟となるので可能な限り変数名や関数名は統一しましょう。

メンテナンス

プログラムは作ったら終わりではありません。

組み込み製品のように10年〜20年スパンで更新されないものもありますが、基本的には問題があったら直していこうという考え方が多いように思います。

というのもソフトウェアは人間が作っている以上、バグがあるのは仕方がない事です。

例えば世界トップクラスのエンジニアが関わっているGoogle,Amazon,Microsoft等のソフトウェアでもバグをゼロにする事には残念ながら今の所成功していません。

自分のような世界トップとは程遠い普通ぐらいのデベロッパーがアプリを作ったら確実にバグが組み込まれてしまうのは間違いありません。

さらに言うと一度作ったプロダクトをずっと使うことが出来るのは一部の限られた環境のみです

組み込み製品では、テストをどれだけきっちりやったところで周りの環境、デバイスが変わってバグが顕在化するかもしれません。

Webの仕組みであってもビジネス環境の変化に合わせてソフトウェアも修正を行う必要があります。例えば10年前のレジを今使うというのはハードウェア的にはまだ使えてもソフトウェアとしては無理があります。

ほんの1例

10年前には無かった〜payはソフトウェア・アップデート無しでは対応することができません。さらに言うと10年後には支払い方法はもっと変化しているハズです。

ではメンテナンスすることになった際に名前や関数名がバラバラだったらどうでしょうか?

単純に解りにくいですよね?

なので命名規則は自分だけでなく、後から開発するメンバーにとっても利益となるものです。

当然逆もしかりなので、何かのソフトウェアを後からメンテナンスする際に読みやすいコードはとても助かります。

日本と北米の違い

実は日本と英語圏での命名規則の違いはそれほど多くはありません。

もちろん日本ではコードのコメントを日本語にする場合もあります。しかし、コメント部分を除くと利用している言語は同じものを利用しているため基本は同じ形式になります。

英語が・・
残念ながら英語のスペルミスや文法ミスはよくある事です。実際私もかなりやってしまいました。しかし恐れずにやっていきましょう、そのうち慣れますし、英語ネイティブも結構ミスしてます。大切なのは気がついたら修正する事です。

それよりも、会社や組織による違いの方が大きいように思います。

日本では英語はあくまでも第二言語であるため、若干違和感のある名前になってしまっている場合も否めませんがそれは気がついたタイミングで修正したら良い話なので、ミスを恐れずに作って行けば良いように思います。

MEMO

北米と日本での命名規則の違いより、失敗を犯す可能性がある挑戦をするか、しないかという部分の方が大きいように思います。
とはいえそれを許容する環境やカルチャー面を含めての違いになるので北米ではOKだから日本でしようというのは難しい部分もあります。

会社や組織によって大きく異る

いくら同じプログラミング言語、さらにはオープンソースのコードを利用しいてもメンバーが異なれば異なる命名規則になる場合も多々あります。

極端な話、命名規則は関わっているエンジニアが全員わかりやすく理解できるものであればなんでもかまいません。

しかし、新規プロジェクトメンバーが参加した際に混乱を招くようなものは除外するべきです。

じゃあ誰が決めるのか?

リーダークラスやコードレビューを行う方により命名規則は変る傾向があります。

しかしこ確実にコレが正解だと言えない場合も多く、開発者の多くは関数名やクラス名を考えることに時間を消費していることも多々あります。

組織内でもプロジェクトによって違う

歴史あるプロジェクトや、10年以上メンテされているものなどは作られた時代に流行っていた単語などが使われがちです。

崩れたコード

命名規則は基本的に開発の早い段階から取り入れ遵守するか、定期的にレビューを行い開発者に対して命名規則を思い出してもらう必要があります。

プログラマーならわかると思いますが、一度崩れてしまったコードをメンテナンスしなくてはいけなくなったらどう思いますか?

特定の人物だけにしか修正できなくなってしまったコードを誰にでもメンテできるコードに戻すことはほぼ不可能です。

規則を強制するには

開発ツールによっては規則に合致しているかどうか自動でチェックできるツールがあります。可能な限り人間によるチェックではなく自動化されたツールで行うべきですが、変数や関数名など、一律チェックすることが難しい場合もあります。

MEMO

世界的な大手企業で働いている優秀なエンジニアでもミスを犯す事はあります。人間が書いている以上ミスは必ず発生するのでどのようにそれをカバーするかが重要です。

英単語 vs ローマ字

これだけは確実に英単語をおすすめします。

というのも、ローマ字は日本語をアルファベットに当てはめただけで、当然日本人にしか理解することはできません。

もしローマ字を採用するのであればひらがなや漢字の方が日本人にとって読みやすいハズです。実際に使うかどうかは別の問題ですが、一部の言語では日本語を関数や変数等に利用することも可能です。

なので外国人には読めず、日本人にも読みにくいというメリットが感じられないローマ字の利用は可能な限り避けるべきです。

しかし、日本語話者のみしか将来的にもメンテナンスする事が無いとわかっている場合はローマ字が採用されるかもしれません。これは組織判断によるものです。

どんな時にローマ字が?

以前流出騒ぎになった銀行のコードにもローマ字関数名があるように、比較的大きな企業ではビジネスプロセスが日本語名になっている事も多く、そのままローマ字が当てはめられていることが多いように思います。

勝手に新しく作らない

同じような機能がいくつもあるシステムを見ることもよくあります。

どうしてこうなってしまったのか?と見ていくと根本に命名規則が違ったため、開発者が見つけることが出来ず新規開発してしまったという場合もありました。

これは命名規則と少し逸れますが、開発時にはできるだけ同じコードを利用すべきです。

再利用

似たような機能を作らなくてはいけない時、コードはできる限りコピペで新しい機能にしてしまう前に、呼び出しするようにできないか考慮すべきです。もしバグがあって修正する際、コピペで関数が乱立していると全てを修正しなくてはいけなくなって更にバグを増やす可能性が高くなります。

具体的な規則は?

ここからは具体的にどのような規則が良いか例を挙げていきます。

MEMO

これらは個人的に思っている事なので、こういう風に考えている人もいるんだなぁ〜程度の参考としていただければ幸いです。

関数名の長さは

長くても良い。

関数名の長さに制限がある場合を除いて、無理に短くする必要はありません

世界的に利用されているlinuxのコードを少し見てみます。

linux/aegis128-neon.c at master · torvalds/linux
Linux kernel source tree. Contribute to torvalds/linux development by creating an account on GitHub.

例えばこのコードの関数宣言部分では以下の通りになっています。

決して短い関数名ではないものの、他の関数名とも矛盾せず、何をしているのか理解しやすい名前設定となっています。

void crypto_aegis128_init_neon(void *state, const void *key, const void *iv);
void crypto_aegis128_update_neon(void *state, const void *msg);
void crypto_aegis128_encrypt_chunk_neon(void *state, void *dst, const void *src,
					unsigned int size);
void crypto_aegis128_decrypt_chunk_neon(void *state, void *dst, const void *src,
					unsigned int size);
int crypto_aegis128_final_neon(void *state, void *tag_xor,
			       unsigned int assoclen,
			       unsigned int cryptlen,
			       unsigned int authsize);

しかし長過ぎる関数名は可読性を著しく低下させるので、2行にまたがってしまうような長さは避けるべきです。

void calculate_area_of_roomba_cleanup_at_least_three_times();
ダメな例

しかしこれほどに関数名が長くなってしまうということは、ひとつの関数に機能を詰め込み過ぎている状態になっているように思います。

命名規則も大切ですが、全体として適切な粒度が揃っていることも重要な要素の一つです。

長い単語は短縮するか?

可能な限りそのままにしておく

とても長い単語は短縮する場合もありますが、現代のプログラミング言語では文字数制限により短くする必要性や、短くした事によるメリットがほぼ無いためそのままにしておきます。

MEMO

まだコンピューターが開発されたばかりの、遥か昔にはメモリも少なく現在のようなOS環境も無かったため、関数名を短くする必要がありました。

メリットがある場合

社内システム等では、会社の業務で一般的に利用されている短縮形の単語等をそのまま利用した方が良い場合もあります。命名規則をきっちり作ってそれ合わせるのではなく、誰もが理解しやすい状態となることを目指しましょう。

どちらかというと短く短縮してしまった事により意味がわからなくなってしまうケースや、最悪の場合意図とは逆に読まれてしまうデメリットの方が大きくなります。

MEMO

例えば Description のような長めの単語は Desc などに短縮される場合もよく見かけます。短縮形であっても開発メンバーがすでに知っている場合は良いですが、Prestidigitation を Prstgtn のように短くしてしまうとほとんどの開発者が元の単語を推測出来ずに悩むことにになります。

Of や In を使う?

使う場合もあります。
作るソフトウェアによっては多用する場合もあるので、避けるべき!という意識は必要ありません。

しかし、ほとんどの変数名や関数名に入ってしまうような場合は名前の付け方がくどいように思うのでもう少しシンプルにするべきです。

// ちょっとくどいかなーと思うレベル
bool create_record_of_users_in_pririty_list();

// OK
bool create_record_for_pririty_user();

命名規則の宗派

命名規則にも大きな分類として、どのように単語を区切るのかという宗派があります。

これはプロジェクト全体で統一されるべき規則ですが、現実的には利用しているライブラリやAPI単位で異なる場合もあります。

同じ人が開発しているのに混ざっていると、何故だ・・という疑問が沸いてきます。

ここからは auto speed up という関数名を例に見ていきます。

MEMO

「自動的に速度を上げる関数の名前」として適当に挙げただけなので、深い意味はありません。

キャメルケース

autoSpeedUp

先頭を除く各単語の頭文字を大文字にしたもの。自分が経験したプロジェクトではこれが一番主流。

Java, C, Swiftなどでよく利用されている

これはラクダの背中のようにボコボコしていることから来ているようです。

さらなる流派も

キャメルケースはさらにいくつかの流派に分かれており、一番先頭を大文字にするものもある。また別の名称で呼ばれる場合もあるが、キャメルと言えば基本このどちらかになります。

  • アッパーキャメルケース:AutoSpeedUp
  • ローワーキャメルケース:autoSpeedUp

スネークケース

auto_speed_up

各単語を_(アンダースコア)でつないで表記する。物理的に単語が離れるため可読性という意味ではキャメルケースより良い場合も多いが、単語数が多くなるほど名前が長くなる。

PHPでよく利用されている
アンダースコアが複数の場合も
プロジェクトによってはアンダースコア数が複数になる場合もある。似たものではマクロが__TEST__のように宣言されている場合もある。

ケバブケース

auto-speed-up

CSSでよく利用されている

スネークケースの_(アンダースコア)に変わり、ハイフンで各単語をつないでいる。

ちなみにケバブとはこのようにお肉をレイヤーにして焼いた料理で中央に串が刺さっている。誰も知りたか無いと思うがもりしーの大好物である。

Photo by Yash Bhardwaj / Unsplash

英語的な正しさと理解しやすさ

例えばライトのON/OFFをする関数名があるとしましょう。

この場合どちらが理解しやすいでしょうか?

(A)対象であるlightを前に

bool light_turn_on();
bool light_turn_off();

(B)動作であるturn_on/offを前に

bool turn_on_light();
bool turn_off_light();

この場合、英語としてそれっぽいのは(B)でしょう。

また、プログラムで扱う対象がライトだけであれば(A)でも(B)でもそれほど大差は無いように思います。

しかし、ライトの他にエアコンやファンがあったら、と考えると(A)である方がプログラムとしてメンテナンスしやすいものになるように思います。

MEMO

VS codeなどほとんどの開発環境では変数名・関数名などの補完が効くため、lightと入力したらいくつかの候補が出てきた方が書きやすいように思います。
逆にturn_onだとリストがどんどん長くなるので、探しにくくなります。

対象となるモノを先頭に持ってきた場合

// light
bool light_turn_on();
bool light_turn_off();

// fan
bool fan_turn_on();
bool fan_turn_off();

動作を先頭に持ってきた場合

// light
bool turn_on_light();
bool turn_off_light();

// fan
bool turn_on_fan();
bool turn_off_fan();

個人的には対象となるモノを先頭に持ってくる方が好きですが、動作が先というルールが採用されていれば、それはそれでかまいません。

命名規則は、どちらが正解と言えないケースも多々あります。

まとめ

ローマ字ではなく英単語にする。
間違えた場合は修正したら良いので恐れる必要はありません。これこそがソフトウェアの良い所なので、メリットを存分に活かしましょう。
長くても良い。
単語を短くするメリットはほとんど無いため、可能な限りそのままにしておきます。しかし長過ぎる場合はより可読性が下がるため関数などの粒度を調整することも検討すべきです。
正解は無いが、ダメなパターンはある。
2つパターンあってどちらも正解の場合もあります。完璧を求めてこだわる必要はそれほどありません。極論で言えば動いているソフトウェアこそが正解ですが、メンテナンスや後々の事を考えた場合に命名規則などが重要になってきます。
スタイルに名前がついている。
キャメル・スネーク・ケバブの3つは知っておくと、ごく稀に役立つ事がありますがコードを見たらわかるので、ネタ程度に覚えておけば良いと思います。

謝辞

この記事はご質問頂いた内容にインスパイアされ作成しています。ご質問ありがとうございました。

もりしの質問箱です
質問・回答はこちら
この記事の画像は vijay verma による作品で、MITライセンスにより利用しています。https://vijayverma.co

References

  1. 命名規則 (プログラミング) https://ja.wikipedia.org/wiki/%E5%91%BD%E5%90%8D%E8%A6%8F%E5%89%87_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)