ルール1: 1つのメソッドにつきインデントは1段階までに
すること
リファクタリング前 :
class Board {
fun board(): String =
buildString {
for (row in data) {
for (square in row)
append(square)
appendLine()
}
}
}
10
リファクタリング後 :
class Board {
fun board(): String =
buildString {
collectRows( this)
}
fun collectRows(sb: StringBuilder) { // 拡張関数にする案も
for (row in data)
collectRow(sb, row)
}
fun collectRow(sb: StringBuilder, row: List<Square>) {
for (square in row)
sb.append(square)
sb.appendLine()
}
}
11
ルール2: else句を使用しないこと
リファクタリング前 :
リファクタリング後 :
fun endMe() {
if (status == DONE) {
doSomething()
} else {
doSomethingElse()
}
}
fun endMe() {
if (status == DONE) {
doSomething()
return
}
doSomethingElse()
}
12
リファクタリング前 :
リファクタリング後 :
fun head(): Node {
if (isAdvancing())
return first
else
return last
}
fun head(): Node =
if (isAdvancing()) first else last
13
ルール4: 1行につきドットは1つまでにすること
リファクタリング前 :
class Board {
class Piece(..., val representation: String)
class Location(..., val current: Piece)
fun boardRepresentation(): String =
buildString {
for (l in squares())
append(l.current.representation.substring( 0,
1))
}
}
14
リファクタリング後 :
class Board {
class Piece(..., private val representation: String) {
fun character(): String =
representation.substring( 0, 1)
fun addTo(sb: StringBuilder) {
sb.append(character())
}
}
class Location(..., private val current: Piece) {
fun addTo(sb: StringBuilder) {
current.addTo(sb)
}
}
// 次ページに続く
15
// 前ページから続く
fun boardRepresentation(): String =
buildString {
for (l in squares())
l.addTo( this)
}
}
16
ルール7: 1つのクラスにつきインスタンス変数は2つま
でにすること
リファクタリング前 :
class Name(
val first: String,
val middle: String,
val last: String,
)
17
リファクタリング後 :
class Name(
val family: Surname,
val given: GivenNames,
)
class Surname(val family: String)
class GivenNames(val names: List<String>)
18
ルール3: 関数は引数以外の入力に依存しないこと
リファクタリング前 :
リファクタリング後 :
var n: Int = 42 // 関数外の不安定な変数 /値
fun f(x: Int): Int = x + n
fun f(x: Int, y: Int): Int = x + y
// 適宜、インター フェー スを整え る
fun g(x: Int): Int = f(x, 42)
fun h(x: Int, y: Int = 42): Int = f(x, y)
35
ルール9: 不正な状態が表せないようにデータ型の選択/
定義で制限すること
リファクタリング前 :
data class User(
val id: UserId,
val isRegistered: Boolean,
val isActive: Boolean,
val joinedAt: LocalDateTime?,
val leftAt: LocalDateTime?,
) {
companion object {
fun registeringUser(id: UserId): User =
User(id, false, false, null, null)
fun activeUser(id: UserId, /* 略 */): User =
User(id, true, true, joinedAt, null)
fun inactiveUser(id: UserId, /* 略 */): User =
User(id, true, false, joinedAt, leftAt)
}
}
49
リファクタリング後 :
sealed interface User {
val id: UserId
data class RegisteringUser(
override val id: UserId,
) : User
data class ActiveUser(
override val id: UserId,
val joinedAt: LocalDateTime,
) : User
data class InactiveUser(
override val id: UserId,
val joinedAt: LocalDateTime,
val leftAt: LocalDateTime,
) : User
}
50