mcpField
R
refactor-module

refactor-module

github.com/plainlang開発8042 回インストール2 日前に更新
リポジトリ

refactor-module について

refactor-moduleは、広範な .plain モジュールを requires チェーンに再編し、各仕様の動作と順序を保つスキルです。分割計画、承認、移行、検証を案内します。

主な機能

  1. 01仕様と依存関係の分析
  2. 02意味に沿ったモジュール分割
  3. 03時系列順序の維持
  4. 04概念の配置とエクスポート
  5. 05テスト移行と検証

活用シーン

  1. 01無関係な機能を含むモジュールの分割
  2. 02安全なモジュール依存チェーンの計画
  3. 03動作を保った仕様の移行

インストール

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

$npx skills add https://github.com/plainlang/plain-forge --skill refactor-module

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

詳細

モジュールのリファクタリング

まずルールを読み込んでください。 .plain ファイルの読み取り、編集、書き込みを行う前に、load-plain-reference スキルを呼び出し、案内されたルールファイルを読んでください。この会話ですでに load-plain-reference が実行されている場合に限り、これを省略できます。

使用するタイミング

  • モジュールに、複数の異なるドメインや機能領域にまたがる機能仕様が多数ある。
  • 関連のない関心事が混在しているため、モジュールの把握が難しい。
  • モジュールの範囲が広すぎて、新機能を追加しにくい。
  • ユーザーが明示的にモジュールの分割や再編成を求めている。

基本原則

リファクタリングは構造の変更のみです。リファクタリング後のモジュールの結合された動作は、元のモジュールと同一でなければなりません。機能仕様を追加、削除、または弱めてはいけません。分割は、関連する仕様をまとめる意味的なものであり、動作を変えるものではありません。

入力

リファクタリング対象の .plain ファイルと、希望するグループ分けについてのユーザーの指示(または、こちらが提案したグループ分けをユーザーに確認します)。

フェーズ 1 — 現在のモジュールを分析する

  1. .plain ファイル全体を読む — フロントマター、定義、実装要件、テスト要件、すべての機能仕様を読みます。また、コンテキスト全体を把握するために、import と requires の依存関係もすべて読みます。
  2. 機能仕様を一覧にする。 各機能の func-id を列挙し、参照している :Concepts: を記録します。依存関係マップを作成し、どの仕様が先行する仕様(そこで導入された動作や状態)に依存しているかを確認します。
  3. 定義を一覧にする。 各コンセプトについて、どの機能仕様が参照しているかを記録します。複数の論理グループで使われるコンセプトと、特定のグループ内でのみ使われるコンセプトを特定します。
  4. 論理グループを特定する。 機能仕様のまとまり、共有するコンセプト、一貫したドメイン、または単一の機能領域を説明する仕様群など、自然な分割点を探します。一般的なグループ分けの例:
    • データモデルのセットアップと CRUD 操作
    • ビジネスロジックと処理ルール
    • UI 画面とナビゲーション
    • 外部サービスとの連携とインターフェース
    • 統計、レポート、分析
  5. グループの独立性を検証する。 各グループの仕様は、時系列順で連続した、またはほぼ連続したブロックを形成する必要があります。あるグループの仕様が散在し、他のグループの仕様と入り交じっている場合は、分割位置の調整が必要なことがあります。

フェーズ 2 — 分割を計画する

変更を行う前に、分割案をユーザーに提示し、明示的な確認を得てください。

2a. モジュールチェーンを定義する

モジュールは、機能仕様の元の時系列順を維持する requires チェーンを形成します。チェーンの最初のモジュールには最も早い仕様を含め、後続の各モジュールは直前のモジュールを requires し、次の論理グループを追加します。

original-module
  ↓ splits into
module-group-a  (no requires — this is the chain root)
module-group-b  (requires: module-group-a)
module-group-c  (requires: module-group-b)

元のモジュールにすでに requires または import の依存関係がある場合は、最初の新しいモジュールがそれを引き継ぎます。

2b. 機能仕様を各モジュールに割り当てる

各機能仕様は、必ずいずれか 1 つのモジュールに配置してください。配置は時系列順を守る必要があります。

  • 各モジュール内では、仕様の相対的な順序を元のモジュールと同じにします。
  • チェーン全体でも順序を維持します。モジュール A のすべての仕様は、モジュール B のすべての仕様より前に置き、モジュール B のすべての仕様は、モジュール C のすべての仕様より前に置きます。
  • ある仕様が依存する仕様より前のモジュールに移動することはできません。
