-
Notifications
You must be signed in to change notification settings - Fork 410
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Step4 자동차 경주 리팩토링 #948
base: youngsuk-kim
Are you sure you want to change the base?
Step4 자동차 경주 리팩토링 #948
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
경주할 자동차 이름을 추출 하는 기능. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
경주할 자동차 대수를 추출 하는 기능. | ||
|
||
경주 자동차 이름 별로 "-" 가 나오도록 구현. | ||
|
||
어떤 자동차가 최종 우승 하였는지 알아내는 기능 | ||
|
||
모든 로직에 단위 테스트를 구현한다. | ||
|
||
단, UI(System.out, System.in) 로직은 제외 | ||
핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다. | ||
|
||
UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다. | ||
|
||
indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. | ||
|
||
예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. | ||
|
||
힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다. | ||
|
||
함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다. | ||
|
||
함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다. | ||
|
||
기능을 구현하기 전에 README.md 파일에 구현할 기능 목록을 정리해 추가한다. | ||
|
||
git의 commit 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위로 추가한다. | ||
|
||
사용자가 입력한 이름의 숫자 만큼 자동차 대수를 생성한다. | ||
|
||
자동차는 자동차 이름과 위치 정보를 가지는 Car 객체를 추가해 구현한다. | ||
|
||
각 자동차에 이름을 부여할 수 있다. 자동차 이름은 5자를 초과할 수 없다. | ||
|
||
전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. | ||
|
||
자동차 이름은 쉼표(,)를 기준으로 구분한다. | ||
|
||
자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package src.racingcar.domain | ||
|
||
class Car( | ||
private val name: String, | ||
private var moveCount: Int = 0 | ||
) { | ||
|
||
fun move(carMoveNumber: Int): Int { | ||
if (CAR_MOVE_CONDITION_NUMBER <= carMoveNumber) moveCount++ | ||
|
||
return moveCount | ||
} | ||
|
||
fun getMoveCount(): Int { | ||
return moveCount | ||
} | ||
|
||
fun getCarName(): String { | ||
return name | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코틀린의 프로퍼티는 접근자를 모두 지원하고 있어요. name에 대한 접근 제어자를 public으로 변경하면 되죠. 하지만 moveCount인 경우에는 set도 같이 쓸 수가 있기 때문에 다른 처리가 필요할거에요. 이 부분에 대해서는 한번 찾아보시겠어요~? |
||
|
||
companion object { | ||
private const val CAR_MOVE_CONDITION_NUMBER = 4 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package src.racingcar.domain | ||
|
||
import src.racingcar.parseComma | ||
|
||
class CarService( | ||
private val carMoveRandomValue: Int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CarService는 자동차에 움직임에 대해서 랜덤인지 아닌지 알 수 없다고 생각합니다. carMobeRandomValue 보다는 자동차의 움직임에 대한 carMoveValue가 좋지 않을까요? 🤔 |
||
) { | ||
|
||
fun execute(carNames: String): MutableList<Car> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MutableList는 가변리스트에요. 가변 리스트인 경우에는 어떤 단점이 있을까요? |
||
val race = Race().create(parseComma(carNames)) | ||
return race.start(carMoveRandomValue) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package src.racingcar.domain | ||
|
||
class Race( | ||
private var cars: MutableList<Car> = mutableListOf() | ||
) { | ||
|
||
fun create(carNames: List<String>): Race { | ||
for (carName in carNames) { | ||
cars.add(Car(carName)) | ||
} | ||
|
||
return this | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
fun start(carMoveRandomValue: Int): MutableList<Car> { | ||
for (car in cars) { | ||
car.move(carMoveRandomValue) | ||
} | ||
return cars | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,9 @@ | ||||||||
package src.racingcar.domain | ||||||||
|
||||||||
class Winner( | ||||||||
private val racingCars: List<Car> | ||||||||
) { | ||||||||
fun findWinners(): List<Car> { | ||||||||
return racingCars.filter { car -> car.getMoveCount() >= racingCars.maxOf { it.getMoveCount() } } | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
maxOf 사용 좋습니다 👍 |
||||||||
} | ||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package src.racingcar | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 패키지 구조가 맞지 않네요. |
||
|
||
fun parseComma(input: String): List<String> { | ||
return input.split(",") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package src.racingcar.view | ||
|
||
object InputView { | ||
fun executeInputScreen(): RacingCarGameInput { | ||
println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).") | ||
val carNames: String = readln() | ||
println("시도할 횟수는 몇 회인가요?") | ||
val tryCount = readln().toInt() | ||
|
||
return RacingCarGameInput(carNames, tryCount) | ||
} | ||
} | ||
|
||
data class RacingCarGameInput( | ||
val carNames: String, | ||
val tryCount: Int | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package src.racingcar.view | ||
|
||
import src.racingcar.domain.Car | ||
import src.racingcar.domain.Winner | ||
|
||
object ResultView { | ||
fun printRacingCarGameResult(tryCount: Int, raceCars: MutableList<Car>) { | ||
repeat(tryCount) { | ||
printRacing(raceCars) | ||
} | ||
|
||
printWinner(Winner(raceCars).findWinners()) | ||
} | ||
|
||
private fun printRacing(raceCars: MutableList<Car>) { | ||
for (raceCar in raceCars) { | ||
print(raceCar.getCarName()) | ||
print(" : ") | ||
println("-".repeat(raceCar.getMoveCount())) | ||
} | ||
println() | ||
} | ||
|
||
private fun printWinner(findWinners: List<Car>) { | ||
print(findWinners.joinToString { car -> car.getCarName() }) | ||
print("가 최종 우승 했습니다.") | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package src.racingcar | ||
|
||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.jupiter.api.Test | ||
import src.racingcar.domain.CarService | ||
|
||
class CarServiceTest { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 우승자에 대한 테스트 케이스는 없는걸까요? |
||
|
||
@Test | ||
fun `랜덤 값이 4 이상이면 자동차들이 움직인다`() { | ||
val carNames = "test1,test2,test3" | ||
val execute = CarService(4).execute(carNames) | ||
.map { it.getMoveCount() } | ||
|
||
assertThat(listOf(1, 1, 1)).hasSameElementsAs(execute) | ||
} | ||
|
||
@Test | ||
fun `랜덤 값이 4 미만이면 자동차들이 정지한다`() { | ||
val carNames = "test1,test2,test3" | ||
val execute = CarService(0).execute(carNames) | ||
.map { it.getMoveCount() } | ||
|
||
assertThat(listOf(0, 0, 0)).hasSameElementsAs(execute) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,26 @@ | ||
package src.racingcar | ||
|
||
import org.assertj.core.api.Assertions | ||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.jupiter.api.Test | ||
import src.racingcar.domain.Car | ||
|
||
class CarTest { | ||
|
||
@Test | ||
fun `자동차는 한번에 두번 이상 움직일 수 없다`() { | ||
val moveCount = Car().move() | ||
fun `랜덤 값이 4 이상이면 차가 움직인다`() { | ||
val moveCount = Car("testName").move(4) | ||
assertThat(moveCount).isEqualTo(1) | ||
} | ||
|
||
Assertions.assertThat(moveCount).isLessThan(2) | ||
@Test | ||
fun `랜덤 값이 4 미만이면 차가 움직이지 않는다`() { | ||
val moveCount = Car("testName").move(3) | ||
assertThat(moveCount).isEqualTo(0) | ||
} | ||
|
||
@Test | ||
fun `차의 이름을 지정할 수 있다`() { | ||
val car = Car("testName") | ||
assertThat(car.getCarName()).isEqualTo("testName") | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
처음에 있는 난수가 정해지면, 그 난수를 이용하여 끝까지 진행이 되는군요! 어떻게 해야 자동차들이 각자 움직일 수 있을까요?