ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [우아한테크코스-프리코스] 1주차 숫자야구 회고를 해보자 ⚾️
    ⭐️ 우아한테크코스 2023. 10. 26. 14:15

     

     

    우아한테크코스 - 프리코스에 참여하고 첫 주의 미션으로 ‘숫자야구’를 구현했어야 했다.

    🔗 나의 Pull Request Link

     

    ⚾ 숫자야구


    🎯 요구사항

    • [x] 1 ~ 9 사이의 서로 다른 수로 이루어진 3자리 수를 맞추기
    • [x] 같은 수가 같은 자리인 경우 스트라이크, 다른 자리인 경우 볼
    • [x] 컴퓨터가 1 ~ 9 까지의 서로 다른 임의의 수 3개를 선택
    • [x] 게임 플레이어는 서로 다른 3개의 숫자를 입력하고 컴퓨터는 입력한 숫자에 대한 결과 출력

     

    🤔 고민


    1️⃣ 숫자야구에 필요한 상수들을 어떻게 관리할까?

    숫자야구에서 필요한 상수들이 여러개 있었다.

    • 몇 자리 수인지
    • 게임 재시작 입력 값
    • 게임 종료 입력 값

     

    처음 생각한 것은 static final 변수로 선언해 사용하는 곳에서 사용하도록 했다.

    private static final int DIGIT = 3;
    private static final String RESTART = "1";
    private static final String EXIT = "2";
    

     

    📖 static final

    • 인스턴스가 만들어질 때마다 새로운 메모리에 초기화하지 않고, 하나의 메모리 공간만을 사용할 수 있다.

     

    상수 값들이 다 떨어져 있다보니 변경사항이 발생했을 때 해당 상수값이 선언된 곳을 찾아 수정하는 과정이 불편하지 않을까? 라는 생각을 하게 되었다.

     

     

    ❗한 곳에서 상수들을 관리하면 좋지 않을까? 라는 생각을 해 열거형 클래스를 통해 처리하기로 했다.

    public enum BaseBallGameConfig {
        BASEBALL_NUMBER_SIZE(3),
        BASEBALL_MIN_NUMBER(1),
        BASEBALL_MAX_NUMBER(9),
        BASEBALL_GAME_RESTART(1),
        BASEBALL_GAME_EXIT(2);
        ...
    }

    이를 통해 변경사항이 생기면 해당 클래스에서 값만 바꾸게 되면 되었다.

    • 유지보수가 더 쉬워지지 않았나?

     

    2️⃣ 정규식을 통해서 입력된 숫자에 대한 검증❓

    처음에는 사용자가 입력한 문자열에 대해서 정규식을 사용해서 아래의 조건을 검증하면 매우 편할 것이라고 생각했다.

    • 입력된 수가 서로 다른 3개의 숫자
    • 입력된 수의 범위가 1 ~ 9 사이
    private boolean isValidatedInputString(String inputString) {
        String regex = String.format("^(?!.*(.).*\\\\1)[0-9]{%d}$", DIGIT);
        return inputString.matches(regex);
    }

     

    이렇게 정규식을 통해 입력된 문자열에 대해 바로 검증하도록 했었다.

     

    ⚠️ 하지만, 정규식을 사용했을 경우 어떤 입력이 들어와 예외를 발생시켰을 때, 어떤 부분에서 검증이 실패했는지 정확하게 알 수 없었다.

    • 입력된 수가 4자리인지 입력된 수의 범위를 넘어선 수가 입력되었는지 알 수 없음

     

    ❗저는 커스텀 예외를 만들어 어떤 부분에서 예외가 발생했는지 처리를 해주기 위해서 정규식보다 따로 검증하는 메서드를 나누어 사용하기로 선택했다.

     

    메서드로 검증을 하는 경우 여러 중복 코드가 발생할 수 있는 문제가 있지만 많은 검증을 하지 않는다고 생각하여 이정도 중복은 괜찮을 것이라고 생각했다.

     

    ...
    
    private void validateSize(int[] numbers) {
        if(numbers.length != BASEBALL_NUMBER_SIZE.getValue())
            throw new BaseBallGameException(INVALID_LENGTH);
    }
    
    private void validateWithinRange(int[] numbers) {
        for(int number : numbers) {
            if(number < BASEBALL_MIN_NUMBER.getValue() || number > BASEBALL_MAX_NUMBER.getValue())
                throw new BaseBallGameException(OUT_OF_RANGE);
        }
    }
    
    private void validateDuplicate(int[] numbers) {
        Set<Integer> set = new HashSet<>();
        for(int num : numbers) set.add(num);
        if(set.size() != BASEBALL_NUMBER_SIZE.getValue()) throw new BaseBallGameException(DUPLICATED_NUMBERS);
    }
    ...

    이렇게 검증하는 메서드를 따로 두고 각각의 조건에 만족하지 않는 경우에 커스텀 예외를 통해 어떤 부분에서 예외가 발생했는지 명시적으로 보일 수 있도록 했다.

     

    🤔 결론

    선택한 내용이 정답은 아니겠지만 위 내용뿐만 아니라 다른 내용에 대해서도 고민하는 과정을 통해 더 많이 배울 수 있었던 시간이 되었던 것 같다.

    아쉬운 점은 PR을 보내고 나니 코드에 부족한 부분이 더 보이는 것 같아 더 많은 best practice를 찾아봤으면 좋았을 것 같다.

     

    ⭐ 4Ls 회고


    ❤️ LIKED

    • 이번 미션을 하면서 많은 동료분들과 함께 커뮤니케이션하면서 하다보니 좋은 자극들을 많이 받아 동기부여가 되었다.
    • 동료분들이 고민하는 내용에 대해 알 수 있었고 그런 내용을 보며 좀 더 꼼꼼하게 코드를 작성해야겠다는 생각을 할 수 있었다.
    • 테스트 코드를 작성해 숫자게임에 대한 로직을 수정했을 때 바로 짜놓은 테스트 코드를 통해 어떤 문제가 있는지 확인할 수 있었다.

     

    📖 LEARNED

    📍 JMH (Java Microbenchmark Harness)

    • JVM 상에서 실행되는 코드의 성능을 측정하기 위한 벤치마크 도구
    • 자바에 있는 Random 클래스에 대해 공부하면서 간단하게 성능을 비교해보려 찾아보다 공부하게 되었다
    • 간단하게 성능 비교를 해볼 상황이 생긴다면 또 다시 사용해보고 싶다.

     

     

    📍 일급 컬렉션

    • 일급 컬렉션을 공부하고 이를 통해 일급컬렉션의 장점을 살려서 이번 미션을 해보려고 노력했다.

     

     

    📍 Java 17

    • 이번 미션을 하기 전까지 Java 11을 사용해왔었다. 이번 미션에서의 요구사항으로 Java 17이 있어 이번 기회에 Java 17에 대해 더 공부해볼 수 있었다.
    • Java 11과 다르게 Java 17에서 추가된 기능에 대해서 이 미션에서 사용해볼 수 있는 것이 있다면 사용해보려고 했다.
      • Record
      • Switch Expression

     

    🗑️ LACKED

    • 테스트 코드를 작성하는 과정에서 실패 케이스를 더 생각할 수 있었을 것 같은데 그런 부분에서 아쉬웠다.
    • commit 을 할 때 너무 사소한 내용에 대해서 commit을 한 것 같아 이런 부분에 대해서 공부하고 신경써서 기능별로 commit을 해야겠다는 생각을 하게 되었다.

     

    ➡️ LONGED FOR

    • 이번에 부족하다고 느꼈던 부분, 배웠던 부분에 대해서 best practice를 더 찾아보고 적용해보고자 한다.
    • 동료들이 고민하는 부분, 공유해준 부분에 대해서 함께 고민해보고 이에 대한 해결을 찾아가며 더 좋은 코드를 작성해보고 싶다.

    댓글

Designed by Tistory.