2c. 定義を各モジュールに割り当てる

各コンセプトについて、配置先を決定します。

コンセプトの使用範囲配置先
1 つのモジュールの仕様内でのみ使用そのモジュールで定義する
チェーン内の複数のモジュールで使用最初に使用するモジュールで定義し、そのモジュールの exported_concepts に追加する
すでに import テンプレートで定義済みimport に残す — 変更不要

多くのコンセプトをすべてのモジュールで共有する場合は、それらを格納する新しい import モジュール(テンプレート)の作成を検討してください。これにより、exported_concepts の一覧が長くなるのを避け、定義を一元管理できます。その場合は create-import-module スキルを使用してください。

2d. 実装要件とテスト要件を割り当てる
  • すべてのモジュールに適用される要件は、共有インポートテンプレートに配置します。すでに存在する場合は、そのまま残します。
  • 単一モジュールのドメインに固有の要件は、そのモジュールに移動します。
  • 判断に迷う場合は、要件を共有テンプレートに残します。モジュール間で重複させるより、テンプレートが少し広範になるほうが望ましいです。
2e. 計画を提示する

ユーザーに以下を要約します。

  • 分割後のモジュール数とその名前
  • 各モジュールに含める機能仕様(func-id を列挙)
  • requires チェーンの順序
  • 新たに作成するインポートモジュール
  • 各モジュールからエクスポートされる概念
  • 元の仕様がすべて反映されており、抜けがないことの確認

作業を進める前に、ユーザーから明示的な確認を得ます。

フェーズ 3 — 分割を実行する

チェーンのルートから順に、新しいモジュールを作成します。

3a. インポートテンプレートを作成または更新する(必要な場合)

共有の定義または要件を新しいインポートテンプレートに移動する場合は、create-import-module スキルを使って最初に作成します。

3b. チェーンのルートを作成する

チェーンの最初のモジュールを作成します。

  1. YAML フロントマターを設定します — 元のモジュールの import 参照を引き継ぎます。下流のモジュールで必要となる概念があれば、exported_concepts を追加します。
  2. このモジュールの仕様で使用する概念と、エクスポートが必要な概念を含む ***definitions*** セクションを追加します。
  3. このモジュール固有の ***implementation reqs*** と ***test reqs*** を追加します(インポートテンプレートで完全にカバーされていない場合)。
  4. このモジュールに割り当てられた ***functional specs*** を、元の順序と正確な文言を保ったまま追加します。
  5. 移動した機能のテスト用プレーンファイルの module: キーを新しいモジュール名に設定し、ファイルをそのモジュールの標準的な場所に移動します。func-id とシナリオのテキストは変更しません。
3c. 後続のモジュールを作成する

チェーン内の後続モジュールごとに、以下を行います。

  1. requires をチェーン内の直前のモジュールに設定します。共有テンプレートを使用する場合は import も設定します。
  2. チェーン内の後続モジュールで必要となる概念があれば、exported_concepts を追加します。
  3. このモジュール内で定義する概念の ***definitions*** を追加します。requires(エクスポート済み)または import によってすでに利用可能な概念を再定義しないでください。
  4. このモジュール固有の ***implementation reqs*** と ***test reqs*** を追加します。
  5. このモジュールに割り当てられた ***functional specs*** を、元の順序と正確な文言を保ったまま追加します。
  6. 移動した機能のテスト用プレーンファイルを、同じ方法で移動します。
3d. 元のモジュールファイルを処理する

新しいモジュールをすべて作成した後、以下を行います。

  • 元のモジュールが完全に置き換えられる場合(すべての仕様が移動した場合)、混乱を避けるために削除するか、名前を変更します。
  • 元のモジュールが他のモジュールから必要とされていた場合は、それらのモジュールを更新し、新しいチェーンの最後のモジュールを require するようにします。そこに蓄積されたコードと以前の機能仕様が、チェーン全体をカバーします。ただし、エクスポートされた概念は推移的ではありません。下流のモジュールが新しいチェーン内の前のモジュールからエクスポートされた概念を参照する場合は、その前のモジュールも requires に列挙する必要があります。

フェーズ 4 — 検証する

