つの重要なポイント
1. 読みやすく保守しやすいクリーンコードを書く
コード品質の唯一の有効な測定基準:WTFs/分
読みやすさが最優先。 クリーンコードは他の開発者が容易に理解できるものであるべきです。シンプルでエレガント、かつ無駄がないことが求められます。広範なコメントを必要とせずに意図を明確に表現するコードを書くよう努めましょう。意味のある変数名や関数名を使用し、関数は小さく焦点を絞り、論理的にコードを整理しましょう。
保守性が進化を可能にする。 変更が難しいコードは負担となります。コードを柔軟でモジュール化されたものに設計し、変化する要件に適応できるようにしましょう。DRY(Don't Repeat Yourself)やSOLIDの原則に従い、疎結合で高凝集なシステムを作りましょう。リファクタリングを徹底して行い、動作を変えずにコードの構造を改善しましょう。
クリーンコードは報われる。 クリーンコードを書くには初期の努力が必要ですが、長期的には大幅な時間と手間を節約できます。クリーンコードはデバッグ、拡張、保守が容易で、開発者が効率的に作業できるようになり、変更時にバグを導入するリスクを減らします。クリーンコードを開発の基本としましょう。
2. 意味のある命名規則に従う
変数、関数、クラスの名前は、存在理由、機能、使用方法をすべて説明するべきです。
意図を明示する名前を使う。 変数、関数、クラスの目的と動作を明確に伝える名前を選びましょう。単一文字の名前や暗号的な略語は避け、検索しやすい発音可能な名前を使用しましょう。例えば:
- 悪い例: d(経過日数)
- 良い例: elapsedTimeInDays
一貫性と正確さを保つ。 コードベース全体で一貫した命名規則を使用しましょう。曖昧さを避けるために正確な名前を使いましょう。例えば、getActiveAccounts()とgetActiveAccountInfo()のように意味のある区別を使用しましょう。クラス名は名詞、メソッド名は動詞にしましょう。
名前の長さはスコープに応じて。 スコープが大きい変数や関数には、より長く詳細な名前を使用しましょう。小さなローカルスコープには短い名前が許容されます。名前の長さはその使用範囲に比例するべきです。読みやすさと理解しやすさを最適化しましょう。
3. 関数を小さく焦点を絞る
関数は一つのことを行うべきです。それをうまく行うべきです。それだけを行うべきです。
小さいことは美しい。 関数は小さく、通常5〜10行程度にしましょう。一画面に収まり、即座に理解できるようにしましょう。長く複雑な関数を書くのではなく、適切な名前のヘルパー関数にコードを抽出しましょう。小さな関数は理解しやすく、テストしやすく、保守しやすいです。
一つのことをうまく行う。 各関数は単一の明確な目的を持つべきです。複数のことを行っている関数は、それらを別々の関数に抽出しましょう。関数が多くのことを行っている兆候には以下が含まれます:
- 複数の抽象レベル
- 複数のセクションやコードブロック
- 多数のパラメータ
一つの抽象レベルを維持する。 関数内のステートメントはすべて同じ抽象レベルにするべきです。高レベルのロジックと低レベルの詳細を混在させないようにしましょう。低レベルの操作は別の関数に抽出しましょう。これにより、関数が焦点を絞り、概念的にシンプルになります。
4. 適切なフォーマットと整理を実践する
コードのフォーマットはコミュニケーションであり、コミュニケーションはプロフェッショナルな開発者の最優先事項です。
一貫したフォーマットが重要。 コード全体で一貫したインデント、改行、スペースを使用しましょう。これにより読みやすさが向上し、認知負荷が軽減されます。チームとフォーマット標準を合意し、自動化ツールを使用してそれを強制しましょう。主なフォーマットガイドラインには以下が含まれます:
- 適切なインデント
- 一貫したブレースの配置
- 論理的な改行
- 適切な空白
コードを論理的に整理する。 関連するコードをグループ化し、無関係なコードを分離しましょう。空行を使用して論理的なセクション間に「段落」ブレークを作りましょう。関連する関数を近くに配置しましょう。ファイルは単一の概念やコンポーネントに焦点を当てましょう。適切な場合は、大きなファイルをより小さく焦点を絞ったものに分割しましょう。
標準的な規約に従う。 言語やコミュニティの標準的な規約に従いましょう。これにより、他の開発者にとってコードがより親しみやすく、アクセスしやすくなります。例えば、Javaでは:
- クラス名はPascalCaseを使用
- メソッド名はcamelCaseを使用
- 定数はALL_CAPSを使用
5. 依存関係を管理し重複を避ける
重複はソフトウェアのすべての悪の根源かもしれません。
重複を排除する。 重複したコードは抽象化の機会を逃しています。重複を見つけたら、共通のコードを再利用可能な関数やクラスに抽出しましょう。これにより、ロジックが集中し、変更の一貫性が向上し、保守性が向上します。注意すべき重複の種類には以下が含まれます:
- 同一のコードブロック
- わずかに異なる類似のアルゴリズム
- 繰り返されるswitch/caseやif/elseチェーン
依存関係を慎重に管理する。 モジュール間の依存関係を最小限に抑え、結合を減らしましょう。依存性注入や制御の反転を使用して、コードをよりモジュール化しテストしやすくしましょう。依存性逆転の原則に従い、具体的なものではなく抽象に依存しましょう。これにより、コードがより柔軟で変更しやすくなります。
最小知識の原則を使用する。 モジュールは操作するオブジェクトの内部について知らないようにするべきです。これにより、モジュール間の結合が減ります。例えば、デメテルの法則を使用しましょう。メソッドは以下のオブジェクトにのみメソッドを呼び出すべきです:
- 自身のオブジェクト
- パラメータとして渡されたオブジェクト
- 自身が作成するオブジェクト
- 直接のコンポーネントオブジェクト
6. エラーを優雅に処理する
エラー処理は重要ですが、ロジックを曖昧にするなら間違っています。
エラーコードではなく例外を使用する。 例外はクリーンで、コードの主要なロジックを乱しません。エラー処理をハッピーパスから分離できます。例外を使用する際には:
- 情報豊富なエラーメッセージを作成する
- 例外にコンテキストを提供する
- 呼び出し元のニーズに基づいて例外クラスを定義する
nullを返さない。 nullを返すとnullポインタ例外が発生し、コードがnullチェックで乱雑になります。代わりに:
- リストの場合はnullの代わりに空のコレクションを返す
- Nullオブジェクトパターンを使用する
- JavaのOptionalや関数型言語のMaybeを使用する
try-catch-finally文を最初に書く。 例外を投げる可能性のあるコードを書く際には、最初にtry-catch-finallyを記述しましょう。これにより、呼び出しコードのスコープと期待が定義されます。エラーシナリオでもリソースが適切に管理され、解放されることを保証します。
7. 徹底的な単体テストを書く
テストコードは本番コードと同じくらい重要です。
TDDの三つの法則に従う。 テスト駆動開発(TDD)はコードの品質と設計を向上させます:
- 本番コードを書く前に失敗するテストを書く
- 失敗を示すために必要なテストだけを書く
- テストに合格するために必要な本番コードだけを書く
テストをクリーンで保守しやすく保つ。 テストコードにも本番コードと同じ品質基準を適用しましょう。定期的にテストコードをリファクタリングし改善しましょう。よく構造化されたテストはドキュメントとして機能し、本番コードの恐れないリファクタリングを可能にします。
包括的なテストカバレッジを目指す。 エッジケース、境界条件、エラーシナリオをカバーするテストを書きましょう。コードカバレッジツールを使用してテストカバレッジのギャップを特定しましょう。100%のカバレッジがバグのないコードを保証するわけではありませんが、リファクタリングや変更に対する信頼を提供します。
8. 継続的にコードをリファクタリングする
キャンプ場を見つけたときよりもきれいにしておく。
機会を見つけてリファクタリングする。 コードを作業するたびに構造を改善しましょう。ボーイスカウトルールに従い、コードを見つけたときよりも良い状態にしておきましょう。小さな改善を積み重ねることで、コードの腐敗を防ぎます。一般的なリファクタリング技術には以下が含まれます:
- メソッドやクラスの抽出
- 明確さのためのリネーミング
- 複雑な条件の簡素化
- 重複の削除
テストで安全にリファクタリングする。 リファクタリングの前に堅牢なテストスイートを持っていることを確認しましょう。小さな変更を行い、頻繁にテストを実行しましょう。これにより、既存の機能を壊さないという自信が得られます。利用可能な場合は、自動リファクタリングツールを使用してエラーのリスクを減らしましょう。
価値の提供とリファクタリングのバランスを取る。 継続的なリファクタリングは重要ですが、進捗を麻痺させないようにしましょう。「十分に良い」状態を目指し、完璧を追求しないようにしましょう。最も問題のある、または頻繁に変更されるコード領域にリファクタリングの努力を集中しましょう。リファクタリングの価値をステークホルダーに伝え、継続的なコード改善のサポートを確保しましょう。
9. オブジェクト指向および関数型プログラミングの原則を適用する
オブジェクトはデータを抽象の背後に隠し、そのデータを操作する関数を公開します。データ構造はデータを公開し、意味のある関数を持ちません。
オブジェクト指向の原則を賢く使う。 カプセル化、継承、ポリモーフィズムなどの原則を適用して、柔軟でモジュール化された設計を作りましょう。SOLID原則に従いましょう:
- 単一責任の原則
- 開放閉鎖の原則
- リスコフの置換原則
- インターフェース分離の原則
- 依存性逆転の原則
関数型プログラミングの概念を活用する。 オブジェクト指向言語でも、関数型プログラミングの技術はクリーンなコードにつながります:
- 副作用のない純粋関数
- 不変データ
- 高階関数
- 関数の合成
問題に適したアプローチを選ぶ。 オブジェクト指向と関数型のパラダイムにはそれぞれ強みと弱みがあります。複雑なドメインを行動でモデル化する必要がある場合はオブジェクト指向設計を使用しましょう。データ変換や処理パイプラインには関数型アプローチを使用しましょう。多くの現代の言語はハイブリッドアプローチをサポートしており、システムの各部分に最適なツールを使用できます。
10. 並行性を慎重に考慮する
並行性はデカップリング戦略です。何が行われるかといつ行われるかを分離するのに役立ちます。
並行性の課題を理解する。 並行プログラミングは複雑さを増し、微妙なバグの可能性を引き起こします。一般的な問題には以下が含まれます:
- レースコンディション
- デッドロック
- シグナルの見逃し
- メモリの可視性の問題
並行性の懸念を分離する。 並行性に関連するコードを他のコードから分離しましょう。これにより、理解しやすくテストしやすくなります。スレッドを直接操作するのではなく、Executors、Futures、Actorsなどの抽象化を使用して並行性を管理しましょう。
不変性と純粋関数を優先する。 不変オブジェクトと純粋関数は本質的にスレッドセーフです。共有の可変状態を避けることで、多くの並行性問題を排除できます。可変状態が必要な場合は、適切な同期技術を使用し、アトミック変数や並行コレクションを検討しましょう。
最終更新日:
レビュー
『Clean Code』は、読みやすく保守しやすいコードを書くための原則について、主に好意的な評価を受けている。読者は、命名、関数、テストに関する実践的なアドバイスを高く評価している。一方で、本書のJavaに特化した内容や、いくつかの過度に厳格なガイドラインについては批判もある。多くの人が開発者にとって必読書と考えているが、経験豊富なプログラマーにはあまり役立たないと感じる人もいる。ケーススタディやリファクタリングの例は、一部の読者には高く評価される一方で、他の読者には過剰と見なされることもある。総じて、レビューアーたちは、本書がコードの品質に関する貴重な洞察を提供していると認めているが、すべての提案が普遍的に適用できるわけではないと一致している。