mcpField
C
clean-code

clean-code

github.com/marcioaltoe開発055 回インストール今日更新
リポジトリ

clean-code について

コードの作成、レビュー、リファクタリングに使えるクリーンコードのリファレンススキルです。可読性と保守性を軸に、原則やコードの問題点、提出前の確認項目をまとめています。

主な機能

  1. 01命名と関数設計
  2. 02コードの問題点の特定
  3. 03フォーマットとエラー処理
  4. 04コメント作成の指針
  5. 05オブジェクトカリステニクスの練習
  6. 06提出前チェックリスト

活用シーン

  1. 01明確な名前と関数構成を選ぶ
  2. 02保守性の観点からプルリクエストを確認する
  3. 03レガシーコードをリファクタリングして複雑さを減らす

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/marcioaltoe/skills --skill clean-code

インストール後、Claude Code で/clean-codeを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
references/
CODE_SMELLS.md
NAMING.md
OBJECT_CALISTHENICS.md

詳細

クリーンコード

「動くコード」を「クリーンなコード」へと変えるための原則です。すべての開発者が読み、理解し、改善できるコードを目指します。

「チームの誰もが簡単に理解できるなら、そのコードはクリーンです。」 — Dave Thomas

適用する場面

次のような場面で、これらのガイドラインを参考にしてください。

  • 新しいコードを書き、名前、関数シグネチャ、構造を決めるとき
  • プルリクエストの可読性と保守性をレビューするとき
  • レガシーコードをリファクタリングしたり、複雑さを減らしたりするとき
  • コードの不吉な臭いを特定して解消するとき
  • チームのコーディング標準を改善するとき

ルールのカテゴリ

優先度カテゴリ影響
1命名高 — コードのすべての行に影響します
2関数高 — 抽象化の中核となる単位です
3コードの不吉な臭い高 — 早期発見により劣化を防げます
4フォーマット中 — 一目で読みやすくなります
5エラー処理中 — 堅牢性と明確さにつながります
6コメント中 — ほとんどは避けられます
7オブジェクト・キャリステニクス目標 — より良い OO 設計のための演習です

1. 命名

読みやすさに最も大きな影響を与えるのは、適切な名前を付けることです。

優先順位:

  1. 一貫性 — 同じ概念には、どこでも同じ名前を使います
  2. 意図を明確に示す — どのように動くかではなく、何をするかを名前で表します
  3. 具体性 — data、info、manager、handler、utils などの曖昧な名前は避けます
  4. 検索しやすさ — grep で見つけられるだけの固有性を持たせます
  5. 簡潔さ — 短くしつつ、暗号のような名前は避けます
// Bad
const d = new Date();
const arr = users.filter((u) => u.a);
function process(data: any) {}

// Good
const createdAt = new Date();
const activeUsers = users.filter((user) => user.isActive);
function validatePayment(payment: Payment) {}

慣例:

  • クラス/型:名詞を使います(Customer、OrderRepository)。Manager、Data、Info は避けます。
  • メソッド/関数:動詞を使います(createOrder、validateEmail、isEligible)
  • 真偽値:疑問形にします(isActive、hasPermission、canWithdraw)
  • コレクション:複数形の名詞を使います(users、orderItems)

詳しいガイドラインは references/NAMING.md を参照してください。

2. 関数

// Bad — does too many things, unclear name
function handle(order: Order, sendEmail: boolean, log: boolean) {
  // validate, calculate, save, email, log — all in one
}

// Good — small, single-purpose, descriptive
function validateOrder(order: Order): ValidationResult { ... }
function calculateTotal(items: OrderItem[]): Money { ... }
function saveOrder(order: Order): Promise<void> { ... }

ルール:

  • 小さくする — 20 行未満を目指します
  • 一つのことだけを行う — 説明に「そして」を使うなら、分割します
  • 抽象化レベルを一つにする — ビジネスロジックと低レベルの詳細を混在させません
  • 引数を少なくする — 0~2 個が理想です。3 個以上ならパラメーターオブジェクトを使います
  • 副作用をなくす — または、save ではなく saveAndNotify のように、名前で明示します
  • コマンドとクエリを分離する — 関数は何かを実行するか、何かを返すかのどちらか一方にします

3. コードの不吉な臭い

リファクタリングが必要かもしれないコードの兆候です。バグではありませんが、設計上の摩擦を示しています。

不吉な臭い症状簡単な修正
長いメソッド20 行を超え、複数の関心事を扱っているメソッドを抽出する
大きなクラス多くの責務を持っているクラスを抽出する(SRP)
長い引数リスト引数が 3 個を超えているパラメーターオブジェクトを導入する
プリミティブ型への執着ドメイン概念に文字列や数値を使っている値オブジェクトでラップする
機能の羨望メソッドが自身のデータよりも他のクラスのデータを多く使っているメソッドを移動する
データの塊同じフィールドの組み合わせが一緒に現れるクラスを抽出する
switch 文コードベース全体で型チェックの switch/if-else を使っているポリモーフィズムに置き換える
発散する変更一つのクラスがさまざまな理由で変更される責務ごとに分割する
ショットガン手術一つの変更で多くのファイルに手を加える関連するコードをまとめる
投機的な汎用性「念のため」の抽象化削除する(YAGNI)
デッドコード到達不能または未使用のコード削除する
メッセージチェーンa.getB().getC().doSomething()委譲先を隠す(デメテルの法則)

