각종 후기/우아한테크코스

[우아한 테크코스 3기] LEVEL 1 회고 (29일차)

제이온 (Jayon) 2021. 3. 2.

안녕하세요? 제이온입니다.

 

오늘은 새로운 미션인 블랙잭을 수행해 보았습니다.

 

 

상속, 인터페이스 수업

첫 우테코 오프라인이지만, 저는 여전히 온라인으로 참여하였습니다. 우리에게 친숙한 커피와 차를 예시로 들어서 쉽게 상속을 이해할 수 있었고, 특히 중복되는 메소드를 찾아서 추상화하는 것이 중요하다고 생각하였습니다.

 

하지만, 수업은 듣다 보니 추상 클래스와 인터페이스의 실용적인 차이가 명확하게 와닿지가 않았고, 이에 대해 질문을 하였으나 제이슨은 직접 블랙잭 미션을 수행하면서 느껴보라고 말씀해 주셨습니다.

 

그래서 아쉽지만 이 궁금증을 가진 상태에서 미션을 잘 수행해봐야겠다고 생각하였습니다.

 

 

페어 프로그래밍 - 1

오늘은 새로운 미션이 열리는 날이어서 페어도 새롭게 배정되었습니다. 원래 백엔드 인원은 52명이었으나, 한 명이 나갔기 때문에 한 팀은 3인 페어가 되어야 합니다. 그리고 제가 이번에 3인 페어로 배정되어 조엘, 바다와 한 팀이 되었습니다.

 

조엘과 바다는 루터 회관에 있었기 때문에 부득이하게 저를 위해서 줌과 Code with me를 통해 원활한 페어 프로그래밍을 할 수 있도록 배려해 주셨습니다 ㅎㅎ.

 

처음에는 상속과 추상 클래스를 활용한 예제 문제가 있었는데, 크게 시간이 오래 걸리지는 않았습니다. 다만, 추상 메소드의 값을 이용하여 일반 메소드에서 사용할 수 있다는 점은 처음 알았습니다.

 

 

public abstract class Car {
    /**
     * 리터당 이동 거리. 즉, 연비
     */
    abstract double getDistancePerLiter();

    /**
     * 여행하려는 거리
     */
    abstract double getTripDistance();
    
    /**
     * 차종의 이름
     */
    abstract String getName();

    /**
     * 주입해야할 연료량을 구한다.
    */
    double getChargeQuantity() {
        return getTripDistance() / getDistancePerLiter();
    }
}

 

 

여기서 연비와 거리는 분명 하위 클래스에서 정의해야 하는 추상 메소드인데, 이들의 반환값을 통해 일반 메소드에서 활용할 수 있다는 점은 꼭 기억해야겠습니다.

 

 

이후에는 본격적으로 블랙잭 미션을 진행하였습니다. 먼저, 블랙잭 미션의 실행 결과를 보여드리겠습니다.

 

 

 

 

이렇게 참가자의 이름을 입력받고나서 전형적인 블랙잭 게임이 진행됩니다. 처음에 카드를 2장씩 받고, 카드 안에 있는 숫자의 합이 21이거나 21에 가까운 사람이 승리하는 규칙이죠. 이때, A는 1 또는 11로 선택할 수 있고, K, Q, J는 모두 10입니다.

 

오후 7시까지 2시간 동안 블랙잭 미션을 수행하였는데, 짧은 시간이지만 페어와 협업하면서 여러 가지 유용한 경험을 할 수 있었습니다.

 

 

첫 번째는 테스트 코드에서 객체가 단순히 생성되었는지 확인하는 메소드를 새롭게 알게 되었습니다. 코드를 우선 봅시다.

 

 

    @Test
    @DisplayName("참가자가 잘 생성되는지 확인")
    void create() {
        assertThatCode(() -> new Player("bada"))
            .doesNotThrowAnyException();
    }

 

 

이렇게 'assertThatCode().doesNotThrowAnyException()'을 사용하면, 객체가 오류 없이 잘 생성되었는지만 체크할 수 있습니다. 저는 그전까지 객체의 필드값을 getter로 받아와서 일치하는지 확인하였는데, 굳이 필요 없는 getter를 사용하지 않아도 되는 것이죠.

 

 

