codeprobe-architecture について
ソフトウェアのアーキテクチャと構造を分析する codeprobe スキルです。依存関係の循環、レイヤー境界、ドメイン分離、ディレクトリ規約、設定方法を確認します。
主な機能
- 01モジュール間の循環依存を検出
- 02レイヤー違反の確認
- 03大きなファイルやクラスの検出
- 04ドメインとモジュール境界の確認
- 05ディレクトリ規約と設定方法の確認
活用シーン
- 01既存コードベースのアーキテクチャレビュー
- 02モジュール間の循環インポートの特定
- 03成長中のプロジェクトにおけるドメイン分離の評価
- 04フレームワークの構成と環境設定の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ machineroom-dev/ codeprobe --skill codeprobe-architectureインストール後、Claude Code で/codeprobe-architectureを入力して読み込まれたか確認します。
詳細
スタンドアロンモード
オーケストレーター経由ではなく直接呼び出された場合は、最初に次の手順を実行する必要があります。
- 出力契約、実行モード、制約を確認するため、
../codeprobe/shared-preamble.mdを読み込みます(ユーザーのプロジェクトではなく、この SKILL.md の場所を基準に、兄弟ディレクトリにあるcodeprobeスキルディレクトリから解決します)。 - プロジェクトの技術スタックに基づいて、該当する参照ファイルを
../codeprobe/references/から読み込みます(同じ方法で解決します)。 - ユーザーから別の指定がない限り、
fullモードをデフォルトにします。
アーキテクチャと構造の分析
対象領域
このサブスキルでは、次のカテゴリにわたるアーキテクチャおよび構造上の問題を検出します。
- レイヤー違反 — コントローラー内のビジネスロジック、モデル内のプレゼンテーションロジック、ビュー内のデータベースアクセス
- 循環依存 — モジュール間の直接的または推移的な循環インポート
- ゴッドオブジェクト — 過大なファイルや、多くの役割を担いすぎているクラス
- 貧血ドメインモデル — 振る舞いを持たないエンティティクラスと、すべてのロジックをサービスクラスに集約する構造
- 境界の欠如 — 明確なモジュール/ドメインの分離がなく、機能間の結合が強い状態
- ディレクトリ構造 — フレームワークの規約違反、フラットなディレクトリ構造のアンチパターン
- 設定/環境 — 環境値のハードコード、設定の抽象化の欠如
検出対象外
- 5 ファイル未満の小規模なプロジェクト/スクリプト — 小規模なコードベースではフラットな構造が適切であり、レイヤーを追加すると過剰な設計になります。
- 意図的にレイヤーを薄くしているマイクロサービス — コントローラー、サービス、リポジトリがそれぞれ 1 つだけのマイクロサービスは、設計上問題ありません。
- フレームワーク標準の慣用的なモノリスパターン — 例:小規模から中規模のアプリにおける Laravel のデフォルト構造、Rails の設定より規約を優先するパターン、Next.js の app ディレクトリ規約。
- プロトタイプや概念実証コードであることが明確に示されているもの。
- 生成コードのディレクトリ(例:
dist/、build/、.next/、__pycache__/)。
検出手順
レイヤー違反
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ARCH | ビジネスロジックを含むコントローラー | コントローラーディレクトリ(controllers/、Controllers/、routes/、api/)内のファイルをスキャンします。次の内容を含むコントローラーを指摘します:データベースクエリ(単純な find()/findById() を超える SQL や ORM クエリビルダー)、ビジネスルールを含む複雑な条件分岐(3 つ以上の分岐)、計算、データ変換、または単純なフィールドの存在確認を超えるバリデーションロジック。コントローラーはサービス/アクションに処理を委譲する必要があります。 | Major |
ARCH | プレゼンテーションロジックを含むモデル/エンティティ | モデル/エンティティのファイルをスキャンします。次の内容を含むモデルを指摘します:HTML の生成、表示用の文字列整形(例:toHtml()、formatForDisplay())、ビュー固有の変換、CSS クラスの算出、またはレスポンスの整形。モデルにはプレゼンテーションロジックではなく、ドメインロジックを含める必要があります。 | Major |
ARCH | データベースを直接呼び出すビュー/コンポーネント | ビューファイル(.blade.php、.vue、.jsx/.tsx コンポーネント、.ejs、.pug、Jinja テンプレート)をスキャンします。次の内容を含むビューを指摘します:データベースへの直接クエリ、ORM 呼び出し、生の SQL、またはリポジトリメソッドの呼び出し。ビューにはコントローラー/props からデータを渡す必要があり、ビュー自体がデータを取得してはなりません。 | Major |
循環依存
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ARCH | モジュール A が B をインポートし、B が A をインポートしている(直接または推移的) | 事前ロードされた依存関係グラフを優先します(下記の「依存関係グラフ」サブセクションを参照)。グラフがある場合は、各循環の完全なファイルパスの連鎖を含む circular_dependencies 配列があるため、その連鎖を根拠として循環ごとに ARCH の指摘を 1 件報告します。グラフがない場合(縮退モード)は、ファイル間の import/require/use 文をたどり、直接的な循環(A→B→A)と推移的な循環(A→B→C→A)を探します。同じモジュール内のファイルレベルの循環よりも、アーキテクチャ上の重要性が高いモジュールレベル(ディレクトリレベル)の循環に注目します。 | Major |
依存関係グラフ(事前ロード済み)
/codeprobe audit または /codeprobe architecture 経由で呼び出されると、オーケストレーターは scripts/dependency_mapper.py を実行してインポートグラフを事前計算し、=== DEPENDENCY_GRAPH === と === END DEPENDENCY_GRAPH === マーカーの間に JSON をコンテキスト内で提供します。JSON のスキーマは次のとおりです。
graph:{file_path: [インポート先のファイル]}— 完全な依存関係グラフです。circular_dependencies:循環オブジェクトのリストです。各オブジェクトには完全なファイルパスの連鎖が含まれます(例:["a.py", "b.py", "c.py", "a.py"])。summary:{total_files, total_cycles, most_imported, most_dependencies}— 集計統計です。
グラフがある場合は、グラフを正解として扱います。circular_dependencies 内のすべての循環を ARCH の指摘とします。独自の循環検出を試みないでください。スクリプトは決定的な DFS を実行するため、LLM によるインポート追跡よりも信頼性が高くなります。
グラフがない場合(スクリプトの失敗、Python 3 の不在、または縮退モード)は、上記の「循環依存」の行に記載されているとおり、LLM ベースのインポート追跡に切り替えます。
ゴッドオブジェクト
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ARCH | ファイルが 500 LOC を超えている | 各ソースファイルの総行数を数えます(空行とコメントは除外)。500 LOC を超えるファイルを指摘します。指摘内容には超過の程度を記載します(2,000 LOC のファイルは 550 LOC のファイルよりも Major とする根拠が強くなります)。ただし、Major を超える重大度には決して引き上げません。ファイルの肥大化は保守性のリスクであり、本番環境の欠陥ではありません。 | Major |
ARCH | 20 個以上のメソッドを持つクラス | 各クラスの public、protected、private メソッドを数えます。20 個以上のメソッドを持つクラスを指摘します。クラスをどのように分割できるかを示すため、メソッドのグループを列挙します。 | Major |
ARCH | リクエストからレスポンスまでのライフサイクルを 1 つのファイルで処理している | リクエストの受信/解析、入力の検証、ビジネスロジックの実行、永続化、レスポンスの整形、ログ記録といった、リクエストのライフサイクル全体を 1 つのファイルまたはクラスで処理しているファイルを探します。これらの関心事のうち 4 つ以上が 1 つのファイルに含まれる場合に指摘します。 | Major |
貧血ドメインモデル
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ARCH | ゲッター/セッターのみで、振る舞いがまったくないエンティティ/モデルクラス | モデル/エンティティクラスをスキャンします。クラスがプロパティ宣言、ゲッター、セッター、コンストラクターでの代入のみで構成され、ビジネスロジックのメソッド(検証、計算、状態遷移、ドメインルールがない)を持たない場合、そのエンティティは貧血状態です。 | Minor |
ARCH | 単純なデータ入れ物を扱う「Service」クラスにすべてのロジックがある | エンティティクラスが単なるデータコンテナーで、振る舞い(検証、計算、状態遷移)のすべてが、エンティティを外部から操作する別個の *Service クラスに置かれているパターンがコードベースにあるか確認します。同じエンティティを操作するサービスが 3 つ以上あり、このパターンが広く見られる場合に指摘します。 | Minor |
境界の欠如
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ARCH | 中規模以上のプロジェクトで、明確なモジュール/ドメインの分離がない | ソースファイルが20個以上あるプロジェクトでは、コードがモジュール、ドメイン、または境界づけられたコンテキストに整理されているか確認します。すべてのソースファイルが単一のフラットなディレクトリに置かれている場合や、ドメイングループ分けがなく、技術レイヤー(controllers/、models/、services/)ごとにしか分けられていない場合は、指摘します。 | Major |
ARCH | 無関係な機能間で共有データベーステーブルに直接アクセスしている | 同じデータベーステーブル名、モデル、またはエンティティが、無関係な複数のモジュールや機能ディレクトリからインポートまたはクエリされていないか検索します。usersテーブルが、共有のuserモジュールを経由せずにbilling/、notifications/、reports/、admin/からアクセスされている場合は、指摘します。 | Major |
ARCH | イベント/インターフェースを介さず、機能間で直接インポートしている | 機能モジュールが、ほかの機能モジュールの内部ファイルを直接インポートしていないか確認します。たとえば、billing/InvoiceServiceが、インターフェースやイベントシステムを介さずにshipping/ShippingCalculatorを直接インポートしている場合です。機能間の密結合を指摘します。 | Minor |
ディレクトリ構造
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ARCH | フレームワークの規約に違反している | プロジェクトが、使用しているフレームワークで想定されているディレクトリ構造に従っているか確認します。例:ビジネスロジックのクラスがControllers/ディレクトリにある、ビューのテンプレートにSQLクエリがある、ルート定義がルート以外のファイルに散在している、命名規則がないままテストファイルとソースファイルが混在している。 | Minor |
ARCH | ファイルが20個以上あるのに、レイヤーが分離されていない | ソースファイルが20個以上あるプロジェクトでは、レイヤー(controllers、services、models、views)またはドメイン間に、ディレクトリによる分離があるか確認します。すべてが単一のフラットなディレクトリに置かれている場合は、指摘します。 | Major |
設定/環境
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ARCH | ソースコードに環境固有の値がハードコードされている | ソースコードファイル(設定ファイルを除く)に、ハードコードされたURL(http://localhost、https://api.example.com)、ポート番号(:3000、:8080、:5432)、ホスト名、IPアドレス、ファイルシステムのパスがないか検索します。これらの値は環境変数または設定から取得する必要があります。 | Major |
ARCH | 環境の抽象化が不足している | 環境の抽象化レイヤー(.envファイルと設定ローダー、環境変数、設定サービス)がプロジェクトにあるか確認します。ソースファイルが一元化された設定モジュールを介さずにprocess.env.Xまたはos.environ['X']を5か所以上で直接読み取っている場合、または.env/設定レイヤーがまったくない場合は、指摘します。 | Minor |
file_stats.py の使用方法
利用可能な場合は、Bash経由でfile_stats.pyスクリプトを実行し、ファイルごとのLOC、クラス数、メソッド数を取得します。スクリプトはcodeprobeスキルのscripts/ディレクトリにあります(ユーザーのプロジェクトではなく、スキルのインストール先を基準に解決してください)。
python3 scripts/file_stats.py <target_path>
注:通常、このスクリプトはオーケストレーターが実行し、結果を渡します。単独で呼び出す場合は、兄弟ディレクトリのcodeprobe/scripts/にあるスクリプトを探してください。
このデータを使用して、以下を行います。
- 巨大なオブジェクト(500 LOC超のファイル、メソッドが20個以上あるクラス)を特定する
- プロジェクト内で最も大きなファイルを見つける
- サマリー用に正確なLOC数を取得する
Python 3またはfile_stats.pyスクリプトを利用できない場合は、Readでファイルを直接読んで推定してください。分析を中断せず、手作業で数えて続行してください。
ID Prefixと修正プロンプトの例
すべての指摘にはARCH-プレフィックスを付け、ARCH-001、ARCH-002のように連番を振ります。
プロンプトの修正例
- 「
OrderController@store(40〜75 行目)から料金計算ロジックを新しいPricingServiceクラスに移し、app/Services/の下に配置してください。コントローラーではPricingServiceをインジェクションし、$this->pricingService->calculate($order)を呼び出してください。コントローラーの役割は、リクエストの解析、サービスへの委譲、レスポンスのフォーマットに限定してください。」 - 「
UserManager(850 LOC)を、役割に特化したサービスに分割してください。認証メソッド(50〜200 行目)をUserAuthServiceに、プロフィール管理(201〜450 行目)をUserProfileServiceに、通知メソッド(451〜700 行目)をUserNotificationServiceに抽出してください。UserManagerは、これら 3 つのサービスに処理を委譲する薄いファサードにしてください。」 - 「
billing/InvoiceServiceとshipping/ShippingCalculatorの循環依存を解消してください。共有インターフェースShippingCostProviderをshared/contracts/ディレクトリに抽出してください。ShippingCalculatorにShippingCostProviderを実装させ、InvoiceServiceは具象クラスではなくインターフェースに依存するようにしてください。」 - 「
src/services/ApiClient.tsの 23 行目にあるハードコードされた URLhttp://localhost:3000/apiを環境変数に置き換えてください。設定モジュールを通じて読み込むprocess.env.API_BASE_URLを使用してください。.env.exampleにAPI_BASE_URL=http://localhost:3000/apiを追加してください。」 - 「ドメインベースのディレクトリ構成を作成してください。
UserController、UserService、UserRepository、UserPolicyをapp/Domains/User/ディレクトリに移動してください。Order、Payment、Notificationの各ドメインでも同様にしてください。各ドメインディレクトリには、それぞれ独自のコントローラー、サービス、モデル、ポリシーを配置してください。」