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

[우아한 테크코스 3기] LEVEL 1 회고 - 블랙잭 1단계 미션의 2차 피드백을 받아보다 (36일차)

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

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

 

오늘은 오프라인으로 루터 회관에서 우아한테크코스 교육을 받았습니다.여러모로 바쁜 하루였습니다.

 

 

데일리 미팅

오전 10시에 데일리 미팅이 진행되었습니다. 오늘의 진행자는 '로키'로, '노래 1초 듣고 맞히기'게임을 준비해 주셨습니다. 로키를 제외한 나머지 크루들이 노래를 맞히되, 끝까지 맞히지 못한 사람이 내일 데일리 미팅을 진행하기로 하였습니다.

 

어떻게 보면 별 것 아닌데도, 다들 승부욕이 불타오르는 모습이 재미있었고, 덩달아 저도 어떻게든 꼴찌는 면하려고 노력하였습니다. 특히, 케빈이 80%는 정답을 말해놓고 끝까지 완벽한 정답을 말하지 못해서 결국 다음날 진행을 맡게 되었습니다 ㅋㅋㅋㅋ. 저는 다행히 중간에 블랙핑크 노래를 간신히 맞혀서 벌칙은 피했습니다.

 

짧은 시간이었지만, 크루들과 함께 게임을 해서 즐거웠고, 이 게임을 위해 적지 않은 시간을 투자하신 로키에게 고맙다는 말을 전하고 싶습니다.

 

 

블랙잭 피드백 수업

오늘은 오전에 제이슨이 블랙잭 피드백 수업을 해 주셨습니다. 요약하자면, 상태 패턴을 통해 기존의 있던 중복된 코드를 추상화하여 더 나은 구조로 바꾸는 것입니다. 블랙잭 게임에는 상태가 HIT, STAY, BUST, BLACKJACK으로  존재하는데, 이들을 각각 추상화하여 각자의 역할을 수행하도록 만드는 것이 목적입니다. 결과적으로, 아래와 같은 구조를 보입니다.

 

 

 

 

수업을 들으면서 이러한 구조를 설계할 수 있다는 것에 흥미로웠지만, 막상 제 코드에 적용하기에는 너무나도 바뀌어야할 점이 많았습니다. 따라서, 위 디자인 패턴을 인지를 한 상태에서 미션을 진행하고, 막히는 부분이 있다면 상태 패턴을 적용해 볼 생각입니다.

 

 

블랙잭 1단계 미션 2차 피드백

2차 피드백은 오늘 오전 9시 즈음에 올라왔습니다. 

 

 

 

 

첫 번째 수정 사항은 CardDeck 객체를 생성할 필요 없이 사용하게 바꾸는 것입니다. CardDeck은 총 52장의 카드를 만들어서 보관한 다음에 카드를 나눠주는 역할을 합니다. 즉, 52장의 카드를 미리 생성한 다음에 관련된 메소드를 static으로 선언하면 CardDeck 객체를 생성하지 않고도 관련 로직을 이용할 수 있겠다고 판단하였습니다.

 

 

public class CardDeck {

    private static final List<Card> cards = new ArrayList<>();

    static {
        for (final CardType type : CardType.values()) {
            Arrays.stream(CardNumber.values())
                .forEach(number -> cards.add(new Card(number, type)));
        }
        Collections.shuffle(cards);
    }

    private CardDeck() {
    }

    public static List<Card> getCards() {
        return Collections.unmodifiableList(cards);
    }

    public static Card distribute() {
        return cards.remove(0);
    }
}

 

 

위와 같이 static 블록으로 52장의 카드를 저장하고 셔플한 다음에, CardDeck이 수행하는 책임을 static 메소드로 수정하였습니다.

 

 

 

 

두 번째 수정 사항은 블랙잭 게임 역할을 하는 BlackjackGame을 만드는 것입니다. 기존의 제 코드는 GameResult에서 뷰에 넘겨줄 결과값을 만든 다음에 뷰로 넘겨주었습니다.

 

 

public class GameResult {

    public int calculateDealerResult(final Participant dealer, final List<Participant> players,
        final Result result) {
        return (int) players.stream()
            .filter(player -> dealer.decideWinner(player).isSameResult(result))
            .count();
    }

