1. 概要(Overview)
Replace Method with Method Object は、長大なメソッド を専用のクラスに切り出し、その中で処理を実行するリファクタリングです。
メソッドが長く複雑になると、
- ローカル変数が増えて処理が見通しづらい
- 途中で Extract Method(メソッドの抽出) がしづらい
- 修正が入りやすく「散弾銃のような変更(Shotgun Surgery)」になりがち
といった問題が起こります。
このリファクタリングでは、**メソッドをクラス化(Method Object 化)**し、フィールドとしてローカル変数を保持できるようにすることで、メソッドの分割や整理を容易にします。
2. 適用シーン(When to Use)
- メソッドが長すぎる/複雑すぎる
- ローカル変数が多く、Extract Method で簡単に切り出せない
- 同じロジックを別の状況でも再利用したい
- 状態を保持しながら複数の小メソッドに分割したい
よくある匂い:
- Long Method(長すぎるメソッド)
- Temporary Field(不要な一時変数)
- Shotgun Surgery(散弾銃のような変更)
3. 手順(Mechanics / Steps)
- 問題のある長いメソッドを特定
- 新しいクラスを作成し、そのクラスに元メソッドのローカル変数をフィールドとして移動
- 元メソッドを新しいクラスのインスタンス生成+実行呼び出しに置き換える
- 新しいクラスの中でメソッドを小さく分割(Extract Method を適用)
- テストを実行して動作確認
4. Kotlin 例(Before → After)
Before:長大なメソッド
class Order(val items: List<Double>) {
fun calculateSummary(discountRate: Double): Double {
var subtotal = items.sum()
val discount = subtotal * discountRate
subtotal -= discount
val tax = subtotal * 0.1
return subtotal + tax
}
}
- ロジックがまとまっていて一見シンプルに見えるが、
実際の業務ロジックでは 条件分岐や計算式が膨張しやすい。 -
subtotalやdiscountといったローカル変数が増えると、Extract Method が難しくなる。
After①:メソッドをクラス化
class Order(val items: List<Double>) {
fun calculateSummary(discountRate: Double): Double {
return OrderSummaryCalculator(this, discountRate).calculate()
}
}
class OrderSummaryCalculator(
private val order: Order,
private val discountRate: Double
) {
private var subtotal: Double = 0.0
fun calculate(): Double {
subtotal = order.items.sum()
applyDiscount()
val tax = subtotal * 0.1
return subtotal + tax
}
private fun applyDiscount() {
val discount = subtotal * discountRate
subtotal -= discount
}
}
→ ロジックをクラスに移し、フィールドとして保持できるため 責務の分割 が容易に。
After②:さらに小さいメソッドに分割
class OrderSummaryCalculator(
private val order: Order,
private val discountRate: Double
) {
private var subtotal: Double = 0.0
fun calculate(): Double {
calculateSubtotal()
applyDiscount()
return addTax()
}
private fun calculateSubtotal() {
subtotal = order.items.sum()
}
private fun applyDiscount() {
subtotal -= subtotal * discountRate
}
private fun addTax(): Double {
return subtotal + subtotal * 0.1
}
}
→ 小さなメソッドに分割でき、テストしやすく保守性が高い設計に。
5. 効果(Benefits)
- 長大なメソッドを整理可能
- ローカル変数をフィールド化でき、Extract Method が適用しやすい
- ロジックを分割・テストしやすくなる
- 状態を持った「計算オブジェクト」として再利用可能
6. 注意点(Pitfalls)
- 小規模なメソッドに対して使うと逆に冗長になる
- クラスを増やすため、設計全体が複雑になりすぎないよう注意
- 「このメソッドは本当にクラス化するほどの責務を持っているか?」を判断する必要がある
まとめ
- Replace Method with Method Object は「長大なメソッドをクラスに切り出して整理」するリファクタリング
- 判断基準:ローカル変数が多すぎてメソッド抽出が難しいか?
- 基本思想:状態を保持できる専用オブジェクトに変換し、責務を分割して保守性を高める