안드로이드 분야의 2주 차 미션은 숫자 야구 게임이었습니다.
기능 요구 사항은 다음과 같습니다.
기능 요구 사항
기본적으로 1부터 9까지 서로 다른 수고 이루어진 3자리의 수를 맞추는 게임이다.
- 같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 낫싱이란 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방(컴퓨터)의 수를 맞추면 승리한다.
- 예) 상대방(컴퓨터)의 수가 425일 때
- 123을 제시한 경우 : 1스트라이크
- 456을 제시한 경우 : 1볼 1스트라이크
- 789를 제시한 경우 : 낫싱
- 위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다. 컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다. 게임 플레이어는 컴퓨터가 생각하고 있는 서로 다른 3개의 숫자를 입력하고, 컴퓨터는 입력한 숫자에 대한 결과를 출력한다.
- 이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다.
- 게임을 종료한 후 게임을 다시 시작하거나 완전히 종료할 수 있다.
- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.
추가된 요구 사항
- indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.
- 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
- 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
- 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라.
- JUnit 5와 AssertJ를 이용하여 본인이 정리한 기능 목록이 정상 동작함을 테스트 코드로 확인한다.
- 테스트 도구 사용법이 익숙하지 않다면 test/kotlin/study를 참고하여 학습한 후 테스트를 구현한다.
그동안 코딩을 하면서 예외 처리를 while문을 써서 잘못된 입력을 할 경우에는 다시 입력을 받도록 하였는데요, 예외를 발생시키는 경우를 처음 작성해본 것 같습니다. try-catch는 많이 사용해보았지만, 의도적으로 예외를 발생시키는 경우와는 다른 것 같습니다. 처음으로 throw를 사용하는 계기가 되었고 예외 처리를 하기에 용이함을 알게 되었습니다.
예외처리를 위해서는 예외처리를 할 경우를 먼저 생각해보아야 했습니다.
1. 숫자로 이루어진 문자열이 아닌 경우
2. 길이가 3인 문자열이 아닌 경우
3. 3개가 서로 다른 숫자가 아닌 경우
저는 위와 같은 세 가지를 도출해내었는데요, 처음에는 추가로 '입력하지 않거나 공백일 경우'도 있었습니다.
하지만 제가 1번을 예외처리하면서 toIntOrNull()을 사용하였는데 null과 공백 같은 경우도 모두 처리가 되더군요. 생각해보니 공백이나 null은 숫자로 변환할 수 없으니 한 번에 예외처리가 가능함을 알았습니다.
1주 차 공통 피드백에서 함수와 변수 이름은 길더라도 명확하게 지어야 한다는 내용이 있어, 함수명이 길어지더라도 무슨 역할을 하는지 이름만 보아도 알 수 있도록 작성하는 데에 신경 썼습니다.
또한 intelliJ에서 코드 리포맷팅 기능을 알려주셔서 커밋 전에 코드 리포맷팅을 하여 올리려고 했으나 익숙하지 않으니 잘 까먹게 되는 것 같습니다. Ctrl + Alt + L 기억하자!
저는 1주 차에서 커밋명을 작성하는 것에 어려움을 느꼈었는데요, 저뿐만이 아니었나 봅니다. 미션 저장소 하단에 커밋 컨벤션 링크를 공유해주셔서 이전보다는 수월하게 작성할 수 있었습니다.
커밋명은 다음과 같은 구조로 작성하였습니다.
<type>(<scope>): <subject>
제가 랜덤으로 번호를 뽑는 기능을 추가했다면, feat: 랜덤 숫자 뽑기 기능 구현과 같은 방식으로 작성할 수 있습니다. scope는 뭘 작성해야 하는지 더 찾아봐야 할 것 같습니다.
이번 과제에서 신경 쓴 것이 있다면 함수가 한 가지 일만 담당하도록 하는 것이었습니다. 저는 그동안 코드가 길어지지 않는 이상 한 함수에서 두 개 정도의 일을 처리하도록 작성한 경우도 있었습니다. 미션을 수행하면서 '한 가지 일만 하도록 한다!'라는 생각을 계속했습니다. 함수 내 코드 길이는 짧아지니 가독성이 좋아졌습니다.
예전에는 함수가 두 가지 (A, B 기능)을 가지고 있어 다른 곳에서 B 기능을 사용해야 할 때 함수를 두 개로 분리했었는데, 미리 함수가 한 가지 기능을 하도록 작성하니 뒤늦게 코드를 변경해야 하는 일이 없어 좋은 것 같습니다.
애초에 단일 책임의 원칙을 따라 한 가지 일을 하도록 작성해야 하는 건데 너무 생각 없이 짰던 것 같네요.
2주차 미션도 끝이 났습니다!
2주 차 미션을 진행하며 공부한 내용을 하단에 정리해두겠습니다.
예외 처리
try-catch
- 예외가 발생하지 않으면 try문 실행
- catch문으로 발생한 예외를 잡아서 처리
fun main(args: Array<String>) {
val str = "abc"
readNumber(str)
}
fun readNumber(input: String) {
input.toInt() // ERROR
}
위 코드를 수행하면 다음과 같은 에러가 발생합니다.
str을 Int형으로 변환하려 했으나 abc는 숫자로 변환할 수 없기에 NumberFormatException 에러가 발생합니다.
이때 try-catch문을 사용하면, NumberFormatException 에러 발생 시 다른 일을 수행하도록 할 수 있습니다.
import java.lang.NumberFormatException
fun main(args: Array<String>) {
val str = "abc"
readNumber(str)
}
fun readNumber(input: String) {
try {
input.toInt()
} catch (e: NumberFormatException) {
println("형변환이 불가능합니다.")
}
}
실행 결과는 다음과 같습니다.
try-catch-finally
- try-catch 다음에 finally를 작성하여, 예외가 발생한 경우/발생하지 않은 경우 모두 수행
//try문 수행 후 finally문 수행
import java.lang.NumberFormatException
fun main(args: Array<String>) {
val str = "123"
readNumber(str)
}
fun readNumber(input: String) {
try {
println(input.toInt())
} catch (e: NumberFormatException) {
println("형변환이 불가능합니다.")
} finally {
println("끝")
}
}
실행 결과는 다음과 같습니다.
//catch문 수행 후 finally문 수행
import java.lang.NumberFormatException
fun main(args: Array<String>) {
val str = "abc"
readNumber(str)
}
fun readNumber(input: String) {
try {
println(input.toInt())
} catch (e: NumberFormatException) {
println("형변환이 불가능합니다.")
} finally {
println("끝")
}
}
실행 결과는 다음과 같습니다.
throw
- 예외 발생시키기
import java.lang.NumberFormatException
fun main(args: Array<String>) {
val str = "abc"
readNumber(str)
}
fun readNumber(input: String) {
try {
println(input.toInt())
} catch (e: NumberFormatException) {
throw IllegalArgumentException("형변환 불가능")
} finally {
println("끝")
}
}
실제 잡힌 에러는 NumberFormatException이지만 throw를 통해서 발생시킬 예외와 에러 메시지를 던질 수 있습니다.
아래에서 throw로 던진 IllegalArgumentException이 에러로 발생한 것을 확인할 수 있습니다.
'Android > 우아한테크코스 5기' 카테고리의 다른 글
[우아한테크코스 5기 프리코스] 안드로이드 4주 차 회고록 (0) | 2022.11.23 |
---|---|
[우아한테크코스 5기 프리코스] 안드로이드 3주차 회고록 (0) | 2022.11.23 |
[우아한테크코스 5기 프리코스] 안드로이드 1주차 회고록 (0) | 2022.11.08 |