Skip to content

Commit 2148c01

Browse files
refactor : 로또 도메인 리팩토링 진행 (#22)
* refactor : LottoTicket 내부에서만 LottoGame 접근 할 수 있도록 수정 * refactor : LottoGame 인스턴스로 수동인지 자동인지 확인 가능하도록 수정 * test : LottoTicket 테스트 코드 작성
1 parent 88ffaed commit 2148c01

File tree

10 files changed

+92
-105
lines changed

10 files changed

+92
-105
lines changed

src/main/kotlin/controller/LottoApp.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package controller
22

33
import model.lotto.LottoCount
4-
import model.lotto.LottoGameGenerator
54
import model.lotto.LottoNumber
65
import model.lotto.LottoNumbers
76
import model.lotto.LottoTickets
@@ -50,12 +49,10 @@ class LottoApp(private val inputView: InputView, private val outputView: OutputV
5049
return LottoCount.of(manualCount, money)
5150
}
5251

53-
// FIXME: 테스트 용이성이나 객체지향 관점에서 Ticket 은 LottoTicket 이 직접 생성해줘야하지 않을까요?
5452
private fun generateLottoTicket(lottoCount: LottoCount): LottoTickets {
5553
val manualNumbers = requestManualLottoNumbers(lottoCount.manualCount)
56-
val manualGames = LottoGameGenerator.generate(manualNumbers)
57-
val autoGames = LottoGameGenerator.generate(lottoCount.autoCount)
58-
return LottoTickets.createWithGames(manualGames + autoGames)
54+
val autoNumbers = requestAutoLottoNumbers(lottoCount.autoCount)
55+
return LottoTickets.of(manualNumbers, autoNumbers)
5956
}
6057

6158
private fun requestManualLottoNumbers(manualCount: Int): List<LottoNumbers> {
@@ -64,4 +61,15 @@ class LottoApp(private val inputView: InputView, private val outputView: OutputV
6461
LottoNumbers.from(inputView.requestLottoNumber())
6562
}
6663
}
64+
65+
private fun requestAutoLottoNumbers(autoCount: Int): List<LottoNumbers> {
66+
val allPossibleNumbers = (1..45).toList()
67+
return List(autoCount) {
68+
val selectedNumbers = allPossibleNumbers
69+
.shuffled()
70+
.take(6)
71+
.sorted()
72+
LottoNumbers.from(selectedNumbers)
73+
}
74+
}
6775
}
Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,10 @@
11
package model.lotto
22

