벌써 프리코스 3주 차를 마쳤다 이제마지막인 4주 차만 마무리를 한다면 프리코스는 끝나게 된다.
생각보다 짧았던 4주였다. 꼭 좋은 결과가 있으면 좋겠다.
이번에는 3주 차 로또 게임을 만들어보았는데 만들면서 느꼈던 점들과 배웠던 점들을 작성해 보겠다.
공통 피드백
1. 함수 라인에 대한 기준
이번 미션에 요구사항 중 15라인으로 제한하는 요구사항이 있었는데 이번미션은 저번미션보다 생각보다 난도가 높았다고 생각이 되었다. 그래서 지금까지 해왔던 걸로 코드를 구현하면 하나의 함수의 굉장히 긴 코드가 작성되곤 했다.
그래서 어떻게 하면 좋을까 생각을 하다가 stream이라는 걸 알게 되었고 이걸사용해보니 코드가 굉장히 줄었다.
stream을 더 잘 활용할 수 있다면 코드의 길이와 가독성이 굉장히 높아질 거 같다.
내가 작성한 코드에서 내가 사용했던 것을 예로 들자면
private static int matchCount(Lotto lotto, List<Integer> numbers) {
return (int) numbers.stream()
.filter(lotto::hasMatchedNumber)
.count();
}
이 함수는 Lotto 객체와 정수 리스트 numbers 간의 일치하는 숫자 개수를 계산하는 함수다
하지만 여기서 stream을 사용하지 않고 만든다면?
private static int matchCount(Lotto lotto, List<Integer> numbers) {
int count = 0;
for (int number : numbers) {
if (lotto.hasMatchedNumber(number)) {
count++;
}
}
return count;
}
이런 식으로 만들 수가 있는데 그냥 보기만 해도 stream이 가독성도 좋고 코드가 줄어들었다는 거를 알 수가 있다.
2. 발생할수 있는 예외 상황에 대해 고민한다.
정상적인 경우를 구현하는 것보다 예외 상황을 모두 구려해 프로그래밍하는 것이 더 어렵다. 그래서 예외 상황을 고려해 프로그래밍하는 습관을 들인다.
그래서 나는 readme에 모든 예외상황을 생각해 보고 적어놓고 기능을 구현하면서 추가할 게 있으면 추가하는 식으로 예외상황을 고려했다
그리고 작성한 예외상황들을 테스트할 테스트 클래스와 여러 함수를 통해 예외상황에 대한 테스트 함수도 작성하였다.
3. 연관성이 있는 상수는 static final 대신 enum을 활용한다.
이번에 로또게임을 만들때 요구사항 중 enum을 사용하라는 글귀가 있었다.
처음 들어보는 단어라 검색을 해보았는데 간단히 말하자면 상수들의 집합을 의미한다.
과거에는 특정 상수값을 사용하기 위해선 모두 상수로 선언해서 사용했다.
이런 식으로 말이다.
public static final String ERROR_NUMBER_MESSAGE = "[ERROR] 입력값은 숫자만 가능합니다.";
public static final String ERROR_THOUSAND_MESSAGE = "[ERROR] 1000단위로만 입력이 가능합니다.";
public static final String ERROR_ZERO_MESSAGE = "[ERROR] 입력값은 0 일수 없습니다.";
이렇게 사용하면 개발자가 실수하기도 쉽고 한눈에 알아보기도 쉽지 않다.
그리고 관련 있는 값들끼리 묶으려면 접두어를 사용해서 점점 변수명도 지저분해진다.
Enum 클래스는 이러한 문제점을 말끔히 해결해 주는 굉장히 유용한 클래스다.
public enum Rank {
EMPTY(0, 0, false, ""),
FIFTH(5_000, 3, false, "3개 일치 (5,000원) - "),
FOURTH(50_000, 4, false, "4개 일치 (50,000원) - "),
THIRD(1_500_000, 5, false, "5개 일치 (1,500,000원) - "),
SECOND(30_000_000, 5, true, "5개 일치, 보너스 볼 일치 (30,000,000원) - "),
FIRST(2_000_000_000, 6, false, "6개 일치 (2,000,000,000원) - ");
public static final int BONUS_CONTAIN_CONDITION = 5;
private int prize;
private int matchLottoCount;
private final boolean bonus;
private String message;
Rank(int prize, int matchLottoCount, boolean bonus, String message) {
this.prize = prize;
this.matchLottoCount = matchLottoCount;
this.bonus = bonus;
this.message = message;
}
enum에 대한 자세한 내용은 여기서 설명하기보다는 내가 찾아보다가 도움이 되었던 블로그를 소개해주겠다.
https://bcp0109.tistory.com/334
Java Enum 1편 : Enum 기본적인 사용
1. Overview Java Enum 타입은 일정 개수의 상수 값을 정의하고, 그 외의 값은 허용하지 않습니다. 과거에는 특정 상수값을 사용하기 위해선 모두 상수로 선언해서 사용했습니다. public static final String M
bcp0109.tistory.com
여기서 enum의 대한 사용법과 정의를 알게 되었다.
4. 테스트 코드도 코드다.
테스트 코드도 코드이므로 리팩터링을 통해 개선해 나가야 한다. 특히 반복적으로 하는 부분을 중복되지 않게 만들어야 한다. 예를 들어 단순히 파라미터의 값만 바뀌는 경우 라면 @ValueSource()와 @ParmeterizedTest 어노테이션을 통해서 반복되는 변수들을 테스트할 수가 있다. 하지만 이번 미션에서는 사용하지 않았다. 아니 몰랐다...
@DisplayName("숫자가 아닌 입력.")
@Test
void createLottoAmountByDifferentTypes() {
assertThatThrownBy(() -> new LottoAmount("as@"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining(ERROR_NUMBER_MESSAGE);
}
이렇게 간단하게만 만들었지만 위두개의 어노테이션을 이용한다면
@DisplayName("숫자가 아닌 입력.")
@ParameterizedTest
@ValueSource(strings = {"as@", "abc", "!@#$"})
void createLottoAmountByDifferentTypes(String invalidInput) {
assertThatThrownBy(() -> new LottoAmount(invalidInput))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining(ERROR_NUMBER_MESSAGE);
}
이런 식으로 숫자가 아닌 입력에 대한 여러 테스트를 한 번에 테스트를 할 수가 있다.
꼭 알아두자.
이번 과제에서는 처음사용해 보는 것들이 많았다 stream과 enum 등등 막상 어떻게 써야 할지 몰랐었던 것들인데
사용에 익숙해지면 굉장히 편리한 것들이라고 생각이 든다 그리고 매주 과제를 만들면서 코드가 점점 발전한다는 게 느껴진다. 처음에는 클래스 나누기부터 함수나누기까지 전혀 모르는 상태였는데 과제를 하면 할수록 다른 사람코드들을 보면서 이렇게 구현하면 되겠구나 라는 생각이 많이 들었다. 그러다 보니 내 코드도 자연스럽게 변해갔던 거 같다.
좋은 결과 나오지 않더라도 마지막 4주 차과제까지 한번 열심히 해보자
'우테코' 카테고리의 다른 글
우아한테크코스 프리코스 4주차 후기 (0) | 2023.11.27 |
---|---|
우아한테크코스 프리코스 2주차 후기 (0) | 2023.11.10 |
우아한테크코스 프리코스 1주차 후기 (0) | 2023.10.28 |