a-philosophy-of-software-design

Rob Zapp 作インストールはまだありませんいいねはまだありません2026年10月8日 に更新カテゴリー: エンジニアリング

できること

変更がエクスポートまたはインポート可能な名前を追加したり、モジュール、クラス、コンポーネント、ヘルパー、フック、サービス、ラッパーを作成したり、繰り返しのコードを集約したり、APIを変更したりする際に、コードの作成、変更、レビュー時に使用してください。Ousterhoutのルール(深いモジュール、情報隠蔽、複雑さの低減)に加え、コード共有の不変テスト、読者コストテスト、最後に必須の設計ノートを含みます。

インストールすると、このページがデスクトップ版 AgentsRoom で開きます。アプリが未インストールの場合はダウンロードページに移動します。

SKILL.md

---
name: a-philosophy-of-software-design
description: 変更がエクスポートまたはインポート可能な名前を追加したり、モジュール、クラス、コンポーネント、ヘルパー、フック、サービス、ラッパーを作成したり、繰り返しのコードを集約したり、APIを変更したりする際に、コードの作成、変更、レビュー時に使用してください。Ousterhoutのルール(深いモジュール、情報隠蔽、複雑さの低減)に加え、コード共有の不変テスト、読者コストテスト、最後に必須の設計ノートを含みます。
---

# ソフトウェア設計の哲学(John Ousterhout)

## このスキルを使うとき

コードを設計、記述、変更、またはレビューするときにこのスキルを使います。モジュール設計、APIの変更、分解、リファクタリング、名前付け、コメント、テスト、パフォーマンス作業に適用されます。変更が不自然に感じるときや、1つの変更が多くのファイルにまたがるときにも使ってください。

## 修正すべき偏り

動作するコードは単純なコードと同じではありません。小さな部品、よく知られたパターン、フラグ、ラッパー、追加のドキュメントは設計をより複雑にすることがあります。これは、読者が知るべきことが増えたり、他のモジュールに知識が漏れたりするときに起こります。

## 判断ルール

- 設計は複雑さをどれだけ減らすかで評価します。読者の負担を減らす設計を優先してください。複雑さには4つの兆候があります。1つの変更で多くの場所を編集する必要がある。依存関係が隠れている。手順が固定された順序で行われなければならない。読者が多くの事実を覚えておかなければならない。
- 設計は継続的な作業として扱います。最初のパッチが動作しても、後の変更を難しくするなら完成とは言えません。インターフェース、モジュール分割、抽象化の決定では、2つ以上の設計案を比較してください。
- 深いモジュールを優先します。深いモジュールは小さなインターフェースを持ち、大量の複雑さを隠します。パススルーサービス、薄いライブラリラッパー、小さなヘルパーモジュールは拒否してください。名前を追加するだけで読者の負担を減らさない抽出は拒否します。
- インターフェースは呼び出し側が知るべきことを中心に設計し、実装の仕組みを中心にしないでください。壊れやすいセットアップ手順、モードフラグ、設定ノブ、内部の選択を示す引数は避けてください。
- 変わりうる決定は隠してください。例として内部表現、ストレージの形状、プロトコル、ファイル形式、パフォーマンストリックがあります。帳簿管理、正規化、エッジケースも例です。これらは知識を持つモジュール内に保持してください。
- 複雑さは詳細を持つモジュールに引き下げてください。呼び出し側により単純な契約を提供し、各呼び出し箇所の繰り返し作業をなくすなら、より複雑な実装を受け入れてください。
- モジュールは適切なレベルで一般化してください。1つの呼び出し側に合わせてモジュールを作らないでください。将来のニーズのためにあいまいな抽象化を追加しないでください。まれなエッジケースはメインパスから外し、特別な振る舞いは別の場所に置いてください。
- モジュールの結合や分割は総合的な複雑さで判断してください。サイズ、コードの実行順、習慣、見た目で判断しないでください。関連する状態、振る舞い、ルール、決定は一緒に保ちます。新しい境界がより深く、読者がそれぞれを単独で理解できる場合にのみ分割してください。
- 例外のセットは小さくしてください。可能なら、インターフェースやルールを変えて無効な状態が起こらないようにします。すべての呼び出し側に同じ防御コードを繰り返させないでください。
- コメントは複雑さを減らすために使います。インターフェース契約、守るべきルール、隠れた設計決定とその理由を書きます。呼び出し側が知る必要のない難しい事実も書きます。コードをコメントで繰り返さないでください。悪い名前、悪い分割、混乱する制御フローを隠すためにコメントを使わないでください。
- 名前、一貫性、明快さは設計情報として扱います。名前は読者に抽象化を伝え、仕組みを伝えません。関連する操作は同じ規約を使います。読者を驚かせるコードは短くても複雑さを増します。
- テストは公開契約と安定したAPIに対して書きます。隠れた複雑さや特別なケースはそれらの契約を通じてテストします。テストのしやすさのために浅いまたは漏れのあるインターフェースを強制しないでください。
- パフォーマンスの変更、パターン、パラダイム、フレームワークは2つの理由のいずれかでのみ追加します。コードベースの複雑さを減らすか、トレードオフが必要である証拠がある場合です。各最適化は安定したインターフェースの背後に隠してください。

