1. 概要(Overview)
Replace Parameter with Method Call は、
呼び出し側で計算済みの値や外部から渡されたパラメータを使う代わりに、
その値をメソッドの内部で直接取得する ように変更するリファクタリングです。
目的:
- 呼び出し側から「余計な計算」や「不要な情報渡し」を取り除く
- API のシンプル化(引数の削減)
- データ取得の責務を呼び出し側ではなくオブジェクト自身に持たせる
2. 適用シーン(When to Use)
- 引数として渡される値が、呼び出し側で計算しているだけのもの
- メソッド内で すでに同じ情報を取得可能
- 「呼び出し側が本来知るべきでない情報」を引数にしている
よくある匂い:
- Long Parameter List(長すぎる引数リスト)
- Inappropriate Intimacy(不適切な親密さ:外部に余計な情報を求めている)
- Feature Envy(呼び出し側が本来持つべきでないロジックを持っている)
3. 手順(Mechanics / Steps)
- パラメータがどのように算出されているか確認
- その値を呼び出し側ではなく、対象オブジェクト自身が計算できるかを検討
- メソッドの引数から不要なパラメータを削除
- メソッド内部で必要な計算や呼び出しを実装
- 呼び出し側を修正し、冗長な計算を取り除く
4. Kotlin 例(Before → After)
4.1 顧客の割引(呼び出し側で計算)
Before
class Customer(val orders: List<Int>) {
fun getDiscountPrice(orderCount: Int): Int {
return if (orderCount > 5) 100 else 0
}
}
fun main() {
val customer = Customer(listOf(10, 20, 30))
val discount = customer.getDiscountPrice(customer.orders.size) // 呼び出し側で size を計算
println(discount)
}
After
class Customer(val orders: List<Int>) {
fun getDiscountPrice(): Int {
val orderCount = orders.size
return if (orderCount > 5) 100 else 0
}
}
fun main() {
val customer = Customer(listOf(10, 20, 30))
val discount = customer.getDiscountPrice() // スッキリ!
println(discount)
}
4.2 日付の比較(呼び出し側で取得 → メソッド内部へ)
Before
class Subscription(val startDate: LocalDate, val endDate: LocalDate)
fun isActive(subscription: Subscription, today: LocalDate): Boolean {
return today.isBefore(subscription.endDate)
}
val sub = Subscription(LocalDate.now(), LocalDate.now().plusDays(30))
println(isActive(sub, LocalDate.now())) // today を毎回渡す必要がある
After
class Subscription(val startDate: LocalDate, val endDate: LocalDate) {
fun isActive(): Boolean {
val today = LocalDate.now()
return today.isBefore(endDate)
}
}
val sub = Subscription(LocalDate.now(), LocalDate.now().plusDays(30))
println(sub.isActive()) // 呼び出し側がシンプルに!
5. 効果(Benefits)
- 呼び出しコードが短く、意図が明確になる
- パラメータリストを減らせる(API がシンプルになる)
- 呼び出し側に不要な知識(内部データや計算方法)を持たせなくてよい
- 変更に強くなる(内部の計算方法が変わっても呼び出し側は影響を受けない)
6. 注意点(Pitfalls)
- 内部で取得できない情報(外部入力や利用者依存のデータ)は削除できない
- 内部での計算コストが大きい場合、呼び出し側でキャッシュした方が効率的なケースもある
- 責務の所在が曖昧にならないよう注意(「どこで計算すべきか」を設計レベルで判断)
まとめ
-
Replace Parameter with Method Call は「呼び出し側で計算・取得して渡している値」を、
メソッド内で直接取得するように変えるリファクタリング - 判断基準:呼び出し側が知るべきでない情報を渡していないか?
- 基本思想:値を知っている責務を持つオブジェクトに計算を移し、API をシンプルに保つ