sc-principles について
sc-principlesは、KISS、Functional Core/Imperative Shell、SOLID、Let It Crashの原則に照らしてPythonコードを検証するスキルです。閾値の設定、個別チェック、JSONレポートに対応し、開発ワークフローで利用できます。
主な機能
- 014つのエンジニアリング原則の検査
- 02複雑度とコード構造の測定
- 03I/Oとエラー処理パターンの検出
- 04チェック項目と閾値の設定
- 05JSONレポートとコミット前実行
活用シーン
- 01Pythonコードの原則違反の確認
- 02リファクタリング時の個別チェック
- 03検証に失敗したコミットの阻止
- 04機械可読な検証レポートの生成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tony363/ superclaude --skill sc-principlesインストール後、Claude Code で/sc-principlesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
scripts/__init__.pyshared.pyvalidate_crash.pyvalidate_kiss.pyvalidate_purity.pyvalidate_solid.pytests/__init__.pytest_shared.pytest_validate_crash.pytest_validate_kiss.pytest_validate_purity.pytest_validate_solid.py詳細
/sc:principles - コード原則バリデーター
4 つの基本的なソフトウェアエンジニアリング原則を強制する、必須の検証スキルです。
- KISS(シンプルにする) - コードは可能な限りシンプルにします
- 関数型コア、命令型シェル - ビジネスロジックは純粋に保ち、I/O は境界に配置します
- SOLID - 単一責任、オープン・クローズド、リスコフの置換、インターフェース分離、依存性逆転
- Let It Crash - バグは速やかに失敗させ、境界ではエラーを明示的に処理します
クイックスタート
# Full validation (all four principles)
/sc:principles src/
# KISS only validation
/sc:principles src/ --kiss-only
# Purity only validation
/sc:principles src/ --purity-only
# SOLID only validation
/sc:principles src/ --solid-only
# Let It Crash only validation
/sc:principles src/ --crash-only
# Strict mode (warnings become errors)
/sc:principles src/ --strict
# Generate detailed report
/sc:principles src/ --report
動作フロー
1. INITIALIZE
├── Detect scope root
├── Find changed Python files (git diff)
└── Determine file contexts (core vs shell)
2. ANALYZE
├── Parse AST for each file
├── Calculate complexity metrics (KISS)
├── Detect I/O patterns (Purity)
├── Check structural patterns (SOLID)
└── Analyze error handling (Let It Crash)
3. VALIDATE
├── Compare against thresholds
├── Classify violations (error vs warning)
└── Apply context rules (core stricter than shell)
4. REPORT/BLOCK
├── Output violations with locations
├── Generate actionable recommendations
└── Exit 0 (pass) or 2 (blocked)
検証ルール
KISS ゲート
| 指標 | しきい値 | 重大度 | 説明 |
|---|---|---|---|
| 循環的複雑度 | > 10 | error | コード内の独立した経路の数 |
| 循環的複雑度 | > 7 | warning | 複雑さの増大を早期に警告 |
| 認知的複雑度 | > 15 | error | 重み付けされた複雑さ(ネストした構造ほど高く評価) |
| 関数の長さ | > 50 行 | error | 関数あたりのコード行数(端数を含む) |
| ネストの深さ | > 4 レベル | error | if/for/while/with/try のネスト |
| パラメーター数 | > 5 | warning | 関数のパラメーター数 |
認知的複雑度と循環的複雑度の違い:
- 循環的複雑度は判断点(分岐)を数えます
- 認知的複雑度はネストした構造をより重く評価します。制御構造ごとに
1 + nesting_depthとなります - 例:
if (if (if ...))は循環的複雑度は低くても、認知的複雑度は高くなります(読みづらいため)
純粋性ゲート
「関数型コア、命令型シェル」パターン:
| レイヤー | パスパターン | I/O の許可 | 重大度 |
|---|---|---|---|
| コア | */domain/*, */logic/*, */services/*, */utils/*, */core/* | いいえ | error |
| シェル | */handlers/*, */adapters/*, */api/*, */cli/*, */scripts/*, */tests/* | はい | warning |
注: */archive/*、*/examples/*、*/benchmarks/*、conftest.py、setup.py、および *__main__.py 内のファイルはシェルとして扱われます(I/O が許可されます)。
検出される I/O パターン:
| カテゴリー | 例 |
|---|---|
| ファイル I/O | open()、read()、write()、Path.read_text() |
| ネットワーク | requests.get()、httpx、urllib、socket |
| データベース | execute()、query()、session.add()、cursor |
| サブプロセス | subprocess.run()、os.system()、Popen |
| グローバル状態 | global、nonlocal キーワード |
| 副作用 | print()、logging.*、logger.* |
| 非同期 I/O | async def、await、async for、async with |
SOLID ゲート
SOLID 設計原則に対する構造上の違反を検出します。
| 原則 | 検出条件 | 重大度 | 説明 |
|---|---|---|---|
| SRP | ファイルが 300 行を超える、またはクラスのパブリックメソッドが 5 個を超える | warning | 単一責任 - 変更理由は 1 つ |
| OCP | 型を判定する if/elif チェーン、isinstance の連鎖 | warning | オープン・クローズド - 拡張し、変更しない |
| LSP | NotImplementedError を送出するオーバーライド | error | リスコフの置換 - 契約を守る |
| ISP | メソッドが 7 個を超えるインターフェース/プロトコル | warning | インターフェース分離 - 小さなインターフェースにする |
| DIP | ビジネスロジック内での直接インスタンス化 | warning | 依存性逆転 - 抽象に依存する |
検出対象のコードスメル:
| スメル | 原則 | 推奨される修正 |
|---|---|---|
| 300 行を超えるファイル | SRP | 責務をモジュールに切り出す |
| 型による if/else の分岐チェーン | OCP | ストラテジーパターンまたはレジストリーを使用する |
| 例外を送出するオーバーライド | LSP | 基底クラスの契約を守るか、継承しない |
| メソッドが 10 個以上あるインターフェース | ISP | 目的を絞ったインターフェースに分割する |
ロジック内の new Service() | DIP | 依存性注入を使用する |
Let It Crash ゲート
「Let It Crash」の理念に基づいて、エラー処理におけるアンチパターンを検出します。
| パターン | 深刻度 | 説明 |
|---|---|---|
except: のみ | error | KeyboardInterrupt を含むすべての例外を捕捉します |
except Exception:(再送出なし) | warning | エラーを処理せずに握りつぶします |
except: pass | error | 無言の失敗で、デバッグを非常に困難にします |
| ネストされた try/except によるフォールバック | warning | エラーパスが複雑になり、デバッグが困難になります |
クラッシュさせるべき場合:
- 検証の失敗 → 明確なエラーを出してクラッシュさせます
- プログラミングエラー → 直ちに表面化させます
- 内部処理 → 失敗を許容します
エラーを処理する場合(ルールの例外):
- データの永続化 → データ損失を防ぎます
- 外部 API → 再試行、フォールバック、適切な縮退運転を行います
- リソースのクリーンアップ → RAII、finally ブロックを使用します
- ユーザー向けの操作 → 適切なエラーメッセージを表示します
フラグ対象外(適切な処理):
*/adapters/*、*/api/*、*/cli/*パス内でのエラー処理- 握りつぶす前に明示的にログを記録する
- ログ記録後に再送出する
フラグ
| フラグ | 型 | デフォルト | 説明 |
|---|---|---|---|
--kiss-only | bool | false | KISS 検証のみを実行します |
--purity-only | bool | false | 純粋性の検証のみを実行します |
--solid-only | bool | false | SOLID 検証のみを実行します |
--crash-only | bool | false | Let It Crash 検証のみを実行します |
--no-kiss | bool | false | KISS 検証をスキップします |
--no-purity | bool | false | 純粋性の検証をスキップします |
--no-solid | bool | false | SOLID 検証をスキップします |
--no-crash | bool | false | Let It Crash 検証をスキップします |
--threshold | int | 10 | 循環的複雑度の最大値 |
--max-cognitive | int | 15 | 認知的複雑度の最大値 |
--max-lines | int | 50 | 関数の最大行数 |
--max-depth | int | 4 | ネストの最大深度 |
--max-params | int | 5 | パラメーターの最大数 |
--max-file-lines | int | 300 | ファイルの最大行数(SRP) |
--max-interface-methods | int | 7 | インターフェースのメソッドの最大数(ISP) |
--strict | bool | false | すべての警告をエラーとして扱います |
--core-only | bool | false | コアレイヤーのファイルのみを検証します |
--all | bool | false | 変更されたファイルだけでなく、すべてのファイルを解析します |
--report | bool | false | 詳細な JSON レポートを生成します |
統合用フラグ
他のスキルや pre-commit フックで使用します。
| フラグ | 説明 |
|---|---|
--pre-commit | pre-commit フックとして実行します(失敗時はコミットをブロックします) |
--inline | 実装中にリアルタイムで検証します |
--json | プログラムからの利用向けに JSON 形式で出力します |
終了コード
| コード | 意味 | アクション |
|---|---|---|
| 0 | 検証に合格しました | 続行します |
| 2 | 違反が検出されました | ブロックされました — リファクタリングが必要です |
| 3 | 検証エラーです | 手動での対応が必要です |
有効化されるペルソナ
- code-warden - 原則の遵守を確認する主なレビュアー
- optimizer - 複雑なリファクタリングのガイダンス
- guardian - メトリクス統合
バリデータースクリプト
script/ ディレクトリにあります。
validate_kiss.py
python .claude/skills/sc-principles/scripts/validate_kiss.py \
--scope-root . \
--threshold 10 \
--max-lines 50 \
--json
validate_purity.py
python .claude/skills/sc-principles/scripts/validate_purity.py \
--scope-root . \
--core-only \
--json
Pre-commit との統合
.pre-commit-config.yaml に追加します。
repos:
- repo: local
hooks:
- id: kiss-check
name: KISS Validation
entry: python .claude/skills/sc-principles/scripts/validate_kiss.py --scope-root . --json
language: python
types: [python]
pass_filenames: false
- id: purity-check
name: Purity Validation
entry: python .claude/skills/sc-principles/scripts/validate_purity.py --scope-root . --json
language: python
types: [python]
pass_filenames: false
リファクタリングのガイダンス
違反が検出された場合は、次のパターンを適用します。
複雑度違反の場合
- メソッドの抽出 - 大きな関数を、名前を付けた小さな要素に分割します
- ガード節 - ネストされた if/else を早期リターンに置き換えます
- ストラテジーパターン - 複雑な switch/if-else をポリモーフィズムに置き換えます
- 条件式の分解 - 複雑な条件に、意味を説明する変数名を付けます
変更前:
def process(data, config, user):
if data:
if config.enabled:
if user.has_permission:
for item in data:
if item.valid:
# deep logic here
変更後:
def process(data, config, user):
if not can_process(data, config, user):
return None
return process_items(data)
def can_process(data, config, user):
return data and config.enabled and user.has_permission
def process_items(data):
return [process_item(item) for item in data if item.valid]
純粋性違反の場合
- 依存性注入 - 依存関係を引数として渡します
- リポジトリパターン - データベース操作を分離します
- アダプターパターン - 外部 API をラップします
- 出力ではなく値を返す - 値を返し、出力の処理は呼び出し元に任せます
変更前:
# In domain/calculator.py (CORE - should be pure)
def calculate_discount(user_id):
user = db.query(User).get(user_id) # I/O in core!
print(f"Calculating for {user.name}") # Side effect!
return 0.2 if user.is_premium else 0.1
変更後:
# In domain/calculator.py (CORE - now pure)
def calculate_discount(user: User) -> float:
"""Pure function - no I/O, just logic."""
return 0.2 if user.is_premium else 0.1
# In adapters/discount_service.py (SHELL - I/O allowed)
def get_user_discount(user_id: int) -> float:
user = user_repository.get(user_id)
discount = calculate_discount(user)
logger.info(f"Discount for {user.name}: {discount}")
return discount
SOLID 違反の場合
- SRP(単一責任の原則) - モジュールに切り分けます
- OCP(開放・閉鎖の原則) - ストラテジーパターンまたはレジストリを使用します
- LSP(リスコフの置換原則) - 基底クラスの契約を守ります
- ISP(インターフェース分離の原則) - 肥大化したインターフェースを分割します
- DIP(依存性逆転の原則) - 依存関係を注入します
修正前(OCP 違反):
def process_payment(payment_type, amount):
if payment_type == "credit":
return process_credit(amount)
elif payment_type == "debit":
return process_debit(amount)
elif payment_type == "crypto": # New type = code change!
return process_crypto(amount)
修正後(OCP 準拠):
PROCESSORS = {
"credit": process_credit,
"debit": process_debit,
"crypto": process_crypto, # Add here, no function change
}
def process_payment(payment_type, amount):
processor = PROCESSORS.get(payment_type)
if not processor:
raise ValueError(f"Unknown payment type: {payment_type}")
return processor(amount)
Let It Crash 違反の場合
- 包括的な catch ブロックを削除します - バグが表面化するようにします
- 防御的なガードを削除します - 代わりに境界で検証します
- try/except をフラット化します - あらゆる場所ではなく、境界で処理します
修正前(包括的な catch のアンチパターン):
def get_user(user_id):
try:
user = db.query(User).get(user_id)
return user
except: # BAD: catches everything, hides bugs
return None
修正後(クラッシュさせる):
def get_user(user_id):
# Let database errors surface - they indicate real problems
return db.query(User).get(user_id)
# Handle at the boundary (API layer)
@app.get("/users/{user_id}")
def api_get_user(user_id: int):
try:
return get_user(user_id)
except DBError as e:
logger.error("Database error", error=e, user_id=user_id)
raise HTTPException(500, "Database unavailable")
例
例 1:完全な検証
$ /sc:principles src/ --report
KISS Validation: BLOCKED
Files analyzed: 12
Errors: 3, Warnings: 5
Violations:
[ERROR] src/services/order.py:45 process_order: complexity = 15 (max: 10)
[ERROR] src/utils/parser.py:12 parse_data: length = 78 (max: 50)
[WARNING] src/domain/calc.py:8 calculate: parameters = 7 (max: 5)
Purity Validation: BLOCKED
Core violations: 2, Shell warnings: 1
Violations:
[ERROR] src/domain/user.py:23 get_status: database - db.query (context: core)
[ERROR] src/services/report.py:56 generate: file_io - open (context: core)
Recommendations:
- COMPLEXITY: Extract helper functions, use early returns
- DATABASE: Use repository pattern. Business logic receives data, not queries
- FILE I/O: Move file operations to adapter layer
例 2:KISS のみ
$ /sc:principles src/ --kiss-only --threshold 8
KISS Validation: PASSED
Files analyzed: 12
Errors: 0, Warnings: 2
例 3:厳格モード
$ /sc:principles src/ --strict
# All warnings become errors
# Any warning will block
品質統合
このスキルは SuperClaude の品質ゲートと統合されています。
simplicityディメンションに寄与します(重み:0.08)purityディメンションに寄与します(重み:0.02)- simplicity < 70 の場合に
simplification戦略をトリガーします - purity < 70 の場合に
purification戦略をトリガーします
関連スキル
/sc:improve --type principles- 原則への準拠を自動リファクタリングします/sc:implement- デフォルトで原則の検証が含まれます/sc:analyze- コード分析に原則のメトリクスが含まれます
テストカバレッジ
バリデーターには包括的なテストカバレッジがあります(4 つのスイートで 59 件のテスト)。
Purity バリデーターのテスト(16 件):
- 非同期関数の検出(
async def) - await 式の検出
- 非同期 for ループの検出
- 非同期 with コンテキストマネージャーの検出
- シェルとコアの重大度の区別
- 偽陽性の回帰テスト(set.add、parser.add_argument、asyncio.run、callback.call)
- エッジケース(構文エラー、Unicode、空のファイル)
KISS バリデーターのテスト(15 件):
- 関数の長さ(包括的なカウント)
- 循環的複雑度
- 認知的複雑度
- ネストの深さ
- パラメーター数
- エッジケース(構文エラー、Unicode、空のファイル)
SOLID バリデーターのテスト(15 件):
- SRP:ファイルの長さ、クラスのメソッド数、プライベートメソッドは除外
- OCP:isinstance の連鎖
- LSP:具象クラスのオーバーライドにおける NotImplementedError、ABC/Protocol は除外
- ISP:肥大化した Protocol および ABC インターフェース
- DIP:コアパスでのサービスの直接インスタンス化
- エッジケース(構文エラー、空のファイル)
Crash バリデーターのテスト(13 件):
- bare except の検出
- except: pass の検出
- コアパスでの例外の握りつぶし
- 再送出を伴う例外(OK)
- 特定の例外処理(OK)
- ネストした try/except の深さ
- シェルパスの緩和(adapters、api)
- エッジケース(構文エラー、空のファイル、try/finally)
テストの実行:
python -m pytest .claude/skills/sc-principles/tests/ -v
バージョン:2.1.0
バリデーター:validate_kiss.py、validate_purity.py、validate_solid.py、validate_crash.py
共有:shared.py(共通の find_python_files ユーティリティ)
エージェント:code-warden
特性:principles-enforced
テスト:59 件成功(4 つすべてのバリデーター)