mcpField
C
component-flattening-analysis

component-flattening-analysis

github.com/tech-leads-club開発7.1k214 回インストール3 日前に更新
リポジトリ

component-flattening-analysis について

component-flattening-analysisは、コードベースのコンポーネント階層を分析し、特にルート名前空間の孤立クラスを見つけるスキルです。名前空間を可視化し、フラット化のリファクタリングを提案・実行して、参照とテストを確認します。

主な機能

  1. 01名前空間とコンポーネント階層のマッピング
  2. 02ルート名前空間の孤立クラス検出
  3. 03統合・分割・共有コード戦略の比較
  4. 04リファクタリング手順と工数の見積もり
  5. 05参照の更新と変更の検証

活用シーン

  1. 01コードベースの階層違反の監査
  2. 02拡張されたルート名前空間内のソースファイル特定
  3. 03コンポーネントの統合または分割の計画
  4. 04名前空間のリファクタリングと依存参照の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/tech-leads-club/agent-skills --skill component-flattening-analysis

インストール後、Claude Code で/component-flattening-analysisを入力して読み込まれたか確認します。

同梱ファイルQUICK-REFERENCE.mdREADME.md

詳細

コンポーネントのフラット化分析

このスキルは、コンポーネント階層の問題を特定し、ディレクトリ/名前空間構造においてコンポーネントがリーフノードとしてのみ存在するようにするとともに、ルート名前空間から孤立したクラスを取り除きます。

使用方法

クイックスタート

コードベースの分析を依頼します。

  • 「ルート名前空間内の孤立したクラスを見つけて」
  • 「コンポーネント階層をフラット化して」
  • 「フラット化が必要なコンポーネントを特定して」
  • 「階層の問題がないかコンポーネント構造を分析して」
使用例

例 1:孤立したクラスを見つける

User: "Find orphaned classes in root namespaces"

The skill will:
1. Scan component namespaces for hierarchy issues
2. Identify orphaned classes in root namespaces
3. Detect components built on top of other components
4. Suggest flattening strategies
5. Create refactoring plan

例 2:コンポーネントをフラット化する

User: "Flatten component hierarchies in this codebase"

The skill will:
1. Identify components with hierarchy issues
2. Analyze orphaned classes
3. Suggest consolidation or splitting strategies
4. Create refactoring plan
5. Estimate effort

例 3:コンポーネント構造を分析する

User: "Analyze component structure for hierarchy issues"

The skill will:
1. Map component namespace structure
2. Identify root namespaces with code
3. Find components built on components
4. Flag hierarchy violations
5. Provide recommendations
手順
  1. 構造をスキャンする:コンポーネントの名前空間階層をマッピングします
  2. 問題を特定する:孤立したクラスとコンポーネントのネストを見つけます
  3. 選択肢を分析する:フラット化の方針(統合または分割)を決定します
  4. 計画を作成する:手順を含むリファクタリング計画を生成します
  5. 実行する:コンポーネントをリファクタリングして階層をなくします

使用する場面

次のような場合にこのスキルを適用します。

  • 共通のドメインコンポーネントを集約した後(パターン 2)
  • コンポーネントの依存関係を決定する前(パターン 4)
  • コンポーネントにネストされた構造がある場合
  • ルート名前空間内の孤立したクラスを探す場合
  • ドメインのグループ化に備える場合
  • コンポーネント構造を整理する場合
  • コンポーネントがリーフノードのみになるようにする場合

主な概念

コンポーネントの定義

コンポーネントは、ディレクトリ/名前空間構造のリーフノードによって識別されます。

  • リーフノード:ソースファイルを含む最も深いディレクトリ
  • コンポーネント:リーフノードの名前空間にあるソースコードファイル
  • サブドメイン:拡張された親名前空間

重要なルール:コンポーネントはリーフノードとしてのみ存在します。名前空間が拡張された場合、親はコンポーネントではなくサブドメインになります。

ルート名前空間

