1. 概要(Overview)
Replace Array with Object は、
配列を使って複数の関連データを「位置(インデックス)」で管理している場合に、
それを 意味のあるフィールドを持ったオブジェクト に置き換えるリファクタリングです。
目的は以下の通りです:
- 「配列の何番目に何が入っているか?」という不透明さを解消
- データに意味を与えて、コードの可読性・保守性を向上
- バグを減らし、自己文書化的なコードにする
2. 適用シーン(When to Use)
- 配列が「複数の異なる種類の情報」をまとめて持っている
- 要素番号に意味があり、読み手が暗黙的なルールを理解しないといけない
- 値を追加・変更するときに インデックスを間違えやすい
- 例:
[ "Alice", "24" ]のように「名前」「年齢」を配列の位置で表現している
よくある匂い:
- Data Clumps(データのかたまり)
- Obscure Intent(意図の不明確さ)
3. 手順(Mechanics / Steps)
- 配列の要素が持つ意味を特定
- 新しいクラスを作成し、各要素をフィールドに分割
- 配列の利用箇所をクラスのプロパティに置き換える
- 配列を完全に置き換える
4. Kotlin 例(Before → After)
Before:配列を使った不明確なコード
fun main() {
val person = arrayOf("Alice", "24")
println("Name: ${person[0]}")
println("Age: ${person[1]}")
}
-
person[0]が名前、person[1]が年齢というルールはコードを読まないと分からない - 可読性・保守性が低い
After:オブジェクトに置き換える
data class Person(val name: String, val age: Int)
fun main() {
val person = Person("Alice", 24)
println("Name: ${person.name}")
println("Age: ${person.age}")
}
-
nameやageが明示的に表現され、意図が一目で分かる - 型も厳密になり(文字列 vs 整数)、安全性が高い
さらに進化:振る舞いを持たせる
data class Person(val name: String, val age: Int) {
fun isAdult(): Boolean = age >= 18
}
fun main() {
val person = Person("Alice", 24)
println("${person.name} is adult? ${person.isAdult()}")
}
→ 配列では表現できなかった 振る舞い(ロジック) を持たせられる
5. 効果(Benefits)
- 配列のインデックスに依存せず、意図が明確になる
- 型安全性が向上し、バグが減る
- データに関連する振る舞いをまとめられる
- ドメインモデルとして表現力が高まる
6. 注意点(Pitfalls)
- 小さな一時配列にまで適用すると、クラスが増えすぎて冗長になる
- 本当に「リスト」でよい場合(例:人数不定のユーザー一覧)には適用しない
- 配列の置き換え後、不要なゲッター/セッターだけのクラスにならないよう注意
まとめ
- Replace Array with Object は「配列のインデックス依存をなくし、意味のあるオブジェクトに変換する」リファクタリング
- 判断基準:この配列は実は「異なる意味を持つデータの集まり」ではないか?
- 基本思想:データに名前を与えて、コードの可読性と安全性を高める