회고: 우아한테크코스 6기 - 프리코스 3주차 로또 미션

금암동 코딩왕·2023년 11월 15일
1
post-thumbnail

우테코 3주차가 정말 빠르게 3주차가 지나갔다.
또한 정말 힘들었던 3주차였다고 생각한다.

자기 관리에 실패하다.

이유는 이번 3주차에는 컨디션 조절에 완전 실패했다.
심한 감기에 걸려 2일은 그냥 누워서 있었다......

물론 컨디션 조절 조차 본인의 실력이기 때문에 할 말은 없다.

이번 3주차의 미션은 로또였다.
사실 처음 로또 미션을 받았을 때의 조건들은 "오!! 뭐지? 너무 쉽지 않나?" 라는
생각을 가지고 시작했던 것 같다.

하지만 역시 나의 교만함에 빠져 허우적 거렸다.

이번 과제 목표

이번 과제의 목표는 다양한 클래스의 기능 분리와
코드 가독성과 유지보수의 측면에서 접근해 각 기능을 명확하게 만들어보자!!! 였다.

3주차 로또 미션

코드를 보면 2주차의 코드와는 완전 다르지만 나만 느끼는 것일 수 있다. 😂

지난 주 미션에서는 클래스 분리를 하는 것에 있어 오버 엔지니어링이라
생각하게 되었는데 그것에 유념하며 프로그래밍을 진행하였다.

항상 좋은 코드란 가독성, 유지보수, 효율적인 면에서 어떻게 하는 것이
좋은 방식일까를 고민하며 똑같은 코드를 적었다 지웠다 했다.

로또 미션 진행을 하며..

public class Lotto {
    private final List<Integer> numbers;

    public Lotto(List<Integer> numbers) {
        validate(numbers);
        this.numbers = numbers;
    }

    private void validate(List<Integer> numbers) {
        if (numbers.size() != 6) {
            throw new IllegalArgumentException();
        }
    }

    // TODO: 추가 기능 구현
}

3주차 로또 미션에서 주어진 기본 클래스이다.

처음에 이걸 보고 할만하다 생각했는데 막상 키보드에 손을 올리니
막막했다. 정말 막막해졌다. 그래도 2주간의 경험이 있는데 이렇게 모르나...

로또 미션 기본 클래스의 조건
Lotto에 매개 변수가 없는 생성자를 추가할 수 없다.
numbers의 접근 제어자인 private을 변경할 수 없다.
Lotto에 필드(인스턴스 변수)를 추가할 수 없다.
Lotto의 패키지 변경은 가능하다.

거기에 위 조건까지 주어지니 처음엔 클래스 기본 사용 방식부터
다시 공부하느라 시간을 보낸 것 같다.

객체 지향 클래스가 도대체 뭐냐?

로또 미션을 시작할 때 목표로 삼은 부분을 실행하기 위해
우선적으로 객체지향에 대해 이해를 해야했다.

객체지향을 모르고 과제를 진행한다? 이건 팥없는 팥빵이다.

사실 흔하게 사용되는 용어로 붕어빵틀과 붕어빵이라는 말을 많이 들었는데
이것만 가지고는 이해가 되지 않았다.

한참 고민하다가 결국 로또를 직접 사러갔다. [5000원 당첨 😁]
카드 결제를 하려 하는데 안된다고 들었다. 처음 사보는 로또...

일단 로또를 사러 가서 느낀것은
고객 -> 사장님 -> 기계 -> 로또 번호 -> 로또 종이 그리고 다시 고객

곰곰히 생각하니 저 하나하나가 객체가 아닌가 생각이 들었다.

public class LottoTicketFactory {

    public static List<Lotto> lottoTickets(int ticketCount) {
        List<Lotto> tickets = new ArrayList<>();
        while (tickets.size() < ticketCount) {
            tickets.add(lottoTicket());
        }
        return tickets;
    }

