0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【リファクタリング】Introduce Parameter Object(パラメータオブジェクトの導入)

Posted at

1. 概要(Overview)

Introduce Parameter Object は、
メソッドに渡す 長い引数リスト(特に「いつも一緒に使われるデータの塊」)を、
オブジェクトとしてまとめて渡す ようにするリファクタリングです。

目的

  • 引数リストを短くして メソッド呼び出しをシンプルにする
  • 関連データをひとまとまりにして 意味を明確にする
  • データのまとまりにふさわしい 振る舞い(メソッド) を追加できる

2. 適用シーン(When to Use)

  • メソッドの引数が多すぎる(3つ以上が目安)
  • いつも同じセットの引数を一緒に渡している
  • データの組み合わせが意味を持っている(例:日付の範囲、座標、個人情報など)
  • 同じ引数の組み合わせが複数メソッドに渡されている

よくある匂い:

  • Long Parameter List(長すぎる引数リスト)
  • Data Clumps(いつも一緒に現れるデータの塊)

3. 手順(Mechanics / Steps)

  1. いつも一緒に渡されている引数群を特定
  2. それらをまとめる 新しいクラス(データクラス) を作成
  3. 新クラスをメソッドの引数に置き換える
  4. 呼び出し側を修正してオブジェクトを生成して渡す
  5. 必要ならそのオブジェクトに関連メソッドを追加する

4. Kotlin 例(Before → After)

4.1 単純な例:日付範囲

Before

fun getInvoices(startDate: LocalDate, endDate: LocalDate): List<String> {
    println("Fetching invoices from $startDate to $endDate")
    return emptyList()
}

val invoices = getInvoices(LocalDate.of(2025,1,1), LocalDate.of(2025,1,31))

After

data class DateRange(val start: LocalDate, val end: LocalDate)

fun getInvoices(range: DateRange): List<String> {
    println("Fetching invoices from ${range.start} to ${range.end}")
    return emptyList()
}

val invoices = getInvoices(DateRange(LocalDate.of(2025,1,1), LocalDate.of(2025,1,31)))

4.2 ビジネス例:顧客情報

Before

fun registerCustomer(name: String, email: String, phone: String) {
    println("Registering $name, $email, $phone")
}

registerCustomer("Anna", "anna@example.com", "123-456")

After

data class CustomerInfo(val name: String, val email: String, val phone: String)

fun registerCustomer(info: CustomerInfo) {
    println("Registering ${info.name}, ${info.email}, ${info.phone}")
}

registerCustomer(CustomerInfo("Anna", "anna@example.com", "123-456"))

4.3 発展:振る舞いを追加

data class DateRange(val start: LocalDate, val end: LocalDate) {
    fun includes(date: LocalDate): Boolean = !date.isBefore(start) && !date.isAfter(end)
}

fun getInvoices(range: DateRange): List<String> {
    if (!range.includes(LocalDate.now())) {
        println("Warning: today is not in range")
    }
    return emptyList()
}
  • 単なるデータの塊に ビジネスロジック を追加できる

5. 効果(Benefits)

  • メソッド呼び出しが 短く明快になる
  • 引数の組み合わせの意味が 型で表現される
  • 将来的に関連ロジックをまとめやすい(ドメインオブジェクト化)
  • 重複コード削減(毎回同じセットを渡す必要なし)

6. 注意点(Pitfalls)

  • 過度に小さいデータまでオブジェクト化すると、クラス乱立で逆に複雑化
  • そのオブジェクトが本当に「ひとまとまりの概念」かを見極める必要がある
  • DTO(ただのデータ入れ物)に留まってしまい、中途半端な責務になる危険

まとめ

  • Introduce Parameter Object は「いつも一緒に渡す引数群」を オブジェクトにまとめる リファクタリング
  • 判断基準:引数のセットはひとつの概念として表せるか?
  • 基本思想:引数を減らし、意味のある「オブジェクト」として再利用・拡張できるようにする

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?