Skip to content
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

[step5] 자동차 경주(리팩토링) #1556

Open
wants to merge 2 commits into
base: mkkim90
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions src/main/kotlin/racingcar/controller/RacingController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@ package racingcar.controller

import racingcar.domain.Cars
import racingcar.domain.WinnerCar
import racingcar.dto.CarsDto
import racingcar.service.RacingService
import racingcar.view.OutputView
import racingcar.view.OutputView.printWinners
import racingcar.view.inputCarName

class RacingController(
private val racingService: RacingService = RacingService()
) {
fun play(): Cars {
return racingService.play(join())
fun play(): CarsDto {
val snapshots = racingService.play(join())
OutputView.printRacing(snapshots)
return snapshots.last()
}

private fun join(): Cars = Cars.of(inputCarName().split(RACING_CAR_DELIMITER))
private fun join(): Cars = Cars.of(inputCarName())

fun win(playRacingCar: Cars) {
fun win(playRacingCar: CarsDto) {
printWinners(WinnerCar.from(playRacingCar))
}

companion object {
private const val RACING_CAR_DELIMITER = ","
}
}
13 changes: 8 additions & 5 deletions src/main/kotlin/racingcar/domain/Car.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package racingcar.domain

import racingcar.dto.CarDto

class Car(val name: String) {
var position: Int = DEFAULT_POSITION
private set
Expand Down Expand Up @@ -33,16 +35,17 @@ class Cars(cars: List<Car>) {
}
}

fun maxOfPositions(): Int {
return cars.maxOf { car -> car.position }
}

companion object {
fun of(names: List<String>): Cars {
private const val RACING_CAR_DELIMITER = ","

fun of(inputName: String): Cars {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

보통 정적 팩토리 함수에서 매개변수를 하나만 받는 경우에는 from이나 valueOf등을 사용하는걸 관례로 하고 있습니다.
참고: https://kyucumber.github.io/posts/book/effective-kotlin/effective-kotlin-item-33

val names = inputName.split(RACING_CAR_DELIMITER)
val cars = names.map {
Car.from(it)
}
return Cars(cars)
}
}

fun toCarDtoList(): List<CarDto> = cars.map { CarDto.from(it) }
}
8 changes: 5 additions & 3 deletions src/main/kotlin/racingcar/domain/WinnerCar.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package racingcar.domain

import racingcar.dto.CarDto
import racingcar.dto.CarsDto

object WinnerCar {
fun from(racingCars: Cars): List<Car> {
return racingCars.cars
.filter { it.position == racingCars.maxOfPositions() }
fun from(racingCars: CarsDto): List<CarDto> {
return racingCars.contentsFilter { it -> it.position == racingCars.maxOfPositions() }
}
}
34 changes: 34 additions & 0 deletions src/main/kotlin/racingcar/dto/CarDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package racingcar.dto

import racingcar.domain.Car

data class CarDto(val name: String, val position: Int) {
companion object {
fun from(car: Car): CarDto {
return CarDto(
name = car.name,
position = car.position
)
}
}
}

data class CarsDto(val carsDto: List<CarDto>) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DTO의 의미는 data transfer object입니다. 즉 데이터 전송용 바스켓 같은 목적으로 사용되죠.
그런데 이 dto에는 출력과, 최대 거리 찾기 등 비즈니스 로직들이 있는 것 같아요 🤔

fun racingTrace() = buildString {
carsDto.forEach {
appendLine("${it.name} : ${RACING_COURSE.repeat(maxOf(0, it.position))}")
}
}

fun contentsFilter(predicate: (CarDto) -> Boolean): List<CarDto> {
return carsDto.filter(predicate)
}

fun maxOfPositions(): Int {
return carsDto.maxOf { car -> car.position }
}

companion object {
private const val RACING_COURSE = "-"
}
}
9 changes: 5 additions & 4 deletions src/main/kotlin/racingcar/service/RacingService.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package racingcar.service

import racingcar.domain.Cars
import racingcar.view.OutputView
import racingcar.dto.CarsDto
import racingcar.view.inputTryCount

class RacingService {
fun play(racingCars: Cars): Cars {
fun play(racingCars: Cars): List<CarsDto> {
val snapshots = mutableListOf<CarsDto>()
repeat(inputTryCount()) {
racingCars.move()
OutputView.printRacing(racingCars)
snapshots.add(CarsDto(racingCars.toCarDtoList()))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서비스에서 dto를 반환해도 되는가? 다른 서비스에서 같은 로직을 수행하는데 dto가 아닌 domain을 받고 싶다면 어떻게 하지? 이런 고민을 해보면 좋은 경험이 될 것 같아요 ㅎㅎ (정답이 있거나 이게 틀렸다는 피드백이 아닙니다 ㅎㅎ)

}
return racingCars
return snapshots
}
}
14 changes: 6 additions & 8 deletions src/main/kotlin/racingcar/view/OutputView.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
package racingcar.view

import racingcar.domain.Car
import racingcar.domain.Cars
import racingcar.dto.CarDto
import racingcar.dto.CarsDto

object OutputView {

private const val WINNER_JOIN_SEPARATOR = ","
private const val RACING_COURSE = "-"
fun printRacing(racingCars: Cars) {
fun printRacing(snapShots: List<CarsDto>) {
val result = buildString {
racingCars.cars.forEach {
appendLine("${it.name} : ${RACING_COURSE.repeat(maxOf(0, it.position))}")
snapShots.forEach {
appendLine(it.racingTrace())
}
appendLine()
}
println(result)
}

fun printWinners(winnerCars: List<Car>): String = buildString {
fun printWinners(winnerCars: List<CarDto>): String = buildString {
val winnersCarNames = winnerCars
.joinToString(WINNER_JOIN_SEPARATOR) { it.name }

Expand Down
15 changes: 15 additions & 0 deletions src/test/kotlin/racingcar/CarsTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package racingcar

import io.kotest.matchers.shouldBe
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import racingcar.domain.Cars

class CarsTest {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트가 성공하지 않고 있네요. ㅠ

@ValueSource(strings = ["test,123,ㅅㄷㅈ", "민균,한솔,재성"])
@ParameterizedTest
fun `각 자동차 이름을 구분자(,)로 구분한다`(param: String) {
val cars = Cars.of(param)
cars.cars shouldBe param.split(",")
}
}