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 Local Extension(ローカル拡張の導入)

Posted at

1. 概要(Overview)

Introduce Local Extension は、既存のクラスに便利なメソッドを追加したいが、

  • そのクラスを直接修正できない(外部ライブラリや標準 API)
  • しかも 複数の関連メソッドをまとめて追加したい

といったケースで使うリファクタリングです。

Kotlin では 拡張関数や拡張プロパティをまとめたクラス/ファイル を導入する形になります。
Java ならユーティリティクラスを導入して、既存クラスに「追加 API」を提供するのが一般的です。

目的は以下の通りです:

  • 外部クラスに対する操作を拡張しつつ、整理してまとめる
  • 再利用性を高め、重複を減らす
  • クライアントコードをシンプルで表現力豊かにする

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

  • 外部クラスに 複数の便利メソッドを追加したい
  • それらを 1つのまとまり(拡張クラス/拡張ファイル) として管理したい
  • プロジェクト内で ローカルにだけ必要な拡張 を導入したい

例:

  • LocalDate に「翌日」「月末」「週の始まり」などの操作を追加
  • String に「isEmail」「isPhoneNumber」「mask」などを追加

3. 手順(Mechanics / Steps)

  1. 外部クラスに追加したい便利メソッドを洗い出す
  2. 新しい拡張クラス(または拡張用ファイル)を作成
  3. 拡張関数や拡張プロパティを定義
  4. クライアントコードからそれを利用するように変更
  5. テストで正しく動作することを確認

4. Kotlin 例(Before → After)

Before:外部クラスを毎回直接操作している

import java.time.LocalDate

fun printDates(date: LocalDate) {
    val tomorrow = date.plusDays(1)
    val monthEnd = date.withDayOfMonth(date.lengthOfMonth())
    println("Tomorrow: $tomorrow, End of Month: $monthEnd")
}
  • plusDayswithDayOfMonth が毎回登場して冗長
  • 「明日」「月末」といった意味が伝わりにくい

After:ローカル拡張を導入

import java.time.LocalDate

// ✅ LocalDate 用の拡張をまとめる
object LocalDateExtensions {
    fun LocalDate.nextDay(): LocalDate = this.plusDays(1)
    fun LocalDate.endOfMonth(): LocalDate = this.withDayOfMonth(this.lengthOfMonth())
}

// クライアントコード
fun printDates(date: LocalDate) {
    with(LocalDateExtensions) {
        println("Tomorrow: ${date.nextDay()}, End of Month: ${date.endOfMonth()}")
    }
}

LocalDate に本来あるかのように自然に使える。
→ 複数の便利メソッドをまとめて管理できる。


After②:Kotlin ならファイルレベルで拡張を定義してもOK

// LocalDateExt.kt
package extensions

import java.time.LocalDate

fun LocalDate.nextDay(): LocalDate = this.plusDays(1)
fun LocalDate.endOfMonth(): LocalDate = this.withDayOfMonth(this.lengthOfMonth())

クライアントコード:

import extensions.*

fun printDates(date: LocalDate) {
    println("Tomorrow: ${date.nextDay()}, End of Month: ${date.endOfMonth()}")
}

5. 効果(Benefits)

  • 外部クラスを「ローカルで拡張」でき、自然な API で利用可能
  • 関連する拡張をまとめることで 整理しやすく再利用性が高い
  • クライアントコードがシンプルで表現力豊かになる

6. 注意点(Pitfalls)

  • 拡張が増えすぎると 本来のクラスの API と競合する危険がある
  • プロジェクト全体で拡張をどう管理するかルールを決めないと、乱立してスパゲッティ化する
  • 公開 API に含めるか、ローカル専用にとどめるか を明確にする

まとめ

  • Introduce Local Extension は「外部クラスに複数の便利メソッドをまとめて追加」するリファクタリング
  • 判断基準:この拡張はプロジェクト全体で必要か?ローカルで十分か?
  • 基本思想:拡張を整理し、自然な API として使えるようにする

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?