変数・関数の命名規則ベストプラクティス - コードの可読性を高める効果的な命名テクニック
関数や変数を見ただけでその役割が明確に伝わる命名を目指す。そのためにも、名前に十分な情報を含めることが重要となる。
単語選び
「名前に情報を詰め込む」には、明確な単語を選ばなければいけない。
『リーダブルコード』(Boswell, Foucher, 2012, p.10)
つまり、汎用性の高い単語を使うのは怠惰であると。
例えば、よく使われるgetter
やsetter
といった単語は曖昧である。
function getPage(url) {
...
}
こういったコードはよく見かけるが、get
からは取得元などの具体的な情報が伝わらない。
function fetchPage(url) {
// インターネット上から取得
}
function loadPage(url) {
// ローカル上のHTMLを取得
}
function getPageFromCache(url) {
// キャッシュからページを取得(キャッシュにない場合はfetchPageを呼び出す)
}
1-1.js
のようなコードの方が明確で理解しやすい。
他にも、以下のような名前の改善例がある。
foobar.size();
// 高さ
foobar.height();
// メモリーサイズ
foobar.memoryBytes();
// 子要素の数
foobar.numNodes();
いろんな言い換え
他にもいろんな言い換えができる。そこで、ChatGPTにコードでよく使う動詞とその類似語についてテーブルにしてもらった。
単語 | 類似語 |
---|---|
get | fetch, load, retrieve, obtain, acquire, pull, read |
set | update, assign, put, store, write, save |
size | length, count, total, capacity, num, volume |
send | post, submit, deliver, push, dispatch, transmit |
create | build, generate, produce, construct, make, instantiate |
delete | remove, erase, clear, destroy, discard |
check | validate, verify, confirm, assert, ensure |
process | handle, execute, run, perform, operate |
find | search, locate, query, scan, match |
show | display, render, present, visualize, output |
change | modify, alter, transform, edit, adjust |
stop | halt, terminate, abort, end, interrupt |
start | launch, initiate, begin, activate, trigger |
便利なtmp, retval
以下のコードがある。
function calculateSum(numbers) {
let retval = 0;
for (const num of numbers) {
retval += num;
}
return retval;
}
const values = [1, 3, 5, 7, 9];
const sum = calculateSum(values);
console.log(`Sum is: ${sum}`); // Sum is: 25
便利なretval
だ。しかし、retval
を見ただけではどのような値が格納されているかが不明である。
この場合、total
やsum
の方が理解しやすいコードになる。
if( foo < bar ){
let tmp = foo;
foo = bar;
bar = tmp;
}
bar
の方が大きい場合に、foo
とbar
を入れ替えるコードである。この場合、tmp
はこの3行でしか使われず、tmp
には他の役割がない。この場合のtmp
は問題ない。
一方で、以下のtmp
は怠惰である。
let tmp = "田中 太郎, ";
tmp += "1200-12-11, ";
tmp += "taro.tanaka@〇〇.com, ";
tmp += "東京都, ";
...
users.add(tmp);
この場合のtmp
の役割は一時的なデータ保存ではなく、ユーザーを定義することである。そのため、profile
やuser
などの方が理解しやすいコードになる。
ループイテレータ
ループで使うi
やj
などの変数名はインデックスやループイテレータで使われるが、名前だけ見るとイテレータ
だということしか読み取れない。
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
console.log(`matrix[${i}][${j}] = ${matrix[i][j]}`);
}
}
それに対して、row
とcol
を使うことで理解しやすいコードになる。
for (let row = 0; row < matrix.length; row++) {
for (let col = 0; col < matrix[row].length; col++) {
console.log(`matrix[${row}][${col}] = ${matrix[row][col]}`);
}
}
row_i
やcol_i
とかでも理解しやすいコードになる。
名前に属性をつける
理解しやすいコードを書く上で、変数名や関数名を見るだけで絶対に知らなくてはならない情報が読み取れることは重要。
const start = (new Date()).getTime(); // 単位が不明確
// ミリ秒
const start_ms = (new Date()).getTime(); // ミリ秒
const start_secs = (new Date()).getTime() / 1000; // 秒
例えば、start
の単位がミリ秒ならstart_ms
にすると、単位
という属性
が変数から読み取れるようになる。
他にもいろんな属性を追加することができる。
// 単位( byte )
const uploadFile = inputFile.files[0];
const size = uploadFile.size; // Before
const size_byte = uploadFile.size; // After
// 単位( byte )
const uploadFile = inputFile.files[0];
const size = uploadFile.size; // Before
const size_byte = uploadFile.size; // After
// パスワードの処理状態
const plain_password = "password"; // プレインテキスト
const encrypted_password = "9a8b7c6d5e4f3g2h1i0j"; // 暗号化されたパスワード(元は"password")
const hashed_password = "$2b$10$eB9fRkZ1Tg2i3pWQ5FQf.eX5S3MjY8j"; // bcryptなどでハッシュ化済みのパスワード
// 日時のフォーマット
const now = new Date();
const nowUnixTimestamp = Math.floor(now.getTime() / 1000); // Unixタイムスタンプ(秒)
const nowIso8601 = now.toISOString(); // ISO 8601のフォーマット YYYY-MM-DDThh:mm:ss.SSSZ
const nowDateIso = now.toISOString().split('T')[0]; // ISO日付のみ YYYY-MM-DD
const nowTimeIso = now.toTimeString().split(' ')[0]; // ISO時間のみ HH:mm:ss
now
だけでは抽象的で、単位もフォーマットもわからない。フォーマットを含めた変数名にすることで、理解しやすいコードになる。
名前の長さ
理解しやすいコードにおいて、名前の長さも重要となる。例えば以下の変数名。
const numberOfBytesAllocatedForInitialBufferSizeInMemory = 1024; // 文章
長すぎて画面は 大きく占領され読みづらい。だからと言って短くても情報が伝わらない。
const size = 1024; // サイズ
長すぎても短すぎても理解されやすいコードにはならない。
const bufferSizeBytes = 1024; // 必要最低限の情報
2~4単語ぐらいがベストではないかと思う。
命名規則
言語によって異なるが、一般的には以下のようにケースを使い分けることが推奨される。
命名規則名 | 構成ルール | 例 | 主な用途 |
---|---|---|---|
キャメルケース (camelCase) | 小文字で開始、単語の区切りを大文字にする |
userName , totalAmount
|
変数、関数名 |
パスカルケース (PascalCase) | 各単語の頭文字を大文字にする |
User , ShoppingCart
|
クラス名、型名 |
スネークケース (snake_case) | 小文字、単語間は_ で区切る |
user_name , total_amount
|
変数、関数名(Python), データベースカラム名 |
アッパースネークケース (UPPER_SNAKE_CASE) | 全て大文字、単語間にアンダースコア |
MAX_SIZE , TOTAL_COUNT
|
定数 |
ケバブケース (kebab-case) | 小文字、単語間にハイフン -
|
user-name , total-amount
|
CSSクラス名、HTML属性 |
参考文献
- 『リーダブルコード』(Dustin Boswell, Trevor Foucher 著、角征典 訳、オライリー・ジャパン、2012年)