Step2
https://github.com/next-step/kotlin-blackjack/pull/528
Test Double
๋จ์ ํ ์คํธ๋ฅผ ์ํด ์์กด์ฑ ์ฃผ์ ๋ถ๋ถ์ ํ ์คํธ ๋๋ธ์ ์ฌ์ฉํด ํ ์คํธ๋ฅผ ์ข ๋ ํธ๋ฆฌํ๊ฒ ํ ์ ์๋๋ก ๊ตฌํํ์๋ค. ๋ค๋ง, ํผ๋๋ฐฑ์ ๋ฐ์ผ๋ฉฐ Stub, Mock, Fake ๋ฑ ํ ์คํธ ๋๋ธ์ ์ข ๋ฅ์ ๋ํด ๋ช ํํ ์๊ณ ์ฌ์ฉํ๋๊ฒ ์ข์ ๊ฒ ๊ฐ์ ์ ๋ฆฌํด๋ณด๋ ค ํ๋ค.
- Dummy
- ๋์ํ์ง ์์๋ ํ ์คํธ์๋ ์ํฅ์ ๋ฏธ์น์ง ์๋ ๊ฐ์ฒด๋ฅผ Dummy ๊ฐ์ฒด๋ผ๊ณ ํ๋ค.
- ๋จ์ ์ธ์คํด์คํํ ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ค.
- Stub
- ํ ์คํธ์์ ํธ์ถ๋ ์์ฒญ์ ๋ํด ๋ฏธ๋ฆฌ ์ค๋นํด๋ ๊ฒฐ๊ณผ๋ฅผ ์ ๊ณตํ๋ค.
- ์ฆ, ํ ์คํธ๋ฅผ ์ํด ๋ฏธ๋ฆฌ ๋ง๋ค์ด๋์ ๊ฐ์ฒด๋ง์ ๋ฐํํ๋ค. (๊ฐ์ฒด์ ์ํ๋ฅผ ๊ฒ์ฆํ ๋ ์ฃผ๋ก ์ฌ์ฉํ๋ค.)
- Mock
- ํธ์ถ์ ๋ํ ๊ธฐ๋๋ฅผ ๋ช ์ธํ๊ณ ๋ด์ฉ์ ๋ฐ๋ผ ๋์ํ๋๋ก ํ๋ก๊ทธ๋๋ฐ ๋ ๊ฐ์ฒด์ด๋ค.
- ์ค์ ๋ก ํจ์๊ฐ ์ ํธ์ถ๋์๋์ง ๊ฒ์ฆํ๋๋ฐ ๋ ๋ชฉ์ ์ด ์๊ณ (ํ๋ ๊ฒ์ฆ) ํ ์คํธ ์๋ ๊ฐ์ ๋ฐ ๊ฒ์ฆํ๊ณ ์ถ์ ํ ์คํธ์ ์ง์คํ๊ณ ์ถ์ ๋ ๊ฒ์ฆํ๊ณ ์ ํ๋ ๊ฒ์ ์ ์ธํ ๋ค๋ฅธ ๊ฐ์ฒด๋ค์ ๋ชจํนํ์ฌ ์ฌ์ฉํ๋ค.
- Fake
- ๋ณต์กํ ๋ก์ง์ ๊ฐ์ง ํจ์์ ๋์์ ๋จ์ํํ์ฌ ๊ตฌํํ ๊ฐ์ฒด์ด๋ค.
- ์ฆ, ๋์์ ํ์ง๋ง ์ค์ ์ฌ์ฉ๋๋ ๊ฐ์ฒด์ฒ๋ผ ์ ๊ตํ๊ฒ ๋์ํ์ง๋ ์๋ ๊ฐ์ฒด๋ฅผ ๋งํ๋ค.
- ์๋ฅผ ๋ค๋ฉด, InMemoryRepository์ ๊ฐ์ด ํ ์คํธ๋ฅผ ์ํด ๊ฐ์ง ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ง๋๋ ๊ฒ๊ณผ ๊ฐ์ ์์๊ฐ ์๋ค. ์ ๊ตํ์ง๋ ์์ง๋ง ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋์ผํ ์ญํ ์ ํ๋ค.
์ฐธ๊ณ
https://tecoble.techcourse.co.kr/post/2020-09-19-what-is-test-double/
Lazy Property ์ฌ์ฉ
๋ถ๋ณ ๊ฐ์ฒด๋ผ๋ฉด ์ ๊ทผํ ๋๋ง๋ค ๋ก์ง์ ์คํํ์ง ์๊ณ ์ฒ์ ์ ๊ทผํ์ ๋ ํ๋ฒ๋ง ์คํํ๊ณ ์ด๊ธฐํํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์๋ค.
์ด๋ ๊ฒ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ค๋ณต๋๋ ๊ณ์ฐ์ ํผํด ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ์ ํ ์ ์๋ค.
val lazyValue: String by lazy {
println("computed!") // ์ฒ์ ์ ๊ทผํ ๋ ๋ฑ ํ๋ฒ๋ง ์คํ
"Hello"
}
// println(lazyValue)
// println(lazyValue)
// -- ์ถ๋ ฅ --
computed!
Hello
Hello
์ฐธ๊ณ
https://kotlinlang.org/docs/delegated-properties.html#lazy-properties
๋น๋์ ์กฐ์ ์
๋ฉ์๋ ๋ค์ด๋ฐ์ ๋ํ ๋ฆฌ๋ทฐ๋ฅผ ๋ฐ์๋ค. ์ฌ์ค ๋ฉ์๋๋ช ์ ์ต๋ํ ๊ฐ๋ ์ฑ์๊ฒ ์์ฑํ๋ ค๊ณ ๋ ธ๋ ฅํ์ง๋ง ๋ฐํ ํ์ ์ ๋ํด์๋ ์ ์คํ๊ฒ ์๊ฐํ์ง ์์๋ ๊ฒ ๊ฐ๋ค.
์๋ ๊ฐํธ ์ค๋ธ์ ํธ ์ฑ ๋ด์ฉ ์ค ์ข์ ๋ฉ์๋ ๋ค์ด๋ฐ์ ํ๋ ๋ฐฉ๋ฒ์ด ์ ์๋์ด ์๋ค.
๋น๋์ ์กฐ์ ์ ์ ๋ํ ๋ด์ฉ์ด์๋๋ฐ
- ๋น๋
- ๋น๋๋ ๋ญ๊ฐ๋ฅผ ๋ง๋ค๊ณ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ๋งํ๋ค. ๋ฐํ ํ์ ์ ์ ๋ void๊ฐ ๋ ์ ์์ผ๋ฉฐ ๋ช ์ฌ, ํ์ฉ์ฌ๋ก ํํํ๋ค.
fun pow(base: Int, power: Int): Int
fun employee(id: Int): Employee
fun parsedCell(x: Int, y: Int): String
fun bytedSaved(content: String): Int
- ์กฐ์ ์
- ์กฐ์ ์๋ ๊ฐ์ฒด๋ก ์ถ์ํํ ์ํฐํฐ๋ฅผ ์์ ํ๋ ๋ฉ์๋๋ฅผ ๋งํ๋ค. ๋ฐํ ํ์ ์ ํญ์ void์ด๋ฉฐ ์ด๋ฆ์ ํญ์ ๋์ฌ์ด๋ค.
- ์กฐ์ ์์ ๊ฒฝ์ฐ ์๋ฏธ๋ฅผ ์ข ๋ ํ๋ถํ๊ฒ ์ค๋ช ํ๊ธฐ ์ํด์ ๋ถ์ฌ ํ์ฉ์ด ๊ฐ๋ฅํ๋ค.
fun save(content: String)
fun put(key: String, value: Float)
fun remote(emp: Employee)
fun quicklyPrint(id: Int)
- ๊ฐ์ฒด์งํฅ์ ์ธ ์ ๊ทผ๋ฒ์ผ๋ก ๋ฉ์๋๋ช
์ ์ ์ง์ผ๋ ค๋ฉด ์ด๋ค ๊ฒ์ ๋ฐํํ๋ ๋ฉ์๋ ์ด๋ฆ์ ๋์ฌ๋ก ์ง๊ธฐ ๋ณด๋ค๋ ๋ช
์ฌ๋ก ์ง๊ณ (๋น๋) ๋ฌด์ธ๊ฐ๋ฅผ ๋ณ๊ฒฝํ ๋์๋ ๋์ฌ(์กฐ์ ์)๋ฅผ ์ฌ์ฉํ์
- ๋ฉ์๋ ๋ช
์ ์๋ช
ํ๊ธฐ ์ด๋ ต๋ค๋ฉด ๊ทธ ๋ฉ์๋์์ ๋ชฉํํ๋ ์์
์ด ํ๋๊ฐ ์๋ ๊ฐ๋ฅ์ฑ์ด ๋๋ค.
- Boolean ๊ฐ์ ๋ฐํํ๋ ๋น๋๋ ์์ธ. ์ด ๊ฒฝ์ฐ์ ํ์ฉ์ฌ
์ฐธ๊ณ
https://lovethefeel.tistory.com/163?category=1002227
https://jessyt.tistory.com/141
Functional Interface
์ถ์ ๋ฉ์๋๊ฐ ํ๋๋ง ์๋ ์ธํฐํ์ด์ค์ ๋ํด functional interface ๋ฅผ ์ ์ฉํ ์ ์๋ค.
fun interface CardGenerator {
fun generate(): Card
}
val randomCardGenerator = CardGenerator {
Card(Rank.random(), Suit.random())
}
์์ ๊ฐ์ด functional interface ๋ฅผ ์ ์ฉํ๋ฉด ๊ฐ๊ฒฐํ ํจ์ํ ์ฝ๋ ์์ฑ์ด ๊ฐ๋ฅํด์ง๋ฉฐ ์งง์ ๋๋ค ํํ์์ผ๋ก ๋ถํ์ํ ์ฝ๋๋ฅผ ์ค์ผ ์ ์๋ค.
์ฐธ๊ณ
• https://kotlinlang.org/docs/fun-interfaces.html
Step3
https://github.com/next-step/kotlin-blackjack/pull/554
์ผ๊ธ ์ปฌ๋ ์ ๊ณผ ๋ถ๋ณ ๊ฐ์ฒด
์ผ๊ธ ์ปฌ๋ ์ ์ ๋ง๋ค์๋ค๊ณ ํด์ ๋ฐ๋์ ๋ด๋ถ๊ฐ ๋ถ๋ณ ๊ฐ์ฒด์ผ ํ์๋ ์๋ค. ํ์ง๋ง ํ๋์ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ๋ถ๋ณ๊ฐ์ฒด๋ก ๋ง๋ค์์ ๋์ ์ฅ์ ์ด ๋๋ ทํด ์๋์ ๊ฐ์ด ๋ถ๋ณ ๊ฐ์ฒด๋ก ํจ๊ป ๊ฐ์ ธ๊ฐ๋ ๊ฒ์ด ์ข๋ค.
data class Cards(
val values: List<Card> = emptyList()
) {
constructor(vararg card: Card) : this(values = card.toList())
val sumOfScoreWithAceAsOne: Int by lazy {
values.sumOf { it.getScore() }
}
val numberOfAce: Int by lazy {
values.count { it.rank == Rank.ACE }
}
}
๋ฆฌ๋ทฐ์ด๋์ ๋ถ๋ณ๊ฐ์ฒด๋ก ๋ง๋๋ ๊ฒ ์์ฒด๋ ์ข์ ์๋์ด์ง๋ง ํ์ค ์ธ๊ณ์ ๊ด์ ์์ ๋ณด์์ ๋ ํ๋ ์ด์ด๋ ๋๋ฌ๊ฐ ๋ค๊ณ ์๋ ์นด๋ ๋๋ฏธ ๋ํ ๋ณํ ์ ์์ด ๋ฌด๋ฆฌํ๊ฒ ๋ถ๋ณ์ผ๋ก ๋ง๋ค ํ์๋ ์์ด๋ณด์ธ๋ค๋ ์๊ฒฌ์ ๋ง์ํด์ฃผ์ จ๋ค.
ํ์ค์์ ํ๋ ์ด์ด๋ ๋๋ฌ๊ฐ ๋ค๊ณ ์๋ ์นด๋ ๋๋ฏธ๊ฐ ๋ณํ ์ ์๋ ์๊ตฌ์ฌํญ์ด๊ธฐ ๋๋ฌธ์ ๋ฌด๋ฆฌํ๊ฒ ๋ถ๋ณ์ผ๋ก ๋ง๋ค์ง๋ ์์๋ ๋ ๊ฒ ๊ฐ๋ค๋ ์๊ฒฌ์ ๊ณต๊ฐํ๊ณ ๋ถ๋ณ๊ฐ์ฒด๋ฅผ ์ฐ์ ์ ์ผ๋ก ์๊ฐํ๋, ์ ์ฐํ๊ฒ ๊ฐ๋ณ๊ฐ์ฒด์ ๊ด์ ์์ ์๊ฐํด๋ณด๋ ๊ฒ๋ ์ข์ ๊ฒ ๊ฐ๋ค.
Step4
https://github.com/next-step/kotlin-blackjack/pull/568
์ปฌ๋ ์ ์ ๋ณ๊ฒฝ์ง์
class Cards(
values: List<Card> = emptyList(),
) {
var values: List<Card> = values
private set
constructor(vararg card: Card) : this(values = card.toMutableList())
val sumOfScoreWithAceAsOne: Int
get() = values.sumOf { it.getScore() }
val numberOfAce: Int
get() = values.count { it.rank == Rank.ACE }
fun add(card: Card) {
values = values + card
}
fun addAll(cards: List<Card>) {
values = values + cards
}
}
Cards ํด๋์ค๋ฅผ ๊ฐ๋ณํ๊ฒ ๋ณ๊ฒฝํ๋ฉด์ mutableList ๋ฅผ ๋ง๋ค๊ณ ๋ฐฉ์ด์ ๋ณต์ฌ๋ก ๋ฐํํ ์ง, ๋๋ var (private set) ๋ก ํ๋กํผํฐ ์์ฒด๋ฅผ ๋ณ๊ฒฝ ์ง์ ์ผ๋ก ๋๊ณ add๋ฅผ ํ ๋๋ง๋ค ์๋ก์ด ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค์ง ๊ณ ๋ฏผ์ ํ๋ค.
๋ฆฌ๋ทฐ์ด๋๋ ์ด ๋ถ๋ถ์ ๋ํด ๋ฆฌ๋ทฐ๋ฅผ ํด์ฃผ์ จ๊ณ values๋ MutableList๋ก ๋๊ณ , ์ธ๋ถ์ List๋ฅผ ๋ฐํํ๋ getter๋ฅผ ๋ ธ์ถ์ํจ ํ์ ์ ๊ทผํ ๋ values๋ฅผ ๋ณต์ (copy)ํ List๋ฅผ ๋ง๋ค์ด์ ๋ฐํํด๋ ์ข์ ๊ฒ ๊ฐ๋ค๋ ์๊ฒฌ์ ์ฃผ์ จ๋ค.
var ๋ฅผ ํตํด ํ๋กํผํฐ ์์ฒด๋ฅผ ๋ณ๊ฒฝ ์ง์ ์ผ๋ก ๋์์ ๋๊ฐ mutableList ๋ก ๋ฆฌ์คํธ ๋ด๋ถ์ ๋ณ๊ฒฝ์ง์ ์ ๋๋ ๊ฒ๋ณด๋ค ๋ฉํฐ ์ค๋ ๋ ํ๊ฒฝ์์ ์์ ์ฑ์ด ํฌ๊ธฐ ๋๋ฌธ์ ํ๋กํผํฐ ์์ฒด๋ฅผ ๋ณ๊ฒฝ ์ง์ ์ผ๋ก ๋๋ ๋ฐฉ์์ ์ ํํ๋ค.
๋ค๋ง ํ์ฌ ๋ฏธ์ ์์ ์ค๋ ๋ ์์ ์ฑ์ ๊ณ ๋ คํด์ผํ ์ํฉ์ ์๋๊ธฐ ๋๋ฌธ์ ์๋๊ฐ ๋ ๋น ๋ฅธ mutableList๋ฅผ ์ฌ์ฉํ๊ณ ๋ฐฉ์ด์ ๋ณต์ฌ๋ก ๋ฆฌํดํ๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ธ ๊ฒ ๊ฐ๋ค.
'BACKEND' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๊ณ์ธตํ ์ํคํ ์ฒ(Layered Architecture) ์(?) ์ฌ์ฉํ๊ธฐ (2) | 2024.11.30 |
---|---|
๋ถ์ฐํ๊ฒฝ์ RabbitMQ ์ ์ฉํ๊ธฐ (0) | 2024.01.05 |
TDD, ํด๋ฆฐ ์ฝ๋ with Kotlin 6๊ธฐ ๋ก๋ ํผ๋๋ฐฑ (0) | 2023.07.24 |
TDD, ํด๋ฆฐ ์ฝ๋ with Kotlin 6๊ธฐ ์๋์ฐจ ๊ฒฝ์ฃผ ํผ๋๋ฐฑ (0) | 2023.07.24 |
๋ ์ด์ ์ค์ํ์ง ์๊ธฐ ์ํด ์ ์ด๋ณด๋ ๋ฆฌํฉํฐ๋ง ๋ฐฉ๋ฒ (0) | 2023.07.09 |