두 번째는 객체의 관계를 그려보는 것입니다. 저는 관계를 직접 손으로 그리는 것은 귀찮아서 텍스트로 치거나, 머릿속으로 상상하여 대략적으로 구조를 맞춰보는 편이었습니다.

 

하지만, 화이트보드에서 조엘이 객체 간의 관계를 손으로 직접 그리니까 전반적인 틀을 이해하기 쉬웠고, 나중에 객체 간의 관계를 잊어버리더라도 기록한 그림을 보면서 다시 상기하기 용이하였습니다. 앞으로는 귀찮더라도 직접 모형을 그려보면서 이해하려는 습관을 길러야겠습니다.

 

 

그 외에 한 가지 일에 집중하는 것의 장점을 오늘도 깨닫고, TDD의 중요성을 다시 한 번 느꼈죠. 특히, 다른 길로 새지 않도록 페어들이 지적해 줘서 참 고마웠습니다.

 

 

페어 프로그래밍 - 2

내일 할 일을 줄이기 위하여 오늘 오후 9시 20분부터 1시간 20분동안 추가로 페어 프로그래밍을 진행하였습니다. 관건은 딜러가 카드의 숫자 합이 16이하일 때까지 계속 덱에서 카드를 뽑는 것이었습니다. 여기서, 한 가지 난관에 봉착하였습니다.

 

바로, 에이스의 값이 1 또는 11로 선택할 수 있다는 것이었습니다. 1차적으로는 enum에 ACE("A", 1, 11)로 할지, ACE("A", 1)로 고민하였고, 우선은 전자로 하는 방향으로 정하였습니다.

 

문제는 딜러가 처음에 (A, 6)을 뽑았을 때, 이것을 17로 봐야하는 것인지 7로 봐야하는 것인지에 대해 토론을 진행하였습니다. 딜러 외에 참가자는 적당히 A가 1 또는 11로 게임에서 패배가 되지 않는 선에서 결정하면 됐지만, 딜러는 A의 유무가 우리를 머리 아프게 만들었습니다.

 

저는 구글링하다보니 '블랙잭 소프트 17' 룰을 알게 되었습니다. 이것은 (A, 6)이나 (A, 3, 3)과 같이 A를 11로 보았을 때 숫자의 합이 17이 되는 경우, 딜러가 더 이상 카드를 뽑지 않는 것을 말합니다. 우리는 이 룰을 적용하기로 결정하였고, 덕분에 딜러 기준으로 A는 11로 처리하여도 무방하였습니다.

 

이후에는 딜러 클래스에서 자신의 숫자 합을 구하는 메소드와 숫자의 합이 16 이하인지 검증하는 메소드를 정의하고, 오늘의 페어 프로그래밍을 마쳤습니다.

 

 

로또 2단계 미션 종료

저번 2차 피드백을 마지막으로 미션이 종료되었습니다. 제가 이전에 요청한 질문은 모두 문제가 없었고, 굳이 하나 꼽자면 Lotteries 필드의 lottos를 ArrayList로 초기화하지 말라는 것입니다.

 

 

private final List<Lotto> lottos = new ArrayList<>();

 

 

객체의 필드값을 이렇게 ArrayList로 한정짓게 되면, 나중에 다른 리스트의 종류로 초기화할 수 없다는 문제가 있어서 생성자 단계에서 초기화하라는 조언을 해 주셨습니다.

 

완성된 로또 미션 코드는 이곳에서 확인하실 수 있습니다.

 

 

정리

블랙잭 미션이 목요일 오후 6시까지 마감이므로 앞으로 이틀동안은 고통받을 것으로 예상됩니다. 하지만, 또 그 속에서 성장할 생각을 하니 설레기도 합니다.

 

오늘은 비록 루터회관에 가지 못하였는데 잠실로 갈 수 있는 다른 루트를 알아냈기 때문에, 아직 방은 대기중이지만 다음 시간부터는 오프라인에 참석할 수 있을 듯 합니다.

 

그 외에, 제가 아직 프로필 사진을 못 찍었는데 이 글을 보는 크루들은 댓글로 포즈를 추천해 주시길 바랍니다. 소품도 같이 알려주시면 좋겠네요 ㅎㅎ

댓글

추천 글