ルート名前空間とは、拡張された名前空間ノードです。

  • 拡張:その下に別の名前空間ノードが追加されている状態
  • 例:ss.survey が ss.survey.templates に拡張されている
  • 結果:ss.survey はルート名前空間(サブドメイン)になります
孤立したクラス

孤立したクラスとは、ルート名前空間内にあるソースファイルです。

  • 場所:ルート名前空間(リーフノードではないノード)
  • 問題:関連付け可能なコンポーネントがありません
  • 解決策:リーフノードの名前空間(コンポーネント)に移動します

例:

ss.survey/              ← Root namespace (extended by .templates)
├── Survey.js           ← Orphaned class (in root namespace)
└── templates/          ← Component (leaf node)
    └── Template.js
フラット化の方針

方針 1:下位を統合する

  • リーフノードからルート名前空間にコードを移動します
  • ルート名前空間がコンポーネントになります
  • 例:ss.survey.templates → ss.survey に移動します

方針 2:上位を分割する

  • ルート名前空間から新しいリーフノードにコードを移動します
  • ルート名前空間から新しいコンポーネントを作成します
  • 例:ss.survey を ss.survey.create + ss.survey.process に分割します

方針 3:共有コードを移動する

  • 共有コードを専用のコンポーネントに移動します
  • .shared コンポーネントを作成します
  • 例:ss.survey の共有コードを ss.survey.shared に移動します

分析プロセス

フェーズ 1:コンポーネント構造をマッピングする

ディレクトリ/名前空間構造をスキャンし、階層を特定します。

  1. 名前空間ツリーをマッピングする

    • すべての名前空間のツリーを構築します
    • 親子関係を特定します
    • リーフノード(コンポーネント)に印を付けます
  2. ルート名前空間を特定する

    • 拡張された名前空間を見つけます
    • ルート名前空間(サブドメイン)として印を付けます
    • それらを拡張している名前空間を記録します
  3. ソースファイルの場所を特定する

    • 各名前空間にあるすべてのソースファイルを見つけます
    • ファイルを名前空間の場所に対応付けます
    • ルート名前空間内のファイルを特定します

構造マッピングの例:

## Component Structure Map

ss.survey/ ← ルート名前空間(拡張済み) ├── Survey.js ← 孤立したクラス ├── SurveyProcessor.js ← 孤立したクラス └── templates/ ← コンポーネント(リーフノード) ├── EmailTemplate.js └── SMSTemplate.js

ss.ticket/ ← ルート名前空間(拡張済み) ├── Ticket.js ← 孤立したクラス ├── assign/ ← コンポーネント(リーフノード) │ └── TicketAssign.js └── route/ ← コンポーネント(リーフノード) └── TicketRoute.js

フェーズ 2:孤立したクラスを特定する

ルート名前空間にあるソースファイルを見つけます。

  1. ルート名前空間をスキャンする

    • 各ルート名前空間にソースファイルがあるか確認します
    • 孤立したファイルを特定します
    • ルート名前空間ごとに孤立したファイル数を数えます
  2. 孤立したクラスを分類する

    • 共有コード:共通ユーティリティ、インターフェース、抽象クラス
    • ドメインコード:コンポーネントに含めるべきビジネスロジック
    • 混在:共有コードとドメインコードの組み合わせ
  3. 影響を評価する

    • 孤立したファイルはいくつありますか?
    • どのような機能が含まれていますか?
    • どのコンポーネントがそれらに依存していますか?

孤立したクラスの検出例:

## Orphaned Classes Found

### Root Namespace: ss.survey

**Orphaned Files** (5 files):

- Survey.js (domain code - survey creation)
- SurveyProcessor.js (domain code - survey processing)
- SurveyValidator.js (shared code - validation)
- SurveyFormatter.js (shared code - formatting)
- SurveyConstants.js (shared code - constants)

**Classification**:

- Domain Code: 2 files (should be in components)
- Shared Code: 3 files (should be in .shared component)

**Dependencies**: Used by ss.survey.templates component
フェーズ 3:フラット化の選択肢を分析する

