TDD, ํด๋ฆฐ ์ฝ๋ with Kotlin 6๊ธฐ ์๋์ฐจ ๊ฒฝ์ฃผ ํผ๋๋ฐฑ
๋๋ฉ์ธ ํ๋กํผํฐ ์ ๊ทผ ์ ์ด์
custom setter์ getter์ ์ฌ์ฉ
์ฝํ๋ฆฐ์์๋ ํ๋กํผํฐ์ ๋ํ getter์ setter๋ฅผ ์๋์ผ๋ก ์์ฑํด์ฃผ๊ธฐ ๋๋ฌธ์ ์ง์ getter๋ฅผ ๊ตฌํํ๊ธฐ๋ณด๋ค๋ ์๋ ์์์ ๊ฐ์ด ์ฝํ๋ฆฐ์ ์ข ๋ ์ฝํ๋ฆฐ์ค๋ฝ๊ฒ ๊ตฌํํ ์ ์๋ค.
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value) // parses the string and assigns values to other properties
}
์ฌ๊ธฐ์ ๋ ๋์๊ฐ, ๋๋ฉ์ธ์ var ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ธ๋ถ์ ๋ณ๊ฒฝ ๊ฐ๋ฅ ์ง์ ์ด ๋ ธ์ถ๋๊ธฐ ๋๋ฌธ์ ์ธ๋ถ์ ๋ณ๊ฒฝ ๊ฐ๋ฅ ์ง์ ์ ๋ ธ์ถํ๊ณ ์ถ์ง ์๋ค๋ฉด private set ์ ํตํด ํด๋์ค ์ธ๋ถ์์ ๋ณ๊ฒฝํ์ง ๋ชปํ๋๋ก ๋ง์ ์ ์๋ค.
class Car(
val name: String,
position: Int = DEFAULT_POSITION,
private val condition: MoveCondition = CarMoveCondition()
) {
init {
require(name.length <= 5) { "์๋์ฐจ์ ์ด๋ฆ์ 5๊ธ์๋ฅผ ๋์ ์ ์์ต๋๋ค." }
}
var position: Int = position
private set
}
๋ฐฉ์ด์ ๋ณต์ฌ
Cars ์ผ๊ธ ์ปฌ๋ ์ ์ ๊ตฌํํ๋ฉฐ ๋ฆฌ๋ทฐ์ด๋๊ป Cars์ history ํ๋กํผํฐ๋ฅผ ๋ฐฉ์ด์ ๋ณต์ฌ๋ก ๋ฆฌํดํ๋ ๊ฒ์ ๋ํ ํผ๋๋ฐฑ์ ๋ฐ์๋ค.
์ฌ๊ธฐ์ ๋ฐฉ์ด์ ๋ณต์ฌ๋ ์์ฑ์์ ์ธ์๋ก ๋ฐ์ ๊ฐ์ฒด์ ๋ณต์ฌ๋ณธ์ ๋ง๋ค์ด ๋ด๋ถ ํ๋๋ฅผ ์ด๊ธฐํํ๊ฑฐ๋ getter๋ฉ์๋์์ ๋ด๋ถ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ ๋, ๊ฐ์ฒด์ ๋ณต์ฌ๋ณธ์ ๋ง๋ค์ด ๋ฐํํ๋ ๊ฒ์ด๋ค.
Cars์ history ํ๋กํผํฐ์ ๊ฒฝ์ฐ ๊ฒฝ์ฃผ ์ด๋ ฅ์ ์ ์ฅํ๋ ํ๋กํผํฐ์ด๊ธฐ ๋๋ฌธ์ ๊ณผ๊ฑฐ ์ํ๋ฅผ ๊ทธ๋ ๊ทธ๋ ์ ์ฅํด์ผํ๋ฏ๋ก ๊ฐ์ ์ด๊ธฐํ ๋๋ ๋ฐํํ ๋ ์ฃผ์ ์ฐธ์กฐ๋ฅผ ๋์ด์ฃผ์ด์ผ ํ๋ค. (๊ทธ๋ ์ง ์์ผ๋ฉด Cars์ ์ํ๊ฐ ๋ณํ ๋๋ง๋ค ์ด๋ ฅ๋ ๊ฐ์ด ๋ณํจ)
class Cars(
private val values: List<Car> = emptyList()
) {
val history get() = values.map { it.copy() }
fun race() {
values.forEach {
it.move()
}
}
}
์์ ๊ฐ์ด ์๋์ฐจ ๊ฒฝ์ฃผ ์ด๋ ฅ์ ์ ์ฅํ๊ธฐ ์ํด ๋ฐฉ์ด์ ๋ณต์ฌ + ๊น์ ๋ณต์ฌ ๋ฅผ ์ฌ์ฉํด history๋ฅผ backing property๋ก ๊ตฌํํด์ฃผ์๋ค.
์ฝํ๋ฆฐ์ map ์ ์๋ก์ด ๋ฆฌ์คํธ๋ก ๊ฐ์ธ์ ๋ฐํํ๊ธฐ ๋๋ฌธ์ ๋ฐฉ์ด์ ๋ณต์ฌ ๊ธฐ๋ฅ์ ํ๋ค. ์ฌ๊ธฐ์ ๋ฐฉ์ด์ ๋ณต์ฌ๋ ๊น์ ๋ณต์ฌ๊ฐ ์๋๋ค. ๋ฐฉ์ด์ ๋ณต์ฌ๋ฅผ ํตํด ๊ฐ์ฒด์ ๋ณต์ฌ๋ณธ์ ๋ง๋ค์์ด๋, ๋ด๋ถ ์์๋ค์ ์ฃผ์๋ ์๋ณธ๊ณผ ๊ณต์ ํ๊ณ ์๋ค.
Cars์ ๋ด๋ถ Car์ ์ํ๋ ๊ณ์ํด์ ๋ณํ ์ ์๊ธฐ ๋๋ฌธ์ copy() ๋ฅผ ํตํด ๊น์ ๋ณต์ฌ๋ฅผ ํจ๊ป ๊ฐ์ ธ๊ฐ๋ค.
๊ฐ์ฒด ๋ด๋ถ์ ๊ฐ์ ์ธ๋ถ๋ก๋ถํฐ ๋ณดํธํ๊ณ ์ถ์ ๋๋ ์ปฌ๋ ์ ์ ๋ฐฉ์ด์ ๋ณต์ฌ๋ฅผ ๋น๋กฏํด ๋ด๋ถ ์์(Car)๋ฅผ ๋ถ๋ณ ๊ฐ์ฒด ๋๋ ๊น์ ๋ณต์ฌ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์.
์ฐธ๊ณ
https://tecoble.techcourse.co.kr/post/2021-04-26-defensive-copy-vs-unmodifiable/