背景
Boolean 型の変数に適した命名規則をあらためて考えてみた。命名は小さなことのように思えるが、コードベースが大きくなるほど、その重要性は増していく。
命名規則に従えば、コードの可読性が向上しメンテナンス性も良くなる。特に Boolean 型変数は条件分岐やフラグとして頻繁に使用されるため、その命名の良し悪しがコード全体の理解しやすさに大きく影響する。
問題事例
同じプロジェクト内で開発者によって様々な命名パターンが混在したとする。
const expired = checkDate(date);
if (expired) {
}
const isExpired = checkDate(date);
if (isExpired) {
}
const notExpired = !checkDate(date);
if (notExpired) {
}
このような不統一は、コードレビューやデバッグの際に混乱を招きバグの原因にもなる。チーム内で一貫した命名規則を採用することで、これらの問題を回避できる。
プレフィクス
Boolean 型の変数には、 is
、has
、should
などのプレフィクスが一般的に利用される(このほかにもcan
、will
、did
、must
なども利用される)。これらのプレフィクスを利用することで、変数がBoolean型というのが明示的になり、コードの可読性が向上する。また、IDEの補完機能も効果的になる。
const isExpired = true;
const isFinished = false;
const hasPermission = true;
const hasError = false;
const shouldShowModal = true;
const shouldFetchData = false;
プレフィクスの重要性
プレフィクスを利用することで、その変数が真偽値であると明確になり、コードを読む際にその変数が何を意味しているのか直感的に理解できる。例えば、isExpired
という変数名は、その変数が有効期限切れかどうかを明示している(expired
という変数名だけでは、期限切れがどういう状態なのかが明確ではない)。
プレフィックスの適切な選択方法
どのプレフィックスを使うべきかは、変数が表す状態や関係によって決まる。
プレフィックス | 使用場面 | 例 |
---|
is | 状態や特性を表す場合 | isActive 、isVisible 、isReady |
has | 所有や存在を表す場合 | hasChildren 、hasError 、hasAccess |
can | 能力や権限を表す場合 | canEdit 、canDelete 、canVote |
should | 予期される行動や判断を表す場合 | shouldUpdate 、shouldRefresh |
will | 今後の動作や意図を表す場合 | willChange 、willExecute |
did | 過去の動作完了を表す場合 | didUpdate 、didProcess |
must | 特定の制約や要件を表す場合 | mustVerify 、mustInclude |
const isLoading = true;
const isAuthenticated = false;
const hasProfile = user.profile !== null;
const hasRequiredFields = checkFields(data);
const canEditDocument = checkPermission(user, 'edit');
const canSubmitForm = formIsValid && !isSubmitting;
チーム全体で同じプレフィックス選択基準を共有することで、コードの一貫性が高まり、読み手の理解が容易になる。
条件の明示
変数名には、その変数が何に対する条件であるかを明示する名前を付けると良い。
const isExpired = true;
const hasPermission = true;
否定形を避ける
Boolean型の変数では否定形を利用せず、肯定形で命名することを推奨する。否定形の変数は読み手に混乱を与える可能性がある。例えば、isNotExpired
とisValid
では、前者が混乱を招く可能性が高い。
const isNotExpired = false;
const isExpired = true;
否定形を使うと変数の意味が逆転して読みにくくなり、条件式も複雑になる。肯定形(例:isValid
)を使うことで理解しやすくなる。
同じ意味の単語を避ける
同じ意味を持つ異なる単語を利用すると、読み手に混乱を与える可能性がある。例えば、isAvailable
とisEnabled
は、どちらも機能が利用可能であるかどうかを示すが、単語が異なるために混乱を招く。
const isAvailable = true;
const isEnabled = true;
const isAllowed = true;
const hasPermission = true;
const canAccess = true;
上記の問題を解決する方法
同じ意味の単語による混乱を避けるためには、プロジェクト内で定義したものにしたがって命名することが重要である。
const isEnabled = true;
同じ意味の単語(例:isAvailable
とisEnabled
とisAllowed
)を違う目的で使うと、読み手に混乱を与える。一方、hasPermission
とcanAccess
はプレフィックスが異なるため意味の違いが明確。プロジェクト全体で共通の命名規則を使うことが重要である。
プロジェクトの命名規則やコーディング規約に従う
各プロジェクトには独自の命名規則やコーディング規約が存在する場合がある。それに従うことで、ほかの開発者もコードを理解しやすくなる。
const isExpiredDate = true;
const hasEditPermission = true;
プロジェクト全体で決めた命名規則やコーディング規約を守ることで、コードの理解、修正、保守が容易になる。一賛性と統一性を重視し、各プロジェクトの方針に合わせる。
Linter で矯正する(ESLint)
Webフロントエンド開発では、ESLint と @typescript-eslint
を利用してBoolean型変数の命名規則を自動的に強制できる。@typescript-eslint/naming-convention
ルールを適切に設定することで、チーム全体のコードの一貫性を保つことができる。
基本的なESLint設定
module.exports = {
rules: {
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'variable',
types: ['boolean'],
prefix: ['is', 'has', 'should'],
},
],
},
};
より高度な設定例
コードベースやチームのニーズに応じて、より詳細な設定もできる。
module.exports = {
rules: {
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'variable',
types: ['boolean'],
prefix: ['is', 'has', 'should', 'can', 'will', 'did', 'must', 'was', 'were'],
format: ['camelCase'],
},
{
selector: 'classProperty',
types: ['boolean'],
prefix: ['is', 'has', 'should', 'can'],
format: ['camelCase'],
},
{
selector: 'parameter',
types: ['boolean'],
prefix: ['is', 'has', 'should', 'can'],
format: ['camelCase'],
},
],
},
};
ESLintの設定に関するチームでの討論ポイント
このルールを導入する前に、チームで以下の点について討論することを推奨する。
- どのプレフィックスを許可するか(
is
、has
、can
など) - 各種プレフィックスの使い分け基準
- 既存コードをルールに適合させるための移行計画
チームでルールに関する共通理解を持つことが、ルール導入の成功に繋がる。
リファクタリング例
Boolean型変数の命名規則にしたがってリファクタリングする具体的な例を示す。
リファクタリング前のコード
function processOrder(order, userVerified, premium, notification) {
if (!userVerified) {
return { success: false, error: 'User not verified' };
}
if (premium) {
applyDiscount(order);
}
const result = finalizeOrder(order);
if (notification) {
sendNotification(order.userId);
}
return { success: true, data: result };
}
リファクタリング後のコード
function processOrder(
order,
isUserVerified,
isPremiumUser,
shouldNotify,
) {
if (!isUserVerified) {
return { success: false, error: 'User not verified' };
}
if (isPremiumUser) {
applyDiscount(order);
}
const result = finalizeOrder(order);
if (shouldNotify) {
sendNotification(order.userId);
}
return { success: true, data: result };
}
リファクタリングのメリット
- 可読性の向上: 変数はBoolean型であることが明確になり、パラメータの目的も理解しやすくなる
- IDEサポートの改善: 自動補完機能がプレフィックスで絞り込めるようになる
- チーム全体の一貫性: プロジェクト全体で同じ命名規則が適用される
まとめ
Boolean型の変数に適した命名規則を採用することで、コードの可読性とメンテナンス性を効果的に高められる。プレフィックスを適切に利用し、否定形を避け、同じ意味を持つ異なる単語を避けることで、理解しやすいコードに近付ける。また、ESLintのようなツールを活用することで、これらの規則をチーム全体で実施することが可能となる。