各ルート名前空間に最適なフラット化戦略を決定します。

  1. 選択肢 1:下位を統合する

    • リーフノードのコードをルート名前空間に移動します
    • ルート名前空間がコンポーネントになります
    • 使用する場合:リーフノードが小さく、関連する機能である場合
  2. 選択肢 2:分割する

    • ルート名前空間のコードを新しいリーフノードに移動します
    • ルートから複数のコンポーネントを作成します
    • 使用する場合:ルート名前空間に個別の機能領域がある場合
  3. 選択肢 3:共有コードを移動する

    • 共有コードを .shared コンポーネントに抽出します
    • ドメインコードはルートに残すか、分割します
    • 使用する場合:ルート名前空間に共有ユーティリティがある場合

フラット化分析の例:

## Flattening Options Analysis

### Root Namespace: ss.survey

**Current State**:

- Root namespace: 5 orphaned files
- Leaf component: ss.survey.templates (7 files)

**Option 1: Consolidate Down** ✅ Recommended

- Move templates code into ss.survey
- Result: Single component ss.survey
- Effort: Low (7 files to move)
- Rationale: Templates are small, related to survey functionality

**Option 2: Split Up**

- Create ss.survey.create (2 files)
- Create ss.survey.process (1 file)
- Create ss.survey.shared (3 files)
- Keep ss.survey.templates (7 files)
- Effort: High (multiple components to create)
- Rationale: More granular, but may be over-engineering

**Option 3: Move Shared Code**

- Create ss.survey.shared (3 shared files)
- Keep domain code in root (2 files)
- Keep ss.survey.templates (7 files)
- Effort: Medium
- Rationale: Separates shared from domain, but still has hierarchy
フェーズ 4:フラット化計画を作成する

各ルート名前空間のリファクタリング計画を作成します。

  1. 戦略を選択する

    • 最適なフラット化の選択肢を選びます
    • 作業量、複雑さ、保守性を考慮します
  2. リファクタリング手順を計画する

    • 移動するファイルを列挙します
    • 移動先の名前空間を特定します
    • 更新が必要な依存関係を記録します
  3. 作業量を見積もる

    • リファクタリングにかかる時間
    • リスク評価
    • テスト要件

フラット化計画の例:

## Flattening Plan

### Priority: High

**Root Namespace: ss.survey**

**Strategy**: Consolidate Down

**Steps**:

1. Move files from ss.survey.templates/ to ss.survey/
   - EmailTemplate.js
   - SMSTemplate.js
   - [5 more files]

2. Update imports in dependent components
   - Update references from ss.survey.templates._ to ss.survey._

3. Remove ss.survey.templates/ directory

4. Update namespace declarations
   - Change namespace from ss.survey.templates to ss.survey

5. Run tests to verify changes

**Effort**: 2-3 days
**Risk**: Low (templates are self-contained)
**Dependencies**: None
フェーズ 5:フラット化を実行する

リファクタリングを実施します。

  1. ファイルを移動する

    • ソースファイルを移動先の名前空間に移動します
    • ファイルパスとインポートを更新します
  2. 参照を更新する

    • 依存するコンポーネント内のインポートを更新します
    • 名前空間の宣言を更新します
    • ディレクトリー構造を更新します
  3. 変更を検証する

    • テストを実行します
    • 壊れた参照がないか確認します
    • コンポーネント構造を検証します

出力形式

孤立したクラスのレポート
## Orphaned Classes Analysis

### Root Namespace: ss.survey

**Status**: ⚠️ Has Orphaned Classes

**Orphaned Files** (5 files):

- Survey.js (domain code)
- SurveyProcessor.js (domain code)
- SurveyValidator.js (shared code)
- SurveyFormatter.js (shared code)
- SurveyConstants.js (shared code)

**Leaf Components**:

- ss.survey.templates (7 files)

**Issue**: Root namespace contains code but is extended by leaf component

**Recommendation**: Consolidate templates into root namespace
コンポーネント階層の問題
## Component Hierarchy Issues