    public Map<Name, Result> makePlayerResults(final List<Participant> players,
        final Participant dealer) {
        final Map<Name, Result> results = new LinkedHashMap<>();
        for (final Participant player : players) {
            final Result result = player.decideWinner(dealer);
            results.put(player.getName(), result);
        }
        return results;
    }

}

 

 

위와 같이 딜러와 플레이어의 결과를 반환해 주는 것이죠. 하지만, 이것을 넘겨받은 뷰 로직을 보면 문제가 있습니다.

 

 

    public static void showGameResult(final Participant dealer, final List<Participant> players,
        final GameResult gameResult) {
        final List<Result> dealerResults = Arrays.stream(Result.values())
            .collect(Collectors.toList());
        final List<Integer> counts = dealerResults.stream()
            .map(result -> gameResult.calculateDealerResult(dealer, players, result))
            .collect(Collectors.toList());

        System.out.println(NEWLINE + GAME_RESULT_MESSAGE);
        System.out
            .printf(GAME_RESULT_FORMAT + NEWLINE, dealer.getName().getValue(), counts.get(0),
                counts.get(1), counts.get(2));
    }

 

 

단순히 출력 형식을 만들어 주는 것이 아닌, 딜러와 플레이어의 데이터를 추가적으로 가공하여 새로운 자료형에 대입하는 것을 알 수 있습니다. 저는 이 부분이나 전반적인 GameResult의 로직은 BlackjackGame 객체에 들어가야겠다고 판단하였고, 아래와 같이 BlackjackGame 객체를 정의하였습니다.

 

 

public class BlackjackGame {

    public GameResult createGameResult(final Participants participants) {
        final Participant dealer = participants.getDealer();
        final List<Participant> players = participants.getPlayers();
        final List<Integer> dealerCounts = makeDealerMatchCounts(dealer, players);
        final Map<Name, Result> playerResults = makePlayerResults(players, dealer);
        return new GameResult(dealerCounts, playerResults);
    }

    public List<Integer> makeDealerMatchCounts(final Participant dealer,
        final List<Participant> players) {
        final List<Result> dealerResults = Arrays.stream(Result.values())
            .collect(Collectors.toList());

        return dealerResults.stream()
            .map(result -> calculateDealerResult(dealer, players, result))
            .collect(Collectors.toList());
    }

    public int calculateDealerResult(final Participant dealer, final List<Participant> players,
        final Result result) {
        return (int) players.stream()
            .filter(player -> dealer.decideWinner(player).isSameResult(result))
            .count();
    }

    public Map<Name, Result> makePlayerResults(final List<Participant> players,
        final Participant dealer) {
        final Map<Name, Result> results = new LinkedHashMap<>();
        for (final Participant player : players) {
            final Result result = player.decideWinner(dealer);
            results.put(player.getName(), result);
        }
        return results;
    }

}

 

 

원래 있던 GameResult의 로직을 싹다 옮기고, 뷰에서 데이터를 가공하던 로직도 이쪽으로 이동시켰습니다. 그리고 BlackjackGame은 GameResult를 생성하여 반환하는 메소드를 정의하였습니다.

 

 

public class GameResult {
    private final List<Integer> dealerCounts;
    private final Map<Name, Result> playerResults;

    public GameResult(final List<Integer> dealerCounts, final Map<Name, Result> playerResults) {
        this.dealerCounts = new ArrayList<>(dealerCounts);
        this.playerResults = new LinkedHashMap<>(playerResults);
    }

    public List<Integer> getDealerCounts() {
        return dealerCounts;
    }

    public Map<Name, Result> getPlayerResults() {
        return playerResults;
    }
}

 

 

그래서 GameResult는 위와 같이 getter 메소드만 존재하도록 수정되었습니다. 이를 통해, 컨트롤러와 뷰의 부담이 동시에 줄어드는 이점을 얻을 수 있었습니다.

 

 

정리

오늘은 블랙잭 2단계 미션까지 어느 정도 끝내자고 계획하였으나, 면담이나 프로필 사진을 찍는 등의 일로 생각보다 많이 개발을 진행하지는 못하였습니다. 하지만, 상태 패턴이라는 것을 알게 되었고, 1단계 미션의 2차 피드백까지는 잘 수행한 점은 의미가 있다고 생각합니다. 내일은 2단계 미션을 끝내고, 디자인 패턴을 공부하려고 합니다.

 

 

위 미션의 코드는 이곳에서 확인하실 수 있습니다.

댓글

추천 글