clean-code について
読みやすくテストしやすいコードを保つための、ソフトウェア開発者向けスキルです。命名、関数、コメント、エラー処理、クラス、テスト、コードスメルをまとめ、詳しい章への参照も示します。
主な機能
- 01意図が伝わる命名
- 02小さく役割を絞った関数
- 03コメントとエラー処理の指針
- 04クラス設計と凝集性の原則
- 05テストと TDD の実践
- 06コードスメルの一覧
活用シーン
- 01コードの可読性を確認
- 02大きすぎる関数やクラスをリファクタリング
- 03単体テストの構成を改善
- 04重複コードやデッドコードを特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ratacat/ claude-skills --skill clean-codeインストール後、Claude Code で/clean-codeを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
chapters/classes.mdcomments.mderror-handling.mdfunctions.mdnames.mdobjects-and-data.mdtests.md詳細
クリーンコード
概要
クリーンコードは、よく書かれた文章のように読めます。すべての名前が意図を明らかにします。すべての関数が物語を語ります。すべてのクラスに目的がひとつあります。目指すのは、動くだけのコードではありません。ほかの人がすばやく理解し、安全に変更し、自信を持って拡張できるコードです。
「クリーンコードはいつも、気を配る人が書いたように見えます。」 — Michael Feathers
「各ルーチンがほぼ期待どおりの内容だとわかるとき、あなたはクリーンコードに取り組んでいるのです。」 — Ward Cunningham
ボーイスカウト・ルール: コードを見つけたときよりもきれいな状態にしておきましょう。わずかな改善でも、すべてのコミットで品質を高めるべきです。小さな改善は積み重なります。
章の参照先
このスキルでは、概要とクイックリファレンスを提供します。例を含む詳しいガイダンスについては、各章のファイルを参照してください。
chapters/names.md- 意味のある名前(意図を明らかにする、検索しやすい、発音しやすい)chapters/functions.md- 関数(小さく、ひとつのことを行い、引数を少なくする)chapters/comments.md- コメント(避けるべき理由、許容される内容)chapters/objects-and-data.md- オブジェクトとデータ構造(デメテルの法則、DTO)chapters/error-handling.md- エラー処理(例外、null の処理、特殊ケースパターン)chapters/tests.md- 単体テスト(TDD、F.I.R.S.T.、クリーンなテスト)chapters/classes.md- クラス(SRP、凝集度、OCP、DIP)smells-and-heuristics.md- コードの臭いの完全なリファレンス(説明付きの66項目)
クイックリファレンス:名前
名前は意図を明らかにし、検索しやすいものにしましょう。
| ルール | 悪い例 | 良い例 |
|---|---|---|
| 意図を明らかにする | d | elapsedTimeInDays |
| 誤解を招かない | accountList(List ではない) | accounts |
| 違いを明確にする | a1, a2 | source, destination |
| 発音しやすい | genymdhms | generationTimestamp |
| 検索しやすい | 7 | MAX_CLASSES_PER_STUDENT |
| クラス=名詞 | Process | Customer, Account |
| メソッド=動詞 | data | postPayment(), save() |
避けるべき名前: クラス名に Manager、Processor、Data、Info を使うこと。責務が不明確であることを示唆します。
重要な考え方: 変数の内容を説明するコメントが必要なら、コメントを書くのではなく、変数名を変えましょう。
クイックリファレンス:関数
サイズとスコープ
- 理想: 4~10行、20行を超えることはまれ
- インデントの深さ: 1~2段を超えない
- ひとつのことを行う — 元の内容を言い換えるだけではない名前で別の関数を抽出できるなら、その関数は多くのことをしすぎています
引数
| 数 | 指針 |
|---|---|
| 0 | 最良 |
| 1 | 良好 |
| 2 | 許容範囲 |
| 3以上 | 避ける — オブジェクトにまとめる |
フラグ引数(ブール値)は見苦しいものです。 関数が2つのことを行うと宣言してしまいます。分割しましょう。
# Bad
def render(is_suite: bool): ...
# Good
def render_for_suite(): ...
def render_for_single_test(): ...
主なルール
- コマンド・クエリ分離: 何かを実行するか、何かに答えるかのどちらかにし、両方は行わない
- 副作用をなくす:
checkPassword()がセッションも初期化するなら、その名前はうそをついています - エラーコードより例外を優先する: 通常処理とエラー処理を分離できます
- try/catch ブロックを抽出する: エラー処理もひとつの役割です
クイックリファレンス:コメント
コメントは、よくても必要悪です。コメントの適切な使い方は、コードで自分の意図を表現できないことを補うことです。
削除するコメント
- 冗長なコメント — コードの内容を言い直すもの
- 作業記録/変更履歴 — git を使う
- コメントアウトされたコード — 忌むべきものです。git が記録しています
- ノイズ —
// default constructor、// increment i - 閉じ波括弧の説明 —
} // end ifはネストが深すぎることを示しています
許容されるコメント
- 法的な告知
- 意図の説明(何をするかではなく、なぜそうするか)
- 結果に関する警告(
// takes 30 minutes) - TODO(ただし、きちんと片付けること)
- 外部ライブラリの動作を明確にする説明
ルール: コメントを書きたくなったら、まずコードをリファクタリングして、コメントが不要になるようにできないか試しましょう。
クイックリファレンス:エラー処理
エラー処理は重要ですが、ロジックを分かりにくくするなら間違いです。
| ルール | 詳細 |
|---|---|
| 戻り値コードより例外を使う | アルゴリズムとエラー処理を分離します |
| コンテキストを提供する | 失敗した操作と失敗の種類を含めます |
| サードパーティ API をラップする | 依存関係を最小限に抑え、モックを可能にします |
| 特例パターンを使う | 特例(空のリスト、デフォルト値)を処理するオブジェクトを返します |
| null を返さない | 作業を増やし、NullPointerException を招きます |
| null を渡さない | null を返すよりも悪いため、デフォルトで禁止します |
# Bad - null checks everywhere
if employees is not None:
for e in employees:
total += e.pay
# Good - return empty collection instead of null
for e in get_employees(): # Returns [] if none
total += e.pay
クイックリファレンス:クラス
単一責任の原則(SRP)
クラスが変更される理由は、ただ一つであるべきです。
確認事項:
- 簡潔な名前を付けられますか?(
Manager、Processor、Superは避けます) - 「if」「and」「or」「but」を使わずに、25 語以内で説明できますか?
凝集度
メソッドはクラスのインスタンス変数を使用するべきです。特定の変数を使うメソッドが集まり、ほかの変数を使わない場合は、クラスを分割するべきです。
オープン・クローズドの原則(OCP)
クラスは拡張に対して開かれ、変更に対して閉じられているべきです。既存のコードを変更するのではなく、サブクラス化によって新しい振る舞いを追加します。
依存性逆転の原則(DIP)
具体的な詳細ではなく、抽象に依存します。テストしやすくするために依存関係を注入します。
# Bad - can't test without network
class Portfolio:
def __init__(self):
self.exchange = TokyoStockExchange()
# Good - injectable, testable
class Portfolio:
def __init__(self, exchange: StockExchange):
self.exchange = exchange
クイックリファレンス:テスト
TDD の三つの法則
- 失敗するテストを書くまでは、本番コードを書かない
- テストは、失敗させるのに十分な分だけ書く
- 本番コードは、テストを通すのに十分な分だけ書く
F.I.R.S.T. の原則
- 高速(Fast) — 頻繁に実行できるよう、素早く実行します
- 独立(Independent) — 互いに依存させません
- 再現可能(Repeatable) — どの環境でも同じ結果になります
- 自己検証可能(Self-Validating) — 真偽値で結果を示します(合格/不合格)
- 適時(Timely) — 本番コードを書く直前に作成します
クリーンなテスト
- 読みやすさが最も重要です
- **準備・実行・確認(BUILD-OPERATE-CHECK)**パターンを使います
- ドメイン固有のテスト用言語を作ります
- 一つのテストにつき一つの概念(アサーションは必ずしも一つではありません)
警告: テストコードは本番コードと同じくらい重要です。テストを劣化させれば、コードも劣化します。
オブジェクトとデータ構造
| 概念 | 隠すもの | 公開するもの | 追加しやすいもの |
|---|---|---|---|
| オブジェクト | データ | 関数 | 新しい型 |
| データ構造 | なし | データ | 新しい関数 |
すべてがオブジェクトであるという考えは迷信です。 データに対して処理を行う、シンプルなデータ構造が必要な場合もあります。
デメテルの法則
メソッドが呼び出してよいのは、次のメソッドだけです。
- クラス自体のメソッド
- 自分で作成したオブジェクトのメソッド
- 引数として渡されたオブジェクトのメソッド
- インスタンス変数に保持されたオブジェクトのメソッド
許可された関数が返したオブジェクトのメソッドは呼び出さないでください(メソッド呼び出しの連鎖):
# Bad
output_dir = ctxt.get_options().get_scratch_dir().get_absolute_path()
# Good - tell the object to do the work
bos = ctxt.create_scratch_file_stream(class_file_name)
最も重要なコードの臭い
第 17 章の包括的な一覧から、特に重要なものを紹介します。
G5:重複
ソフトウェアにおけるすべての悪の根源です。 重複するたびに、抽象化の機会を逃しています。
- 同一のコード → 関数に抽出します
- 繰り返される switch/if-else → ポリモーフィズムにします
- 似たアルゴリズム → Template Method または Strategy パターンにします
G30:関数は一つのことだけを行う
関数から別の関数を抽出できるなら、元の関数は一つ以上のことを行っていました。
N1:説明的な名前を選ぶ
コードの読みやすさの 90%は名前で決まります。時間をかけて適切な名前を選びます。
F1:引数が多すぎる
引数はゼロが最善で、次に一つ、二つ、三つです。それ以上は正当な理由が必要です。
F3:フラグ引数
ブール値の引数は、関数が二つのことを行うことを意味します。分割してください。
G9:デッドコード
実行されないコードです。削除してください。バージョン管理が記録を保持します。
G11:一貫性の欠如
ある方法で何かを行うなら、類似するものもすべて同じ方法で行います。
C5:コメントアウトされたコード
許しがたいものです。すぐに削除してください。
クラフト
「クリーンなコードを書くには、入念に身につけた『清潔さ』の感覚をもとに、数多くの小さな技法を規律正しく用いる必要があります。コードセンスこそが鍵です。」
クリーンなコードは、ルールに機械的に従うだけでは書けません。クラフトを大切にし、自分のコードを読む人を尊重し、プロフェッショナルな仕事に誇りを持つという価値観が、規律ある実践を支えます。
どうすればクリーンなコードを書けるでしょうか? 最初の草稿はぎこちないものです。長い関数、ネストしたループ、場当たり的な名前、重複。そこから磨き上げていきます。関数を切り出し、名前を変え、重複をなくし、メソッドを短くします。最初からクリーンなコードを書ける人はいません。
ソフトウェアを動くようにすることと、クリーンにすることは別の作業です。私たちの多くは頭の中で扱えることに限りがあるため、まずコードを動かすことに集中します。問題は、プログラムが動けば完了だと考えてしまう人があまりにも多いことです。 整理整頓と清潔さへと意識を切り替えられません。膨れ上がったクラスを疎結合な単位に分割するために戻るのではなく、次の問題に移ってしまいます。
そうしないでください。戻りましょう。きれいに整えましょう。見つけたときよりも良い状態にしておきましょう。