
命名は主観的で状況に依存し、それは芸術です。そして、ほとんどの芸術と同様に、私たちはパターンを発見します。私は他の人のコードを読むことで多くを学びました。この記事では、私が他の人のコードを読む際に、彼らが従っていてほしかった9つのガイドラインをまとめました。
ソフトウェアエンジニアがクラスを開いたとき、彼女は名前に基づいて、そのクラスの責任を知るべきです。はい、命名は車輪の一つのスポークに過ぎないことは分かっています。物理的および論理的構造も、複雑さと同様に、コードの理解において重要な役割を果たします。この記事では、コードの理解に最も大きな影響を与えると感じているため、命名にのみ焦点を当てています。
意図を明確にしない限り、型を含めない
型は、プログラミング型(string、int、decimal)から責任のグループ化(Util、Helper、Validator、Event等)まで、何でもあり得ます。多くの場合、それは意図を表現しない分類です。
例を見てみましょう:StringHelperという名前はあまり表現していません。stringはシステム型であり、Helperは曖昧で、StringHelperは意図よりも「方法」について語っています。代わりに、名前をDisplayNameFormatterに変更すると、意図のより明確な図が得られます。DisplayNameは非常に具体的で、Formatterは結果を表現します。Formatterは型である場合もそうでない場合もありますが、意図を表現しているので問題ありません。
常に例外があります。例えば、ASP.Net MVCでは、コントローラーは「Controller」で終わらなければならず、そうでなければアプリケーションが機能しません。ドメイン駆動設計(DDD)などのパラダイムを使用する場合、「Services」、「Repository」、「ValueType」、「Model」などの名前はDDDにおいて意味を持ち、責任を表現します。
例えば、UserRepositoryは、ユーザーデータがデータストアから取得され、保存されることを意味します。
メタファーを避ける
メタファーは文化的であり、他の文化のエンジニアは意図を理解できない可能性があります。
アメリカの一般的なメタファー:
- Beating a dead horse(無駄な努力)
- Chicken or the egg(鶏が先か卵が先か)
- Elephant in the room(見て見ぬふりをされている問題)
ニュージーランドの一般的なメタファー:
- Spit the dummy(かんしゃくを起こす)
- Knackered(疲れ果てた)
- Hard yakka(重労働)
動詞を使う
Steve Yeggeは名詞よりも動詞を使うことについて(非常に長い)ブログ投稿を書きました。
彼のポイントは動詞を使うことです。アプリケーションは名詞で構成されていますが、名詞は何もしません。システムは名詞だけでは役に立たず、代わりにメソッドの名前でアクションを表現します。
例えば、UserAuthentication*(名詞).AuthenticateUser(アクション/動詞)*は、ユーザーの認証情報を検証するアクションを表現します。
説明的であること
説明的であること、詳細が多いほど良い — 名前で責任を表現してください。
自分に問いかけてください:このクラスや関数がうまく行う一つのことは何ですか?
名前を見つけるのに困難がある場合、クラスや関数は複数の責任を持っている可能性があり、単一責任原則に違反している可能性があります。
意図をコメントに頼らない
コメントはコードに追加のコンテキストを提供する素晴らしい方法ですが、コメントに頼らないでください。クラスやメソッドの名前は単独で成り立つべきです。
Martin Fowler、Kent Beck、John Brant、William Opdyke、Don Robertsによる「リファクタリング:既存コードの設計改善」では:
…コメントはしばしば消臭剤として使用されます。厚くコメントされたコードを見て、コメントがそこにあるのはコードが悪いからだということに気づくのは驚くほど頻繁です。
「リファクタリング」の著者からの別の素晴らしい引用:
コメントを書く必要を感じたときは、まずコメントが不要になるようにコードをリファクタリングしてみてください。88ページ
コードがリファクタリングされ、メソッドにカプセル化されるとき、新しいメソッドを活用できる他の場所、決して予想していなかった新しいメソッドを使用する場所を見つけることが多くあります。
メソッドを呼び出すとき、消費者はメソッドについて特別な何かを知る必要がある場合があります。その特別さが名前の一部であれば、消費者はソースコードを確認する必要がありません。
コメントを名前に組み込む例を示します。
コメント付き:
// without tracking
var user = GetUserByUserId(userId);
コメントをメソッド名に含むようにリファクタリング:
var userWithOutTracking = GetUserByUserIdWithoutTracking(userId);
他のエンジニアは、ソースコードを読んだりコメントを見つけたりする前に、このメソッドにトラッキングがないことを知ることができます。
コメントは、可能な場合の最後の防御線であるべきです。物理的および論理的構造と名前を使用して意図を伝える他の方法に頼ってください。
曖昧な意味を持つ名前の使用を控える
曖昧な意味を持つ名前を避けてください。曖昧な名前の意味はプロジェクトごとに変わり、新しいエンジニアにとって意図の理解を困難にします。
一般的な曖昧な名前のリスト:
- Helper
- Input
- Item
- Logic
- Manager
- Minder
- Moniker
- Nanny
- Overseer
- Processor
- Shepherd
- Supervisor
- Thingy
- Utility
- Widget
ビジネスドメインと同じ言語を使う
コードでビジネスドメインと同じ用語を使用してください。これにより、エンジニアと専門家(SME)が同じ語彙を共有するため、アイデアを簡単にコミュニケーションできます。共有語彙がない場合、翻訳が発生し、必然的に誤解を招きます。
私が取り組んだあるプロジェクトでは、ビジネスは「Pupil」から始まり、その後「Student」に切り替えました。ソフトウェアエンジニアは、用語の変更を反映するためにソフトウェアを更新することはありませんでした。新しいエンジニアがプロジェクトに参加したとき、ほとんどがPupilとStudentは異なる概念だと信じていました。
業界用語を使う
可能な場合は、ソフトウェア業界全体で意味を持つ用語を使用してください。
ほとんどのソフトウェアエンジニアは、「factory」という名前のものを見ると、すぐにファクトリーパターンを思い浮かべます。
「クリーンアーキテクチャ」や「ドメイン駆動設計」などの既存のアプリケーションパラダイムを使用することで、アイデアの共有が促進され、エンジニア同士がアイデアをコミュニケーションするための共通言語が作成されます。
最悪の命名は、業界全体の用語を流用して異なる意味を与えることです。
ブール値の命名について…
ブール名は常に、trueまたはfalseの値を持つ質問への答えであるべきです。
例えば、isUserAuthenticated、答えはyes *(true)*またはno *(false)*のいずれかです
次のような単語を使用してください:
- Has
- Does
- Is
- Can
否定された名前を避けてください。例えば:
否定された変数名:
var IsNotDeleted = true; // これは混乱を招く
if(!IsNotDeleted) { // 値が否定されるとさらに混乱する
//Do magic
}
否定されていない変数名:
var IsDeleted = true; // これは混乱を招く
if(!IsDeleted) {
//Do magic
}
終わりに
表現力豊かな名前を選ぶことは、意図、設計、ドメイン知識を次のエンジニアに伝えるために重要です。多くの場合、私たちは欠陥を修正したり新機能を組み込んだりするためにコードに取り組み、それがどのように動作するかを理解しようとして、頭の中で継続的にコードをコンパイルしています。命名は、前のエンジニアが何を考えていたかのヒントを与えてくれます。過去と未来のエンジニア間のこのコミュニケーションなしには、アプリケーションの成長において自分たちを不利にし、プロジェクトを失敗に導く可能性があります。
著者:Chuck Conwayはソフトウェアエンジニアリングと生成AIを専門としています。ソーシャルメディアで彼とつながりましょう:X (@chuckconway) または YouTube をご覧ください。