1. 概要(Overview)
Replace Type Code with Class は、定数や数値で表現している「型コード(type code)」を、
明示的なクラス に置き換えるリファクタリングです。
例:
- 「1 = エンジニア, 2 = マネージャー」などの 数字
-
"S"や"P"などの 文字列コード
こうした「マジックコード」は意味が不明瞭で、比較や変更に弱いです。
専用クラスに置き換えることで:
- 意味を明示化
- 不正値を防止
- 振る舞いを追加可能
2. 適用シーン(When to Use)
- 数字や文字列を 型コード(識別子) として使っている
- if/switch 文で型コードを分岐している
- 「型コードに応じた振る舞い」を拡張したい
- 意図しない値(
999や"X")が入り込む危険がある
よくある匂い:
- Magic Number / String(マジックナンバー/文字列)
- Primitive Obsession(基本型執着)
3. 手順(Mechanics / Steps)
- 型コードを使っているフィールドや定数を特定
- それを表す新しいクラスを導入
- 型コードをそのクラスのインスタンスに置き換える
- クライアントコードを修正して、新しいクラスを利用するようにする
- 必要なら、そのクラスに振る舞いを追加
4. Kotlin 例(Before → After)
Before:型コードを int で管理
class Employee(val name: String, val type: Int) {
companion object {
const val ENGINEER = 0
const val MANAGER = 1
const val SALESMAN = 2
}
}
fun main() {
val alice = Employee("Alice", Employee.ENGINEER)
if (alice.type == Employee.ENGINEER) {
println("${alice.name} is an engineer")
}
}
-
0, 1, 2の数字が「職種コード」として使われている - 意味が分かりにくく、不正な値(
999)も入り込める
After:クラスに置き換え
class EmployeeType private constructor(val name: String) {
companion object {
val ENGINEER = EmployeeType("Engineer")
val MANAGER = EmployeeType("Manager")
val SALESMAN = EmployeeType("Salesman")
}
override fun toString(): String = name
}
class Employee(val name: String, val type: EmployeeType)
fun main() {
val alice = Employee("Alice", EmployeeType.ENGINEER)
println("${alice.name} is a ${alice.type}")
}
- 型コードを
EmployeeTypeクラスにまとめて明示化 - 不正な値を使えなくなり、意図が明確になる
After②:振る舞いを型クラスに追加
class EmployeeType private constructor(val title: String) {
companion object {
val ENGINEER = EmployeeType("Engineer")
val MANAGER = EmployeeType("Manager")
val SALESMAN = EmployeeType("Salesman")
}
fun calculateOvertimePay(hours: Int): Int {
return when (this) {
ENGINEER -> hours * 20
MANAGER -> hours * 30
SALESMAN -> hours * 10
else -> 0
}
}
override fun toString(): String = title
}
class Employee(val name: String, val type: EmployeeType) {
fun overtimePay(hours: Int): Int = type.calculateOvertimePay(hours)
}
→ 型コードに応じたロジックを EmployeeType に集約可能。
5. 効果(Benefits)
- マジックナンバー/文字列を排除して 意図が明確に
- 不正値を防止できる(型安全)
- 型コードごとの振る舞いをクラスにまとめられる
- Primitive Obsession を解消し、ドメインモデルがリッチに
6. 注意点(Pitfalls)
- 小規模・一時的なコードに適用すると冗長になる
- 定数だけなら enum class の方が適切な場合も多い
- 拡張可能性が不要なら、まずは
enumを検討する
まとめ
- Replace Type Code with Class は「数字や文字列コードを明示的なクラスに置き換える」リファクタリング
- 判断基準:その型コードは不正値を防ぎ、振る舞いを追加する価値があるか?
- 基本思想:意味ある概念はクラスで表現し、コードを自己文書化する