    private static Lotto lottoTicket() {
        List<Integer> lottoNumbers = new ArrayList<>(Randoms.pickUniqueNumbersInRange(
                Constant.MIN_LOTTO_NUMBER, Constant.MAX_LOTTO_NUMBER, Constant.LOTTO_NUMBER_COUNT
        ));
        Collections.sort(lottoNumbers);
        return new Lotto(lottoNumbers);
    }
}

그래서 로또를 생성하는 기계라는 느낌으로 코드를 작성했다.
처음엔 그냥 Machine이라고 작성했는데 너무 추상적이어서 흔히들
사용한다는 controller 내에 factory로 작성했다.

오 뭔가 지난 주와는 다르게 좀 더 객체지향에 가까워진 느낌이 나지 않는가?

테스트는 또 어떻게 하는거야..

이번 과제에서는 지난 주차보다 조금 더 많은 테스트를 진행했다.

코드를 작성하는 것 보다 테스트를 진행하는 것이 더욱 어려웠다.

일단 어디서부터 어디까지 이건 테스트해도 괜찮은거야?
이거까지 테스트 하는건가? 테스트 커버리지는?

그럼 단위 테스트를 할 때 도메인에서 진행하는 단위 테스트 말고
하위 메서드도 전부 다 해야하는 것인가?

class DepositTest {

    @DisplayName("Deposit 을 생성한다.")
    @Test
    public void createDeposit() {
        int amount = Constant.TICKET_PRICE * 2;
        Deposit deposit = new Deposit(amount);
        assertThat(deposit.getDeposit()).isEqualTo(amount);
    }
}

하나만 예시로 들자면 이번 과제에서 따로 하위 메서드는 진행하지 않았다.

첫번째로 익숙하지 않았다.
코드에 익숙하지 않다보니 하나씩 전부 찾아서 해야했다.

두번째론 진짜 헷갈렸다.
그냥 이렇게만 하면 되는것인가? 도메인으로 단위 테스트만 하면 되는건가?

예로 로또의 순위를 매기는 하위 메서드들은 어떻게 해야하는 것인지
입력값이 맞는지만 테스트하기 보다는 연산을 책임지는 메서드도 확인해야 하지 않나?

정말 한 주간 많은 고민에 고민을 거듭했다.

내가 생각한 테스트

공부하면서 생각해본 진짜 테스트의 의미는 궁극적으로 코드의 오류를 줄이는 것이다.

그렇다면 정말 세세하게 테스트를 진행하는 것이 좋지 않을까? 라는 생각을 했다.
기본적으로 나는 오류를 수정하는데 정말 많은 시간을 투자한다.

그런데 처음부터 테스트 코드를 작성하고, 진행한다면??
후에 있을 오류들을 조금이라도 더 줄이고, 생산성을 높일 수 있지 않을까?

이미 도메인에 넣은 메서드들의 반환 값이 정상이어도 코드를 작성하면서
어디서든 변경될 여지가 있다.

final로 상수 처리를 하더라도 어디선가 발생한 에러를 못잡는다면??

예전에 자바스크립트를 공부할 때 그랬던 적이 있다.
동적 언어인 자바스크립트는 타입을 알아서 정해준다. 때문에 에러가 발생할 시
어디서 에러가 났는지 몰랐던 적이 있다.

아 그래서 결론은 커버리지를 최대한 채우는 것이 좋다!

마침.

으 정말 공부할 시간이 부족한 것 같다. 잠이 아예 없어지면 좋겠다...

물론 우테코 과정을 진행하며 어마어마하게 자바를 학습하게 되었다.
하지만 기본적인 미션을 진행하는데 급해 세세히 들여다 보는 것을 하지 못했다.

조금더 세심하게 코드를 작성하고, 이쁘게 작성하고 싶은데 욕심인가... 라는 생각도 든다.
항상 명심하자 우선 기능부터 다음 클래스를 나눠보자 또 다짐한다.

다음 미션은 프리코스 마지막 과제이다.
후회를 남기지 말도록 더 열심해 해보자!! 💪

profile
헤이 헤이 궁금증과 타협하지 말자구!!

0개의 댓글