solid について
solid は、SOLID 原則をモジュール境界や依存方向の設計に適用する開発スキルです。テスト容易性を考慮した設計やレビューを導き、テストだけを目的とする抽象化を避けます。
主な機能
- 01モジュールの責務と境界の定義
- 02依存方向の確認
- 03呼び出し側に合わせた小さなインターフェース
- 04IO を境界のアダプターに配置
- 05テスト専用の抽象化を回避
活用シーン
- 01新しいモジュールと依存関係の設計
- 02クラスや API の境界設計のレビュー
- 03モックが多いテストのためのリファクタリング
- 04結合によるテストの難しさへの対処
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ gusen1453/ creed --skill solidインストール後、Claude Code で/solidを入力して読み込まれたか確認します。
詳細
SOLID
**出力言語:**回答と成果物は、ユーザーが使用している言語で書いてください(リポジトリの履歴ではなく、ユーザーのメッセージに合わせてください)。
概要
SOLIDを適用し、大量のモックを用意しなくても、動作を簡単に変更・テストできるようにします。
関連するスキル: grill → write-specでプロダクトの形を整えます。tdd + test-designで動作を検証します。このスキルが扱うのは、構造と依存関係の方向のみです。
基本原則:テストしにくいものは、たいてい使いにくいものです。モックでごまかさず、境界を修正してください。
起動モード(重要)
| モード | タイミング | 対応 |
|---|---|---|
| ゲート(主) | write-specの後(または設計を省略した場合)、write-planの前で、スライスにモジュール/ポート/IOの境界が追加される場合 | 以下のワークフロー全体を実行します — Using solid to …と宣言します |
| レスキュー | テストで3個以上のモックが必要な場合、レビュー/PRで結合が問題になっている場合、tddの途中で構造に行き詰まった場合 | ワークフロー全体を実行してから、呼び出し元に戻ります |
| 匂いの指摘のみ(grill内) | 異なる境界を示唆するアプローチを比較する場合 | このスキルをメインスキルとして読み込まないでください。セッションの主導権はGrillが保持します。選択肢のラベルでは、境界の匂いを1つ指摘してもかまいません(「これはドメインをSQLに結び付けるため、後でモックだらけになります」)。正式なSOLIDの適用はゲートまで待ちます |
既定:プロダクトの「何を/なぜ」がまだ決まっていない場合は、solidではなくgrillを使います。
使用するタイミング
- 仕様が承認され、次のステップでパッケージ、ポート、依存関係の矢印を決める必要がある場合
- モジュール境界、クラス/APIの形、依存関係の方向を設計またはレビューする場合
- 「分離」のために単体テストで多数のモックが必要な場合
- テスト容易性を目的としたリファクタリング、またはPRで結合やGodクラスが追加される場合
使用しない場合:
- プロダクトの決定事項がまだ残っている場合(grillを使います)
- 単純な接着コード、ついでの名前変更、使い捨ての試作
- 新しい境界を追加しない小さな変更(既存の型で単一の動作を追加する場合)— ゲートを省略し、write-planまたはtddに進みます
- プロダクト上のトレードオフを検討する代わりに使う場合
鉄則(譲れない原則)
1. New non-trivial behavior lives behind a boundary you can name (SRP).
2. Domain/policy does not depend on IO/framework details (DIP).
3. Fake abstractions invented only to satisfy a test are forbidden (no theater).
文言に反することは、精神にも反することです。「とにかく何でもモックする」も「今はGodクラスでも問題ない」も、許容されません。
5つの原則をエンジニアリング上のチェック項目として捉える
S — 単一責任
- 1つの単位 → 変更理由は1つ
- 名前に「そして」や「すべてを管理する」が必要なら、分割します
- オーケストレーション、ポリシー、IO、フォーマット処理を分離します
O — オープン/クローズド
- 中核のswitchを延々と編集するのではなく、新しい型/戦略/合成による拡張を優先します
- YAGNI:プラグインシステムを先回りして作らないでください。ただし、新しいケースを巨大な塊に次々と詰め込むのはやめましょう
L — リスコフの置換
- サブタイプは呼び出し元との契約(事前条件/事後条件、エラー)を守る必要があります
- 呼び出し元を困惑させる「再利用のための継承」は避け、合成を優先します
I — インターフェース分離
- 巨大な単一インターフェースではなく、呼び出し元に合わせた小さなポートにします
- 呼び出し元が使わないメソッドへの依存を強制してはいけません
D — 依存関係逆転
- 高水準のポリシーは、DB/HTTP/FS/SDKの具象実装ではなく、抽象(ポート)に依存します
- アダプターは境界に置き、コアは純粋でフェイク可能な状態に保ちます
- **兆候:**単体テストに3個以上のモックが必要なら、DIP/SRPに問題がある可能性があります(test-designを参照)
ワークフロー(ゲートまたはレスキューで起動した場合)
「Using solid to …」と宣言してから、次の手順を実行します。
- 単位を特定する — それぞれの役割、使い方、依存先を確認します
- 依存関係の矢印を描く — domain → ports ← adapters(domain → SQL/HTTPクライアントへの直接依存は禁止)
- SRPを確認する — 「そして」で結ばれる責務を分割します
- ISPを確認する — 肥大化したインターフェースを整理します
- DIPを確認する — IOを外側に移し、ポートを注入します
- 見せかけでないか確認する — 新しいインターフェースはすべて、テスト上の理由だけでなく、プロダクト上の理由が必要です
- 引き継ぐ — write-plan(ゲート)に進むか、tdd(レスキュー)を再開します。プロダクトに関する疑問が再び出てきた場合は、grillに進みます
危険信号
- 機能全体を「把握する」Godクラス/パッケージ
- ドメインがORM、HTTPクライアント、UIキットをインポートしている
- 不変条件を弱めるサブクラスのオーバーライド
- 1つの呼び出し元が2つしか使わないのに、15個のメソッドがあるインターフェース
- テストでしか使われず、プロダクション用アダプターがない新しいインターフェース
- 「分離」のために、システムの半分をモックする単体テスト
合理化表
| 言い訳 | 実態 |
|---|---|
| 「つらくなってから分割すればいい」 | モックが4つ必要になった時点で、すでにつらい状態です。 |
| 「ポートより具象のほうがシンプル」 | 2つ目のI/O経路ができるまではそうです。ポートとアダプター1つのほうが、書き直すより低コストです。 |
| 「継承すればコードを再利用できる」 | 継承は階層同士を密結合にします。代わりにコンポジションを使いましょう。 |
| 「サービスインターフェースを1つにすれば整理できる」 | 肥大化したインターフェースは、偽のメソッドとISPの負債を生みます。 |
| 「モックがDIPの証明になる」 | モックはDIPの失敗を覆い隠します。実際のポートを導入した後にモックが減ることが、その証明です。 |
| 「まだ要件を詰めている段階だけど、今すぐ全体をソリッドにしよう」 | オプションのラベルにだけ臭いがある状態です。何をなぜ作るかが確定してから、全体をソリッドにします。 |
チェックリスト
- プロダクトの「何を」「なぜ」がすでに確定している(または実装途中のRescueである)
- 各ユニットの目的が1つだけで、「and」を含まない名前になっている
- 依存関係の矢印がI/Oではなく、ポリシーに向かっている
- ポートは小さく、アダプターがフレームワークを担っている
- テスト専用の抽象化がない
- モックの山を作らずに、write-planまたはtdd/test-designへ進める
引き継ぎ
移行ゲート — 境界をwrite-plan(Gate)に進める前、またはコードに戻す(Rescue)前に、ユーザーに確認します(AskUserQuestionを1回。自動で次へ進めないでください)。
A) Recommended: Proceed → write-plan (Gate) / resume tdd (Rescue)
B) Review first — run **review** on these boundaries (`references/solid.md`; upstream = spec's promised boundaries), then return to this gate
C) Adjust — rework the structure, then return to this gate
D) Something else (I will type it)
- プロダクトの決定事項が未確定 → grill → write-spec
- 境界が確定済み → write-plan
- 実装中 → tdd + test-design
- リリース中 → review / commit-and-push
コメント
Markdown 対応