| Root Namespace | Orphaned Files | Leaf Components                 | Issue                | Recommendation   |
| -------------- | -------------- | ------------------------------- | -------------------- | ---------------- |
| ss.survey      | 5              | 1 (templates)                   | Has orphaned classes | Consolidate down |
| ss.ticket      | 45             | 2 (assign, route)               | Large orphaned code  | Split up         |
| ss.reporting   | 0              | 3 (tickets, experts, financial) | No issue             | ✅ OK            |
フラット化計画
## Flattening Plan

### Priority: High

**ss.survey** → Consolidate Down

- Move 7 files from templates to root
- Effort: 2-3 days
- Risk: Low

### Priority: Medium

**ss.ticket** → Split Up

- Create ss.ticket.maintenance (30 files)
- Create ss.ticket.completion (10 files)
- Create ss.ticket.shared (5 files)
- Effort: 1 week
- Risk: Medium

分析チェックリスト

構造のマッピング:

  • すべての名前空間階層をマッピングしました
  • ルート名前空間を特定しました
  • すべてのソースファイルを見つけました
  • リーフノード(コンポーネント)に印を付けました

孤立したクラスの検出:

  • ルート名前空間をスキャンしてソースファイルを確認しました
  • 孤立したクラスを特定しました
  • 孤立したクラスを分類しました(共有/ドメイン/混在)
  • 影響と依存関係を評価しました

フラット化分析:

  • 統合の選択肢を分析しました
  • 分割の選択肢を分析しました
  • 共有コードの抽出の選択肢を分析しました
  • 各ルート名前空間に最適な戦略を選択しました

計画の作成:

  • フラット化戦略を選択しました
  • リファクタリング手順を作成しました
  • 作業量とリスクを見積もりました
  • 作業に優先順位を付けました

実行:

  • ファイルを移動先の名前空間に移動しました
  • インポートと参照を更新しました
  • 名前空間の宣言を更新しました
  • テストで変更を検証しました

実装に関する注意事項

Node.js/Express アプリケーションの場合

コンポーネントは通常 services/ ディレクトリーにあります。

services/
├── survey/              ← Root namespace (extended)
│   ├── Survey.js       ← Orphaned class
│   └── templates/      ← Component (leaf node)
│       └── Template.js

フラット化:

  • 統合:templates/ のファイルを survey/ に移動します
  • 分割:survey/create/ と survey/process/ を作成します
  • 共有:ユーティリティ用に survey/shared/ を作成します
Java アプリケーションの場合

コンポーネントはパッケージ構造で特定します。

com.company.survey       ← Root package (extended)
├── Survey.java         ← Orphaned class
└── templates/          ← Component (leaf package)
    └── Template.java

フラット化:

  • 統合:templates クラスを survey パッケージに移動します
  • 分割:survey.create と survey.process パッケージを作成します
  • 共有:survey.shared パッケージを作成します
検出戦略

コードを含むルート名前空間を見つける:

// Find root namespaces containing source files
function findRootNamespacesWithCode(namespaces, sourceFiles) {
  const rootNamespaces = namespaces.filter((ns) => {
    // Check if namespace has been extended
    const hasChildren = namespaces.some((n) => n.startsWith(ns + '.') || n.startsWith(ns + '/'))

    // Check if namespace contains source files
    const hasFiles = sourceFiles.some((f) => f.namespace === ns)

    return hasChildren && hasFiles
  })

  return rootNamespaces
}

孤立したクラスを見つける:

// Find orphaned classes in root namespaces
function findOrphanedClasses(rootNamespaces, sourceFiles) {
  const orphaned = []

  rootNamespaces.forEach((rootNs) => {
    const files = sourceFiles.filter((f) => f.namespace === rootNs)
    orphaned.push({
      rootNamespace: rootNs,
      files: files,
      count: files.length,
    })
  })

  return orphaned
}

フィットネス関数

コンポーネントをフラット化した後、自動チェックを作成します。

