solid
SOLIDの原則を適用して、柔軟で保守性が高く、テスト可能なコードを書くことができます。クラス、インターフェース、モジュール境界の設計時に活用できます。単一責任の原則、開放閉鎖の原則、リスコフの置換原則、インターフェース分離の原則、依存性逆転の原則の5つを、実践的なTypeScriptの例と検出ヒューリスティックを通じてカバーしています。
description の原文を見る
Apply SOLID principles to write flexible, maintainable, and testable code. Use when designing classes, interfaces, and module boundaries. Covers Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion with practical TypeScript examples and detection heuristics.
SKILL.md 本文
SOLID 原則
ソフトウェアを理解しやすく、拡張しやすく、保守しやすくするための 5 つの原則です。結合度を低減し、凝集度を向上させ、コードをテスト可能にします。
適用するタイミング
以下の場合に参照してください:
- 新しいクラス、モジュール、またはインターフェースを設計するとき
- 責務が多すぎるコードをリファクタリングするとき
- PR をアーキテクチャの観点から レビューするとき
- ゴッドオブジェクトや肥大なインターフェースを分割するとき
- モジュール境界をどこに引くかを決めるとき
- コードをより テスト可能にするとき
クイックリファレンス
| 原則 | 一行説明 | 危険信号 |
|---|---|---|
| SRP (単一責任) | 変更する理由が 1 つ | 「このクラスは X と Y と Z を処理する」 |
| OCP (オープン・クローズド) | 修正ではなく追加 | if/else や switch の連鎖が増えている |
| LSP (リスコフ置換) | サブタイプは置換可能 | 呼び出し側でのタイプチェックや特別扱い |
| ISP (インターフェース分離) | 小さく焦点を絞ったインターフェース | 空のメソッド実装または throw new Error("Not implemented") |
| DIP (依存性逆転) | 具象ではなく抽象に依存 | ビジネスロジック内の new ConcreteClass() |
詳細な説明と TypeScript の例については references/PRINCIPLES.md を参照してください。
検出チェックリスト
すべてのクラスとモジュールに対してこれらの質問を問いかけてください:
| 質問 | 違反している原則 |
|---|---|
| このクラスに複数の変更理由がありますか? | SRP |
| 新しいバリアントを追加するために既存コードを修正する必要がありますか? | OCP |
| 呼び出し側がサブタイプのタイプチェックや特別な処理を必要としていますか? | LSP |
| 実装側が未使用のメソッドをスタブ化する必要がありますか? | ISP |
| 高レベルのロジックがインフラストラクチャを直接インスタンス化していますか? | DIP |
さまざまなスケールでの SOLID 適用
| スケール | SRP | OCP | LSP | ISP | DIP |
|---|---|---|---|---|---|
| 関数 | 1 つのことをする | — | — | — | 抽象をパラメータとして受け取る |
| クラス | 変更理由が 1 つ | 合成で拡張 | サブタイプが契約を遵守 | 使用するものだけを実装 | コンストラクタインジェクション |
| モジュール | 1 つのバウンデッドコンテキスト | プラグインアーキテクチャ | 交換可能な実装 | 細いパブリック API | 内向きの依存 |
| サービス | 単一のドメイン | 新機能 = 新サービス | API コントラクトの安定性 | 最小限の API サーフェス | 境界での抽象化 |
原則間の関係
- SRP + ISP: 責務を分割することは、多くの場合インターフェースも分割することを意味します
- OCP + DIP: 抽象に依存することで、修正なしに拡張することが可能になります
- LSP + OCP: サブタイプが置換可能であれば、新しいサブタイプを追加することで動作を拡張できます
- DIP + ISP: 小さく焦点を絞ったインターフェースにより、依存性逆転が実用的になります
一般的なアンチパターン
| アンチパターン | 違反している原則 | 修正方法 |
|---|---|---|
| すべてを行うゴッドクラス | SRP | 焦点を絞ったクラスを抽出 |
コードベース全体でのタイプに対する switch | OCP、LSP | ポリモーフィズムで置き換え |
| 「サポートされていない」をスロー するサブクラス | LSP、ISP | 階層の再設計、インターフェースの分割 |
| 20 個のメソッドを持つ肥大なインターフェース | ISP | ロールベースのインターフェースに分割 |
| DB ドライバをインポートするビジネスロジック | DIP | リポジトリインターフェースを注入 |
| 独自の依存性を作成するサービス | DIP | コンストラクタインジェクション |
ベストプラクティス
すべきこと
- SRP から始める — これが他のすべての基礎です
- インターフェースを使用して コンポーネント間の境界を定義する
- 実際の問題から違反が現れたら、それを修正する
- 動作を拡張するには継承よりも合成を優先する
- インターフェースは小さくロール固有に保つ
- コンストラクタを通じて依存性を注入する
してはいけないこと
- 些細なコードに SOLID を教条的に適用する(5 行のユーティリティにはインターフェースは不要)
- 少なくとも 2 つの実装がない段階で抽象化を作成する
- SRP を「単一メソッド」と混同する — これはサイズではなく変更理由についてです
- 同じ階層に属すべきではないクラスに Liskov 準拠を強制する
- 凝集力のあるグループが適切な場合に、インターフェースを単一メソッドのフラグメントに過度に分割する
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- fellipeutaka
- リポジトリ
- fellipeutaka/denji
- ライセンス
- MIT
- 最終更新
- 2026/3/28
Source: https://github.com/fellipeutaka/denji / ライセンス: MIT