3-
enum class TicketType {
4-
Manual,
5-
Auto,
6-
}
7-
8-
data class LottoGame(
9-
val numbers: LottoNumbers,
10-
val type: TicketType,
11-
) {
12-
companion object {
13-
fun of(
14-
numbers: LottoNumbers,
15-
type: TicketType,
16-
): LottoGame {
17-
return LottoGame(numbers, type)
18-
}
19-
}
3+
sealed class LottoGame(val numbers: LottoNumbers) {
4+
class Manual(manualNumbers: LottoNumbers) : LottoGame(manualNumbers)
5+
class Auto(autoNumbers: LottoNumbers) : LottoGame(autoNumbers)
206

217
override fun toString(): String {
228
return numbers.toString()
239
}
2410
}
25-
26-
object LottoGameGenerator {
27-
fun generate(count: Int): List<LottoGame> {
28-
val allPossibleNumbers = (1..45).toList()
29-
return List(count) {
30-
val selectedNumbers = allPossibleNumbers.shuffled().take(6).sorted()
31-
val lottoNumbers = LottoNumbers.from(selectedNumbers)
32-
LottoGame.of(lottoNumbers, TicketType.Auto)
33-
}
34-
}
35-
36-
fun generate(manualNumbers: List<LottoNumbers>): List<LottoGame> {
37-
return manualNumbers.map { lottoNumbers ->
38-
LottoGame.of(lottoNumbers, TicketType.Manual)
39-
}
40-
}
41-
}

src/main/kotlin/model/lotto/LottoTicket.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package model.lotto
22

3+
internal const val REQUIRED_LEAST_ONE_GAME = "최소 한 게임 이상 포함되어야 합니다."
4+
internal const val REQUIRED_MAXIMUM_FIVE_GAME = "최대 다섯 게임만 포함될 수 있습니다."
5+
36
class LottoTicket(val games: List<LottoGame>) {
4-
companion object {
5-
fun of(games: List<LottoGame>): LottoTicket {
6-
return LottoTicket(games)
7-
}
7+
init {
8+
require(games.isNotEmpty()) { REQUIRED_LEAST_ONE_GAME }
9+
require(games.size < 6) { REQUIRED_MAXIMUM_FIVE_GAME }
810
}
911

1012
override fun toString(): String {

src/main/kotlin/model/lotto/LottoTickets.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ class LottoTickets(
55
val elements: List<LottoTicket>,
66
) {
77
companion object {
8-
fun of(elements: List<LottoTicket>): LottoTickets {
9-
return LottoTickets(elements)
10-
}
11-
12-
fun createWithGames(elements: List<LottoGame>): LottoTickets {
13-
val tickets = elements.chunked(5).map { LottoTicket.of(it) }
8+
fun of(manualNumbers: List<LottoNumbers>, autoNumbers: List<LottoNumbers>): LottoTickets {
9+
val manualGames = manualNumbers.map { LottoGame.Manual(it) }.toList()
10+
val autoGames = autoNumbers.map { LottoGame.Auto(it) }.toList()
11+
val tickets = (manualGames + autoGames).chunked(5).map { LottoTicket(it) }
1412
return LottoTickets(tickets)
1513
}
1614
}

src/main/kotlin/view/OutputView.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package view
22

33
import model.lotto.LottoGame
44
import model.lotto.LottoTickets
5-
import model.lotto.TicketType
65

76
internal const val INPUT_MONEY_MESSAGE = "구입금액을 입력해 주세요."
87
internal const val INPUT_MANUAL_INPUT_MESSAGE = "수동으로 구매할 로또 게임 수를 입력해 주세요."
@@ -33,8 +32,8 @@ class OutputView {
3332
}
3433

3534
private fun printLottoGames(lottoGames: List<LottoGame>) {
36-
val manualGames = lottoGames.filter { it.type == TicketType.Manual }
37-
val autoGames = lottoGames.filter { it.type == TicketType.Auto }
35+
val manualGames = lottoGames.filterIsInstance<LottoGame.Manual>()
36+
val autoGames = lottoGames.filterIsInstance<LottoGame.Auto>()
3837
println("수동으로 ${manualGames.size}게임, 자동으로 ${autoGames.size}게임을 구매하셨습니다.")
3938
if (manualGames.isNotEmpty()) {
4039
println("수동으로 구매한 로또 번호")
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package model
2+
3+
import model.lotto.LottoGame
4+
import model.lotto.LottoNumbers
5+
6+
fun generateFixtureLottoGames(count: Int): List<LottoGame> {
7+
if (count == 0) {
8+
return emptyList()
9+
}
10+
11+
return List(count) {
12+
val selectedNumbers = (1..45).toList()
13+
.shuffled()
14+
.take(6)
15+
.sorted()
16+
LottoGame.Auto(LottoNumbers.from(selectedNumbers))
17+
}
18+
}

src/test/kotlin/model/lotto/LottoGameGeneratorTest.kt

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/test/kotlin/model/lotto/LottoGameTest.kt

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,18 @@ import io.kotest.matchers.shouldBe
55

66
class LottoGameTest : FreeSpec(
77
{
8-
"LottoGame 생성" - {
9-
"주어진 LottoNumbers 와 TicketType 을 가진 LottoGame 을 반환" {
10-
val numbers = LottoNumbers.from(listOf(1, 2, 3, 4, 5, 6))
11-
val ticketType = TicketType.Manual
12-
val ticket = LottoGame.of(numbers, ticketType)
8+
"ManualLotto 생성" {
9+
val numbers = LottoNumbers.from(listOf(1, 2, 3, 4, 5, 6))
10+
val ticket = LottoGame.Manual(numbers)
1311

14-
ticket.numbers shouldBe numbers
15-
ticket.type shouldBe ticketType
16-
}
12+
ticket.numbers shouldBe numbers
1713
}
1814

19-
"LottoGame 출력" - {
20-
"LottoGame 의 numbers 필드를 문자열화 하여 반환" {
21-
val numbers = LottoNumbers.from(listOf(1, 2, 3, 4, 5, 6))
22-
val ticket = LottoGame.of(numbers, TicketType.Manual)
15+
"AutoLotto 출력" {
16+
val numbers = LottoNumbers.from(listOf(1, 2, 3, 4, 5, 6))
17+
val ticket = LottoGame.Auto(numbers)
2318

24-
ticket.toString() shouldBe numbers.toString()
25-
}
19+
ticket.toString() shouldBe numbers.toString()
2620
}
2721
},
2822
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package model.lotto
2+
3+
import io.kotest.assertions.throwables.shouldThrowExactly
4+
import io.kotest.core.spec.style.FreeSpec
5+
import io.kotest.matchers.shouldBe
6+
import model.generateFixtureLottoGames
7+
8+
class LottoTicketTest : FreeSpec(
9+
{
10+
"LottoTicket을 생성할 때" - {
11+
"1개의 로또 게임이 포함 될 수 있다." - {
12+
val count = 1
13+
val ticket = LottoTicket(generateFixtureLottoGames(count))
14+
ticket.games.size shouldBe count
15+
}
16+
17+
"5개의 로또 게임이 포함 될 수 있다." - {
18+
val count = 5
19+
val ticket = LottoTicket(generateFixtureLottoGames(count))
20+
ticket.games.size shouldBe count
21+
}
22+
23+
"로또 게임이 없으면 안된다." - {
24+
val games = generateFixtureLottoGames(0)
25+
println(games)
26+
shouldThrowExactly<IllegalArgumentException> {
27+
LottoTicket(emptyList())
28+
}.message shouldBe REQUIRED_LEAST_ONE_GAME
29+
}
30+
31+
"로또 게임이 6개 이상 포함되면 안된다." - {
32+
shouldThrowExactly<IllegalArgumentException> {
33+
LottoTicket(generateFixtureLottoGames(6))
34+
}.message shouldBe REQUIRED_MAXIMUM_FIVE_GAME
35+
}
36+
}
37+
},
38+
)

src/test/kotlin/model/lotto/LottoTicketsTest.kt

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)