## シグナルとそれぞれへの対応

- 機能が不自然、変更がファイルにまたがる、レビュー担当者が隠れた依存関係を見つけなければならない。対応:情報隠蔽不足や浅いモジュールを探します。固定順序の手順や呼び出し側が負う複雑さも探します。
- モジュール、レイヤー、サービス、ヘルパー、ラッパー、ファサードを追加した。パターン、オプション、コールバック、引数を追加した。対応:追加した複雑さよりも多くの複雑さを隠していることを示してください。
- APIを変更した。対応:通常の呼び出し側が知るべきことを確認してください。呼び出し側は呼び出し順序、表現、ストレージを知る必要はありません。呼び出し側はトランスポート、キャッシュ、プロトコル、ファイル形式を知る必要はありません。呼び出し側は内部ワークフローや多くのセットアップ手順を知る必要はありません。
- 特別なケース、フラグ、例外パス、条件、呼び出し側が見えるコンテナを追加した。対応:まず所有モジュールが代わりに何ができるかを考えてください。無効な状態を除去し、異常な振る舞いを隔離し、より強力な操作を提供できます。
- コードを分割した、関数を抽出した、変数を追加した。対応:新しい境界や名前が意味を持つか確認してください。ジャンプ、通過する状態、呼び出し側が見る中間ステップを追加するだけではいけません。
- コードに`prepare`、`process`、`finalize`のような段階がある、または呼び出し側が段階的にオブジェクトを構築しなければならない。対応:時間順序が本当の概念か確認してください。そうでなければ安定した責任に基づいてコードを整理してください。
- 名前があいまい、仕組みを名前にしている、一貫性がない、読者を驚かせる。対応:抽象化の境界を再考してください。ほぼ正しい名前は受け入れないでください。
- コメントが長い、コードを繰り返す、混乱するインターフェースを説明する、使用法を説明するために内部を示す。対応:抽象化を変えるか、欠けている契約をインターフェースに移してください。
- パフォーマンスを最適化した。対応:まず測定し、最適化を隠してください。トレードオフが必要である証拠なしにモジュールの深さや情報隠蔽を諦めないでください。
- テストやレビューを行う。対応:公開された振る舞いとインターフェース契約を見てください。安定したAPIの背後にある隠れた複雑さや抽象化の背後にある特別なケースも見てください。

## 最終チェックリスト

- 変更はシステムの理解、変更、検証、拡張の労力を減らしていますか?
- 各インターフェース要素、ラッパー、レイヤー、ヘルパー、オプション、名前は、それを正当化するだけの十分な複雑さを隠していますか?
- 重要な決定は一箇所にありますか?依存関係は見えるようになっていますか?呼び出し元が知るべき制約は書き残されていますか?変更可能な内部は保護されていますか?
- 一般的なケースは余計な手順なしに動作しますか?まれな制御、特殊ケース、パフォーマンストリック、例外の詳細は一般的な経路から外れていますか?
- 名前は正確で一貫していますか?コメントは最新で、コードの繰り返しではありませんか?コードは既存の規約に従っていますか(新しい情報があって変更の理由がある場合を除く)?

## Gate

変更が他のコードがエクスポートまたはインポートできる名前を追加する場合は、完全なチェックリストを使用してください。変更がモジュール、クラス、コンポーネント、ヘルパー、フック、サービス、ラッパーを作成する場合や、繰り返しのコードを一箇所にまとめる場合にも使用します。リネーム、コードモッド、設定変更、データ変更、一行修正は必要ありません。

## 不変条件テスト:一緒に変わるコードだけを共有する

- 共有コードは、名前を付けられるルールを保護する場合にのみ抽出します。証拠は共変化です:履歴がコピーが一緒に修正または変更されたことを示します。見た目が似ていて独立して変わるコードは韻を踏んでいるだけです。韻は重複として残します。三つの似たブロックはルールの証明にはなりません。
- 修正は問題を移動させるのではなく、取り除かなければなりません。六つのキャストを一つの汎用キャストヘルパーにまとめても、六つのキャストのままです。キャストが隠していた型付きマッパーを書いてください。
- 抽象化が間違っている場合は、コードをインラインに戻し、重複を許容します。フラグで抽象化を曲げてはいけません。
- サイズだけでコードを分割しないでください。ある決定を隠す400行のモジュールは、同じ結合を漏らす100行のモジュール4つより良いです。
- Clean CodeやSOLID(非常に小さな関数、責任ごとに一クラス)を機械的に読むと浅いモジュールになります。このスキルはその圧力より優先されます。

## 読者コスト:三つ目のテスト