ルート名前空間にソースコードを置かない
// Alert if source code exists in root namespace
function checkRootNamespaceCode(namespaces, sourceFiles) {
  const violations = []

  namespaces.forEach((ns) => {
    // Check if namespace has been extended
    const hasChildren = namespaces.some((n) => n.startsWith(ns + '.') || n.startsWith(ns + '/'))

    if (hasChildren) {
      // Check if namespace contains source files
      const files = sourceFiles.filter((f) => f.namespace === ns)

      if (files.length > 0) {
        violations.push({
          namespace: ns,
          files: files.map((f) => f.name),
          issue: 'Root namespace contains source files (orphaned classes)',
        })
      }
    }
  })

  return violations
}
コンポーネントは末端ノードにのみ配置する
// Ensure components exist only as leaf nodes
function validateComponentStructure(namespaces, sourceFiles) {
  const violations = []

  // Find all leaf nodes (components)
  const leafNodes = namespaces.filter((ns) => {
    return !namespaces.some((n) => n.startsWith(ns + '.') || n.startsWith(ns + '/'))
  })

  // Check that all source files are in leaf nodes
  sourceFiles.forEach((file) => {
    if (!leafNodes.includes(file.namespace)) {
      violations.push({
        file: file.name,
        namespace: file.namespace,
        issue: 'Source file not in leaf node (component)',
      })
    }
  })

  return violations
}

ベストプラクティス

推奨事項 ✅
  • コンポーネントが末端ノードにのみ存在するようにします
  • ルート名前空間から孤立したクラスを削除します
  • 機能に基づいてフラット化の方法を選択します
  • 機能に関連性がある場合は統合します
  • 機能が異なる場合は分割します
  • 共通コードを.sharedコンポーネントに抽出します
  • フラット化後、すべての参照を更新します
  • テストで変更を検証します
禁止事項 ❌
  • ルート名前空間に孤立したクラスを残さないでください
  • ほかのコンポーネントの上にコンポーネントを作成しないでください
  • ファイルの移動後にインポートの更新を省略しないでください
  • 影響を分析せずにフラット化しないでください
  • フラット化の方法に一貫性を欠かせないでください
  • フラット化の際に共通コードを無視しないでください
  • リファクタリング後のテストを省略しないでください

よくあるパターン

パターン 1:単純な統合

変更前:

ss.survey/
├── Survey.js           ← Orphaned
└── templates/          ← Component
    └── Template.js

変更後:

ss.survey/              ← Component (leaf node)
├── Survey.js
└── Template.js
パターン 2:機能別の分割

変更前:

ss.ticket/              ← Root namespace
├── Ticket.js           ← Orphaned (45 files)
├── assign/             ← Component
└── route/              ← Component

変更後:

ss.ticket/              ← Subdomain
├── maintenance/        ← Component
│   └── Ticket.js
├── completion/        ← Component
│   └── TicketCompletion.js
├── assign/             ← Component
└── route/              ← Component
パターン 3:共通コードの抽出

変更前:

ss.survey/              ← Root namespace
├── Survey.js           ← Domain code
├── SurveyValidator.js  ← Shared code
└── templates/          ← Component

変更後:

ss.survey/              ← Component
├── Survey.js
└── shared/             ← Component
    └── SurveyValidator.js

次のステップ

コンポーネントをフラット化した後:

  1. コンポーネントの依存関係を特定するパターンを適用する - 結合度を分析します
  2. コンポーネントドメインを作成する - コンポーネントをドメインにグループ化します
  3. ドメインサービスを作成する - ドメインをサービスとして抽出します

注記

  • コンポーネントは末端ノードにのみ存在する必要があります
  • コードを含むルート名前空間は問題の原因になります
  • フラット化によりコンポーネントが明確になります
  • 機能に基づいてフラット化の方法を選択します
  • 共通コードは専用のコンポーネントに配置します
  • ファイルの移動後は必ず参照を更新します
  • フラット化後は十分にテストします

コメント