-
Notifications
You must be signed in to change notification settings - Fork 116
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
[둘리] 2단계 자동차 경주 제출합니다. #68
Changes from 3 commits
3e97c71
cb95bad
89d4dd8
e37d339
affbefb
b6834c8
1b39386
e818230
18e68de
f282093
4e8ad55
90c2b1d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,16 +2,19 @@ package model | |
|
||
import util.Validator | ||
|
||
class Car(private val name: String, private var position: Int = 0) { | ||
class Car(private val _name: String, private var _position: Int = 0) { | ||
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. 코틀린에서 변수에 언더바(_)를 붙이는 것은, backing property를 사용할 때 붙여요. class Car(val name: String, position: Int) {
private var _position: Int = position
val position: Int get() = _position
} ref. https://kotlinlang.org/docs/coding-conventions.html#names-for-backing-properties |
||
|
||
val name: String | ||
get() = _name | ||
val position: Int | ||
get() = _position | ||
|
||
init { | ||
Validator().checkName(name) | ||
Validator().checkName(_name) | ||
} | ||
|
||
fun getInfo(): CarInfo = CarInfo(name, position) | ||
|
||
fun move(condition: Int) { | ||
if (condition >= MOVING_POINT) position++ | ||
if (condition >= MOVING_POINT) _position++ | ||
} | ||
|
||
companion object { | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,20 +2,15 @@ package model | |
|
||
import generator.RandomGenerator | ||
|
||
class Cars(private val cars: List<Car>) { | ||
constructor(input: String) : this(input.split(",").mapIndexed { _, name -> Car(name.trim()) }) | ||
class Cars(private val _cars: List<Car>) { | ||
val cars: List<Car> | ||
get() = _cars | ||
|
||
fun getCarInfos(): List<CarInfo> { | ||
val carInfos = mutableListOf<CarInfo>() | ||
repeat(cars.size) { | ||
carInfos.add(cars[it].getInfo()) | ||
} | ||
return carInfos | ||
} | ||
constructor(input: String) : this(input.split(",").mapIndexed { _, name -> Car(name.trim()) }) | ||
|
||
fun getCarInfo(index: Int): CarInfo = cars[index].getInfo() | ||
fun getCarSize(): Int = cars.size | ||
fun getCar(index: Int): Car = _cars[index] | ||
fun getCarSize(): Int = _cars.size | ||
fun move(index: Int) { | ||
cars[index].move(RandomGenerator().getRandomNumber()) | ||
_cars[index].move(RandomGenerator().getRandomNumber()) | ||
} | ||
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. move 함수를 잘 구현해주셨네요. 👍 |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,9 @@ package util | |
|
||
import model.Cars | ||
|
||
class CarsHelper { | ||
companion object { | ||
fun findWinners(cars: Cars): List<String> { | ||
val carInfos = cars.getCarInfos() | ||
val equalCars = carInfos.groupBy({ it.position }, { it.name }) | ||
return equalCars[equalCars.keys.max()]?.toList() ?: listOf() | ||
} | ||
object CarsHelper { | ||
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 findWinners(cars: Cars): List<String> { | ||
val equalCars = cars.cars.groupBy({ it.position }, { it.name }) | ||
return equalCars[equalCars.keys.max()]?.toList() ?: listOf() | ||
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. 방어적 복사 활용 👍 |
||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -1,5 +1,7 @@ | ||||
package util | ||||
|
||||
import view.OutputView | ||||
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
domain과 view에 둘 다 접근이 가능한 것은 Controller입니다. |
||||
|
||||
class Validator { | ||||
|
||||
fun checkNames(names: String?) { | ||||
|
@@ -18,34 +20,35 @@ class Validator { | |||
|
||||
fun checkTryNumber(name: String?) { | ||||
checkTryNumberNull(name) | ||||
checkTryNumberIsRight(name) | ||||
checkTryNumberIsRight(name ?: "") | ||||
} | ||||
|
||||
private fun checkNameNull(name: String?) { | ||||
require(name != null) { Constants.INPUT_NAME_NULL_ERROR_MESSAGE } | ||||
require(name != null) { OutputView().outputErrorMessage(Constants.INPUT_NAME_NULL_ERROR_MESSAGE) } | ||||
} | ||||
|
||||
private fun checkNameSize(name: String) { | ||||
require(name.length < 5) { Constants.INPUT_NAME_SIZE_ERROR_MESSAGE } | ||||
require(name.length < 5) { OutputView().outputErrorMessage(Constants.INPUT_NAME_SIZE_ERROR_MESSAGE) } | ||||
} | ||||
|
||||
private fun checkNameEmpty(name: String) { | ||||
require(name != "") { Constants.INPUT_NAME_NULL_ERROR_MESSAGE } | ||||
require(name != "") { OutputView().outputErrorMessage(Constants.INPUT_NAME_NULL_ERROR_MESSAGE) } | ||||
} | ||||
|
||||
private fun checkNameRight(name: String) { | ||||
require(name.contains("^[a-zA-Z가-힣]*$".toRegex())) { Constants.INPUT_NAME_RIGHT_ERROR_MESSAGE } | ||||
require(name.contains("^[a-zA-Z가-힣]*$".toRegex())) { OutputView().outputErrorMessage(Constants.INPUT_NAME_RIGHT_ERROR_MESSAGE) } | ||||
} | ||||
|
||||
private fun checkTryNumberNull(number: String?) { | ||||
require(number != null) { Constants.INPUT_TRY_NUMBER_NULL_ERROR_MESSAGE } | ||||
require(number != null) { OutputView().outputErrorMessage(Constants.INPUT_TRY_NUMBER_NULL_ERROR_MESSAGE) } | ||||
} | ||||
|
||||
private fun checkTryNumberIsRight(number: String?) { | ||||
try { | ||||
number!!.toInt() | ||||
} catch (e: NumberFormatException) { | ||||
throw IllegalArgumentException(Constants.INPUT_TRY_NUMBER_RIGHT_ERROR_MESSAGE) | ||||
private fun checkTryNumberIsRight(number: String) { | ||||
require( | ||||
number.isNotEmpty() && number.chars().allMatch { Character.isDigit(it) }) { | ||||
OutputView().outputErrorMessage( | ||||
Constants.INPUT_TRY_NUMBER_RIGHT_ERROR_MESSAGE | ||||
) | ||||
} | ||||
} | ||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,25 @@ | ||
package view | ||
|
||
import util.Validator | ||
|
||
class InputView { | ||
fun inputCarNames(): String { | ||
return readLine() ?: "" | ||
val input = readlnOrNull() | ||
runCatching { | ||
Validator().checkNames(input) | ||
}.onFailure { | ||
return inputCarNames() | ||
}.getOrNull() | ||
return input ?: inputCarNames() | ||
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. input이 null일 경우 자신의 함수를 다시 호출해주고 있네요. |
||
} | ||
|
||
fun inputTryNumber(): String { | ||
return readLine() ?: "" | ||
val input = readlnOrNull() | ||
runCatching { | ||
Validator().checkTryNumber(input) | ||
}.onFailure { | ||
return inputTryNumber() | ||
}.getOrNull() | ||
return input ?: inputTryNumber() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,10 +6,10 @@ import org.junit.jupiter.api.assertThrows | |
class CarTest { | ||
|
||
@Test | ||
fun getInfoTest() { | ||
fun initTest() { | ||
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. 지금과 같은 초기화 테스트보다는, 내가 원하는 자동차 이름을 넣었을 때 해당 이름으로 객체가 생성되는지를 확인한다는 의미를 담아보면 어떨까요? |
||
val car = Car("dool") | ||
assertThat(car.getInfo().name).isEqualTo("dool") | ||
assertThat(car.getInfo().position).isEqualTo(0) | ||
assertThat(car.name).isEqualTo("dool") | ||
assertThat(car.position).isEqualTo(0) | ||
} | ||
|
||
@Test | ||
|
@@ -23,13 +23,13 @@ class CarTest { | |
fun moveTest() { | ||
val car = Car("dool") | ||
car.move(3) | ||
assertThat(car.getInfo().position).isEqualTo(0) | ||
assertThat(car.position).isEqualTo(0) | ||
} | ||
|
||
@Test | ||
fun dontMoveTest() { | ||
val car = Car("dool") | ||
car.move(4) | ||
assertThat(car.getInfo().position).isEqualTo(1) | ||
assertThat(car.position).isEqualTo(1) | ||
} | ||
} |
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.
함수명만 봤을 때에는 "InputTryNumber를 실행한다"라는 의미로 보여요.
하지만, executeInputTryNumber함수보다는 inputTryNumber라는 함수가 더 잘 이해가 돼요.
executeInputTryNumber함수를 사용하는 것을 "간접 호출"이라고 합니다.
"간접 호출"은 유용한 경우도 많지만, 자칫 잘못하게 되면 과하게 함수를 호출하게 되는 상황을 만들기도 해요.
불필요한 간접 호출을 줄여보면 어떨까요? (이하 관련 내용 동일)