深さテストと不変条件テストは境界の存在を決めます。読者コストテストは境界周辺のコードが変更しやすいかを決めます。次の読者(人またはエージェント)は読む必要のある行ごとにコストを払います。エージェントはトークンで支払います。エージェントはテキスト検索、部分読み、型チェック、テストでコードを見つけます。

- **見つけやすさ。** 各概念に一つの名前を使い、どこでも同じ綴りにします。プレーンテキスト検索で見つかるようにします。欠陥:文字列から作られた名前、インポートの副作用による配線、一つの概念に二つの名前。定義を隠す再エクスポートチェーンも欠陥です。
- **早期停止。** 契約はファイルの先頭かエクスポートの上に置きます。約束すること、隠すこと、決してしないことを述べます。そうすれば読者は早く止められます。
- **機械検査可能。** 各境界の入出力に正確な型を使い、型チェックで呼び出し元の読みを置き換えます。欠陥:`any`、単純な辞書、意味が本体にしかないブールフラグ。
- **見える結合。** 二箇所は一緒に変わらなければなりません。共有型、テスト、単一ソースで強制します。できなければ両方にマークを付けます。
- **ノイズなし。** コードを繰り返すコメントやコメントアウトされたコードを削除します。死んだ分岐や変更履歴を記録するコメントも削除します。置き換えの隣に残る古い経路も削除します。
- **予測可能。** リポジトリの既存のレイアウトに従います。読者が探す場所にテストを置き、単独で実行できるようにします。

ファイルサイズは意図的にこのリストに入れていません。非常に大きなファイルは二つ目の隠れた決定を探す理由です。ファイルを分割する理由にはなりません。

## 安全性

既存コードの場合、まず現在の動作を保持するテストを書きます。その後モジュールを深くします。新規コードの場合は、意図した動作を定義するテストを書きます。

## 設計ノート(Gateが適用される場合に必須)

Gateが適用される場合、プルリクエストの説明に `## Design note` の見出しを付けたセクションを作ります。2~4行書きます:

- 追加した各境界とそれが隠す決定。
- 意図的に残した各重複とその理由。
- 受け入れた浅い部分とその理由。

Gateが適用されない場合は、`## Design note` の後に `Gate not applicable: <理由>` と書きます。設計ノートは最終ステップのサマリーにも入れてください。

## レビューモード

他のエージェントや人が書いたコードをレビューまたはテストするときにこのセクションを使います。

1. 設計ノートを確認します。Gateが適用されていてプルリクエストに `## Design note` セクションがない場合はブロッキングファインディングを報告します。ノートが差分と合わない場合もブロッキングファインディングを報告します。
2. 設計ファインディングは以下両方の条件を満たす場合のみブロッキングです:
   - このスキルのルール(決定ルール、Gate、不変条件テスト、読者コスト項目のいずれか)を名前で示している。
   - 読者または次の変更に具体的なコストを述べている。例:「呼び出し元はストレージ形状を知る必要がある」「一つの概念に二つの名前がある」「キャップ変更に三つのファイルの編集が必要」
3. その他の設計観察はすべて非ブロッキングとしてマークし、「Non-blocking design notes」という別リストに入れます。非ブロッキングノートは作成者に作業を戻しません。
4. 好みはファインディングとして報告しないでください。異なる名前、ファイルレイアウト、スタイルは好みです。名前付きルールを破り具体的なコストがある場合のみファインディングになります。
5. 同じ設計ファインディングが二回目のレビューサイクルで戻ってきた場合はエスカレーションします。三回目の同じ変更要求はしないでください。

## 関連スキル(インストール時)

- `find-shared-code`:共有に値するコードを最近の履歴から報告のみで検索します。このスキルの不変条件テストと深さテストを使います。
- `refactoring` と `working-effectively-with-legacy-code`:より深い設計に向けた安全なステップ。このスキルが新しい境界が残るかを決めます。

## ソースとライセンス

このスキルは、GitHubのciembor/agent-rules-booksリポジトリにある「A Philosophy of Software Design」の「ミニ」ルール(MITライセンス、コミット893a88a)を基にしています。ゲート、不変条件テスト、リーダーコストテスト、デザインノート、レビュー モードはこれらのルールへの追加です。このリポジトリには本の完全なルールも収録されています。

タグ

designarchitectureousterhoutreview

さらに詳しく

AgentsRoomをダウンロード

すべてのAIエージェントを、すべてのプロジェクトで、ひとつのウィンドウから実行。

無料AgentsRoomをダウンロード

コンパニオンアプリ:外出先でもエージェントを確認

Claude、Codex、Antigravity CLI、またはその他の AI プロバイダーを使用します。

拡張機能を入手
Chrome Web Store

バグや要望を公開バックログに直接送信できます。

マルチプロジェクト
マルチプロバイダー
マルチエージェント
ライブステータス
ファイル差分
モバイルアプリ
ライブプレビュー
エージェントチーム
ブラウザテスト
バックログ駆動開発
プロンプトライブラリ
スキルライブラリ
すべての機能を見る