java-refactoring-extract-method について
Java の動作を変えずに Extract Method リファクタリングを行うためのスキルです。候補の特定、安全な抽出条件、テストとコンパイルによる検証を扱います。
主な機能
- 01複雑なメソッドと一貫したブロックを特定
- 02動作とメソッドの可視性を維持
- 03制御フローと副作用を考慮
- 04利用可能な IDE のリファクタリングを優先
- 05テストとコンパイルを実行
活用シーン
- 01長い Java メソッドを目的別のメソッドに分割
- 02動作を変えずに可読性を改善
- 03既存テストでメソッド抽出を検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ github/ awesome-copilot --skill java-refactoring-extract-methodインストール後、Claude Code で/java-refactoring-extract-methodを入力して読み込まれたか確認します。
詳細
Extract Method による Java メソッドのリファクタリング
役割
Java メソッドのリファクタリングに精通しています。
以下に 2 つの例(リファクタリング前とリファクタリング後のコードを含む)を示します。これらは Extract Method の例です。
リファクタリング前のコード 1:
public FactLineBuilder setC_BPartner_ID_IfValid(final int bpartnerId) {
assertNotBuild();
if (bpartnerId > 0) {
setC_BPartner_ID(bpartnerId);
}
return this;
}
リファクタリング後のコード 1:
public FactLineBuilder bpartnerIdIfNotNull(final BPartnerId bpartnerId) {
if (bpartnerId != null) {
return bpartnerId(bpartnerId);
} else {
return this;
}
}
public FactLineBuilder setC_BPartner_ID_IfValid(final int bpartnerRepoId) {
return bpartnerIdIfNotNull(BPartnerId.ofRepoIdOrNull(bpartnerRepoId));
}
リファクタリング前のコード 2:
public DefaultExpander add(RelationshipType type, Direction direction) {
Direction existingDirection = directions.get(type.name());
final RelationshipType[] newTypes;
if (existingDirection != null) {
if (existingDirection == direction) {
return this;
}
newTypes = types;
} else {
newTypes = new RelationshipType[types.length + 1];
System.arraycopy(types, 0, newTypes, 0, types.length);
newTypes[types.length] = type;
}
Map<String, Direction> newDirections = new HashMap<String, Direction>(directions);
newDirections.put(type.name(), direction);
return new DefaultExpander(newTypes, newDirections);
}
リファクタリング後のコード 2:
public DefaultExpander add(RelationshipType type, Direction direction) {
Direction existingDirection = directions.get(type.name());
final RelationshipType[] newTypes;
if (existingDirection != null) {
if (existingDirection == direction) {
return this;
}
newTypes = types;
} else {
newTypes = new RelationshipType[types.length + 1];
System.arraycopy(types, 0, newTypes, 0, types.length);
newTypes[types.length] = type;
}
Map<String, Direction> newDirections = new HashMap<String, Direction>(directions);
newDirections.put(type.name(), direction);
return (DefaultExpander) newExpander(newTypes, newDirections);
}
protected RelationshipExpander newExpander(RelationshipType[] types,
Map<String, Direction> directions) {
return new DefaultExpander(types, directions);
}
安全性に関するルール
- 動作を維持すること:機能の変更、ロジックの削除、例外の変更、副作用の順序や元のメソッドの可視性の変更を行わないでください。
- まずベースラインを確認すること:コードに対して最も対象を絞った成功するテストコマンド(
./mvnw -q -Dtest=MyTest test、./gradlew test --tests MyTest)または./mvnw verify/./gradlew buildを実行してください。抽出のたびに再実行してください。ベースラインが失敗した場合は中止して報告してください。 - コードにテストがない場合は中止して報告してください。まず特性化テストを提案してください。テストを削除したり、弱めたりしないでください。
- 1 ステップにつき 1 つの抽出のみ行ってください(ユーザーがコミットを求めている場合は、1 コミットにつき 1 つ)。これにより、各変更をレビューし、元に戻せるようにします。
- IDE のリファクタリングを優先してください:Extract Method を提供する IDE ツールが利用可能な場合は、それを使用してください(パラメーターと戻り値を安全に処理できます)。Copilot CLI の
lspツールはナビゲーションと名前変更に対応していますが、コードアクションには対応していないため、lsp-setupで jdtls を設定しても利用できません。そうでない場合は手作業で抽出し、コンパイラーとテストで検証してください。 - 抽出したメソッドはデフォルトで
privateにしてください。public/protectedメソッドを追加したり、既存のシグネチャを変更したり、ユーザーに確認せずに生成コード(target/、build/generated、@Generated)に触れたりしないでください。 - 次の点に注意してください:ブロック内で変更されるローカル変数(値を返すか、小さな結果型を導入してください)、複数の戻り値、検査例外、ブロック内の
return/break/continue、およびsynchronized/トランザクションアノテーション付きメソッド(thisで呼び出される抽出後のprivateメソッドは Spring プロキシと AOP を迂回します)。
タスク
可読性、テスト容易性、凝集性、一貫性を高めるために Extract Method を適用してください。
- 複雑度の高いメソッド(目安:15 行超、10 個超の文、または循環的複雑度 10 超)と、その中の凝集性のあるブロックを特定してください。
- 各ブロックを、既存のコードスタイルとプロジェクトの Java バージョンに従って、説明的な名前のメソッドに抽出してください(
maven.compiler.release/ツールチェーンを確認し、新しい構文は使用しないでください)。 - 新しいメソッドの名前だけでは目的が伝わらない場合に限り、そのメソッドの上に 1 行のコメントを追加してください。
- コンパイルしてテストを実行し、変更したメソッド、実行したコマンド、およびその結果を報告してください。
変更した各メソッドの、コンパイル可能なコード全体を出力してください。
リファクタリング対象コード:
次に、複雑度の高いすべてのメソッドを評価し、Extract Method を適用してリファクタリングしてください。
コメント
Markdown 対応