4a. 完全性チェック

これは最も重要な検証です。元のモジュールの機能仕様をすべて確認し、それぞれが新しいモジュールのちょうど1つに含まれていることを確かめます。何も失われたり、弱められたり、変更されたり、暗黙のまま残されたりしてはなりません。

チェックリスト:

  • 新しいすべてのモジュールに含まれる仕様の合計数が、元の仕様数と一致する
  • 各仕様のテキストが元の内容と完全に一致し(言い換えなし)、func-id も保持されている
  • 各機能のテスト用プレーンファイルが機能とともに移動され、module: が更新され、シナリオもそのまま保たれている
4b. 時系列順序のチェック

requires チェーンをルートから末端までたどってすべての機能仕様を読んだとき、時系列順序が元の順序と一致することを確認します。ある仕様が、それに依存する仕様より先に現れてはなりません。

4c. 概念の利用可否チェック

各モジュールについて、次の項目を確認します。

  • 仕様で参照されているすべての :Concept: が、ローカルで定義されているか、import 経由で利用可能か、または requires に記載されたモジュールの exported_concepts 経由で利用可能である
  • exported_concepts に、下流モジュールが必要とするすべての概念が含まれている
  • モジュール間で概念名が重複していない
4d. モジュールごとの構造検証

新しい各モジュールについて、次の項目を確認します。

  • 機能仕様が少なくとも1つ、実装要件が少なくとも1つある
  • YAML フロントマターが正しく記述されている
  • requires と import のパスが正しい
  • モジュールファイルがリポジトリのルートにある(template/ 内ではない)
  • 仕様が言語に依存しない
  • すべての外部インターフェースが明示されている
4e. 新しいモジュールをすべて読む

新しい各 .plain ファイルを最後まで読み、最終的な構造をユーザーに提示して承認を得ます。ユーザーから変更の依頼があった場合は、変更を適用して再検証します。

よくある落とし穴

細分化しすぎる

仕様が1~2個だけの小さなモジュールを多数作成すると、明確さが増すことなくオーバーヘッドが増えます。テーマに一貫性を持たせてグループ化し、モジュールごとに機能仕様が3~10個になるようにします。

時系列順序を崩す

エントリーポイント、データベースの初期化、コア CRUD など、基盤となる動作を設定する仕様は、複数のドメインの概念に関係していても、チェーンのルートに維持する必要があります。仕様を明確に分離できる場合にのみ分割します。

exported_concepts を忘れる

モジュール A で定義された概念が、モジュール A を requires するモジュール B の仕様で参照される場合、その概念を A の exported_concepts に含める必要があります。エクスポートが不足すると、レンダリングに失敗します。

分割時に仕様テキストを変更する

これはリファクタリングであり、書き直しではありません。仕様テキストはそのままコピーする必要があります。仕様を新しいモジュールのコンテキストに合わせて言い換える必要がある場合は、分割境界が適切でないことを示しています。その場合はグループ分けを調整します。

テスト用 plain ファイルを失う

テスト用 plain ファイルは、module: と func_id: によって機能に紐付けられます。機能を新しいモジュールに移動すると、その module: キーが変わり、ファイルも新しいモジュールの慣例に沿った場所へ移動します。そうしないと、レンダラーはどの機能にも一致しないペアとして報告します。

検証チェックリスト

  • 実行前にユーザーが分割計画を確認した
  • 元の機能仕様がすべて、いずれか1つの新しいモジュールに含まれている(失われたものがない)
  • 仕様テキストが元のものと同一である(言い換えがない)
  • テスト用 plain ファイルが機能とともに移動され、新しいモジュールに再紐付けされている
  • requires チェーン全体で時系列順序が保たれている
  • 参照されるすべての :Concept: が各モジュールで利用可能である(ローカル、インポート、またはエクスポート経由)
  • 各モジュールの exported_concepts が正しく設定されている
  • 概念名が重複していない
  • 各モジュールに機能仕様が少なくとも1つ、実装要件が少なくとも1つある
  • requires チェーンが正しい順序になっている(ルート → リーフ)
  • 元のモジュールが削除または更新されている
  • 下流モジュール(存在する場合)が、チェーンの最終モジュールに加え、参照するエクスポート済み概念があるチェーン上の先行モジュールも requires するよう更新されている
  • ユーザーが最終結果を承認した

コメント