1. 概要(Overview)
Pull Up Method は、サブクラスに重複して存在する 同一/ほぼ同一のメソッド実装 を
スーパークラスへ移動(引き上げ) して共通化するリファクタリングです。
目的:
- 重複実装を一箇所に集約して保守性を上げる
- 振る舞いの“共通契約”を上位で明示し、設計をクリアにする
- バグ修正や仕様変更の波及を最小化
2. 適用シーン(When to Use)
- 複数のサブクラスに 同じロジック のメソッドがある
- メソッド名は同じだが実装がごく小さな差分しかない(共通化可能)
- 上位型(ポリモーフィックに扱う)経由で共通メソッドを呼びたい
よくある匂い:
- Duplicate Code(重複コード)
- Parallel Inheritance Hierarchies(並行継承階層)
3. 手順(Mechanics / Steps)
- サブクラスの重複メソッドを比較し、共通部分を特定
- 共通化できるなら、その実装を スーパークラスへ移動
- 差分が残る場合は:
- Template Method を導入(フックメソッドで差分を下位へ)
- もしくは差分を 別メソッドに抽出 してオーバーライドさせる
- サブクラス側の重複定義を削除
- テストを実行し回帰を確認
4. Kotlin 例(Before → After)
4.1 完全一致するメソッドの引き上げ
Before
open class Employee
class Engineer(val name: String) : Employee() {
fun displayInfo(): String = "Employee: $name"
}
class Manager(val name: String) : Employee() {
fun displayInfo(): String = "Employee: $name"
}
After
open class Employee(open val name: String) {
fun displayInfo(): String = "Employee: $name"
}
class Engineer(override val name: String) : Employee(name)
class Manager(override val name: String) : Employee(name)
- 重複していた
displayInfo()をEmployeeに引き上げ
4.2 小さな差分がある場合:Template Method で引き上げ
Before
class CsvReport : Report() {
fun export(): String = "header\n" + buildBody() + "\nfooter"
private fun buildBody() = "csv rows"
}
class JsonReport : Report() {
fun export(): String = "{ \"header\": true, " + buildBody() + ", \"footer\": true }"
private fun buildBody() = "\"json\": \"rows\""
}
open class Report
After(共通フローを上位に、差分はフックで)
open class Report {
fun export(): String = wrap(buildBody())
protected open fun buildBody(): String = ""
protected open fun wrap(body: String): String = body
}
class CsvReport : Report() {
override fun buildBody(): String = "csv rows"
override fun wrap(body: String): String = "header\n$body\nfooter"
}
class JsonReport : Report() {
override fun buildBody(): String = "\"json\": \"rows\""
override fun wrap(body: String): String =
"{ \"header\": true, $body, \"footer\": true }"
}
- 共通の手順(export フロー)を上位へ引き上げ、差分はオーバーライド
5. 効果(Benefits)
- 重複排除により修正コストを削減
- 共通 API を スーパークラスで保証(契約の明確化)
- ポリモーフィズムで上位型経由の呼び出しが可能に
6. 注意点(Pitfalls)
- 「本当にすべてのサブクラスで同じか?」を慎重に評価
- 一部のみなら Pull Up の対象外、または 抽象メソッド化を検討
- 無理な引き上げは スーパークラスの責務過多(God Class 化) を招く
- 共有化で隠れた依存が増えるなら、**委譲(委譲オブジェクト)**や Strategy も検討
まとめ
- Pull Up Method は、サブクラスに散らばる同一/類似メソッドを 上位へ集約して保守性を高める手法
- 判断基準:共通部分が十分に大きいか? 上位に置くのが自然か?
- 差分が残るなら Template Method / Strategy / Hook メソッド を併用して設計を整える