詳しい例とリファクタリングの戦略は references/CODE_SMELLS.md を参照してください。

4. フォーマット

新聞の比喩 — コードは新聞記事のように上から下へ読み進められるようにします。最初に概要を示し、その下に詳細を記述します。

class OrderProcessor {
  // Public API first — the "headline"
  process(order: Order): ProcessResult {
    this.validate(order);
    const total = this.calculateTotal(order);
    return this.save(order, total);
  }

  // Supporting methods below, in order of appearance
  private validate(order: Order) { ... }
  private calculateTotal(order: Order): Money { ... }
  private save(order: Order, total: Money): ProcessResult { ... }
}

ルール:

  • 関連するコードは近くにまとめます(縦方向の密度)
  • 概念の区切りには空行を入れます(縦方向の開放性)
  • 変数は使用箇所の近くで宣言します
  • 呼び出し元を呼び出し先より上に置きます(段階的詳細化のルール)
  • インデントを一貫させます — 妥協は認められません

5. エラー処理

  • エラーコードより例外 — 正常系の処理をすっきり保てます
  • nullを返さない — undefined、Result型、または例外を使います
  • nullを渡さない — あらゆる場所で防御的なチェックが必要になります
  • 迅速に失敗させる — 境界で検証し、内部の処理を信頼します
  • 具体的な例外 — 汎用的なErrorよりInsufficientFundsErrorを使います
// Bad — null checks cascade through codebase
function getUser(id: string): User | null {
  return db.find(id);
}
const user = getUser(id);
if (user === null) { ... } // Every caller must check

// Good — throw at boundary, trust within domain
function getUser(id: string): User {
  const user = db.find(id);
  if (!user) throw new UserNotFoundError(id);
  return user;
}

6. コメント

「悪いコードにコメントを付けるのではなく、書き直しましょう。」

多くのコメントは、コードで意図を表現できていないことを補っています。コメントよりも、 自己文書化されたコードを優先しましょう。

良いコメント:

  • 理由(ビジネス上の理由、すぐには分からない判断)
  • 警告(「Xのため処理が遅い」、「ここでは順序が重要」)
  • 背景情報を添えたTODO(課題へのリンク)
  • 法的事項/ライセンスのヘッダー
  • 公開APIのドキュメント(ライブラリ向けのJSDoc)

悪いコメント:

  • コードの動作を言い換えたもの(// increment counter)
  • コメントアウトされたコード(そのためにgitがあります)
  • 作業記録/変更履歴のコメント
  • 冗長なもの(// constructor、// getters)
  • 義務的な定型文
// Bad — restates the obvious
// Check if user is active
if (user.isActive) { ... }

// Good — explains a non-obvious business rule
// Users who haven't verified email within 30 days are auto-deactivated
// per compliance requirement GDPR-2024-42
if (user.isAutoDeactivated) { ... }

7. オブジェクト・カリステニクス

Jeff Bayが考案した、オブジェクト指向設計を改善するための9つの練習です。これらは目標として 捉えてください。練習中は厳格に、本番環境では現実的に適用します。

#ルール目標
1メソッドごとのインデントは1段階まで積極的にメソッドを抽出する
2elseを使わない早期リターン、ガード節、ポリモーフィズム
3すべてのプリミティブ型にドメイン上の意味を持たせる値オブジェクト(Email、Money、UserId)
4コレクションを第一級オブジェクトにする配列をドメイン固有のクラスでラップする
51行につきドットは1つまでデメテルの法則 — 直接関わる相手とのみやり取りする
6略語を使わない名前が長すぎるなら、クラスの責務も多すぎます
7エンティティを小さく保つクラスは50行未満、メソッドは10行未満
8インスタンス変数を制限する2〜3個を目指し、クラスの責務を絞る
9ゲッター/セッターを使わないオブジェクトには振る舞いがあり、データだけではありません

各ルールの例については、references/OBJECT_CALISTHENICS.mdを参照してください。

実装チェックリスト

コードを提出する前に確認してください。

  • 新しいチームメンバーが質問せずに理解できますか?
  • 名前は意図が伝わり、一貫していますか?
  • 各関数は、ちょうど1つのことだけを行っていますか?
  • ここで修正できるコードの臭いはありませんか?
  • コメントは「何を」ではなく「なぜ」を説明していますか?
  • エラー処理はすっきりしていて、具体的ですか?
  • コードを、見つけたときより良い状態にしましたか?(ボーイスカウト・ルール)

コメント