-
Notifications
You must be signed in to change notification settings - Fork 6
[블랙잭] 레몽(이규명) 미션 제출합니다. #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: lgm1007
Are you sure you want to change the base?
Changes from all commits
ab35e08
75f23cb
1dd9777
efe67af
414858b
a291a12
fa3d675
0d620eb
eff7337
94efede
778c323
c4d9413
2d7cb6d
a1efa10
b37874e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| ## 기능 요구사항 | ||
| * 사용자에게 블랙잭 게임에 참여할 플레이어를 입력받는다. | ||
| * 블랙잭 게임의 참가자는 딜러 + 플레이어이다. | ||
| * 게임 처음에는 게임의 참가자들은 카드덱에서 무작위로 카드 2장을 받는다. | ||
| * 카드덱은 하트, 클로버, 스페이드, 다이아몬드 4개의 모양이 있고 각각 ACE, 2~9, KING, QUEEN, JACK이 있다. | ||
| * ACE는 1또는 11로 계산할 수 있고 (합계가 21이 넘으면 1로 계산, 아니면 11), KING, QUEEN, JACK은 각각 10으로 계산한다. | ||
| * 플레이어는 처음에 받은 두 장의 카드의 숫자 합계가 21을 넘지 않으면 얼마든지 카드를 더 받을 수 있다. | ||
| * 딜러는 처음에 받은 카드 2장의 합계가 16이하라면 반드시 1장의 카드를 추가로 받아야 하고, 17점 이상이면 추가로 받을 수 없다. | ||
| * 21이 초과된 플레이어는 무조건 패배한다. | ||
| * 21에 가장 가까운 플레이어가 승리한다. | ||
| * 게임을 완료한 후 각 플레이어별로 승패를 출력한다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import game.controller.GameController; | ||
| import view.InputView; | ||
| import view.OutputView; | ||
|
|
||
| public class Application { | ||
| public static void main(String[] args) { | ||
| GameController gameController = new GameController(new InputView(), new OutputView()); | ||
| gameController.run(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package card.controller; | ||
|
|
||
| public enum DrawCard { | ||
| y, | ||
| n; | ||
|
|
||
| public boolean isY() { | ||
| return this == y; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package card.controller; | ||
|
|
||
| import card.validator.DrawCardInputValidator; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class DrawCardRequest { | ||
| private static final List<String> DRAW_YES = List.of("y", "Y"); | ||
| public final DrawCard drawCard; | ||
|
|
||
| private DrawCardRequest(final DrawCard drawCard) { | ||
| this.drawCard = drawCard; | ||
| } | ||
|
|
||
| public static DrawCardRequest from(final String input) { | ||
| DrawCardInputValidator.validate(input); | ||
| return new DrawCardRequest(formattedDrawCardInput(input)); | ||
| } | ||
|
|
||
| private static DrawCard formattedDrawCardInput(final String input) { | ||
| if (DRAW_YES.contains(input)) { | ||
| return DrawCard.y; | ||
| } | ||
|
|
||
| return DrawCard.n; | ||
| } | ||
|
|
||
| public boolean isNotDrawCard() { | ||
| return !this.drawCard.isY(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package card.model; | ||
|
|
||
| public record Card ( | ||
| CardSuit suit, | ||
| CardRank rank | ||
| ) { | ||
| @Override | ||
| public String toString() { | ||
| return "%s%s".formatted(rank.getRank(), suit.getName()); | ||
| } | ||
|
Comment on lines
+1
to
+10
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 모델이 UI(뷰)로직에 의존하고 있어요.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네! 해당 리뷰를 보고 |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package card.model; | ||
|
|
||
| import java.util.*; | ||
|
|
||
| public class CardDeck { | ||
| private static final List<CardSuit> CARD_EMBLEMS = List.of(CardSuit.CLOVER, CardSuit.HEART, CardSuit.SPADE, CardSuit.DIAMOND); | ||
| private static final List<CardRank> CARD_NUMBER = List.of(CardRank.ACE, CardRank.TWO, CardRank.THREE, CardRank.FOUR, CardRank.FIVE, CardRank.SIX, CardRank.SEVEN, CardRank.EIGHT, CardRank.NINE, CardRank.JACK, CardRank.QUEEN, CardRank.KING); | ||
|
Comment on lines
+6
to
+7
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 엇 이 부분은 처음에 카드 문양을 EMBLEM, 숫자를 NUMBER로 네이밍했었습니다만,
Comment on lines
+6
to
+7
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CardSuit, CardRank 에 이미 모든 카드 문양과 카드 숫자가 잘 정의 되어있어서,
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아하 |
||
|
|
||
| private final Deque<Card> cards; | ||
|
|
||
| public CardDeck() { | ||
| List<Card> cardList = new ArrayList<>(); | ||
| for (CardSuit emblem : CARD_EMBLEMS) { | ||
| cardList.addAll(CARD_NUMBER.stream() | ||
| .map(cardRank -> new Card(emblem, cardRank)) | ||
| .toList()); | ||
| } | ||
| Collections.shuffle(cardList); | ||
| this.cards = new ArrayDeque<>(cardList); | ||
| } | ||
|
|
||
| public Card pickCard() { | ||
| return this.cards.pollFirst(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package card.model; | ||
|
|
||
| public enum CardRank { | ||
| ACE(1, "A"), | ||
| TWO(2, "2"), | ||
| THREE(3, "3"), | ||
| FOUR(4, "4"), | ||
| FIVE(5, "5"), | ||
| SIX(6, "6"), | ||
| SEVEN(7, "7"), | ||
| EIGHT(8, "8"), | ||
| NINE(9, "9"), | ||
| JACK(10, "J"), | ||
| QUEEN(10, "Q"), | ||
| KING(10, "K"); | ||
|
|
||
| private final int score; | ||
| private final String rank; | ||
|
|
||
| CardRank(final int score, final String rank) { | ||
| this.score = score; | ||
| this.rank = rank; | ||
| } | ||
|
|
||
| public int getScore() { | ||
| return this.score; | ||
| } | ||
|
|
||
| public String getRank() { | ||
| return this.rank; | ||
| } | ||
|
|
||
| public boolean isAce() { | ||
| return this == ACE; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package card.model; | ||
|
|
||
| public enum CardSuit { | ||
| CLOVER("클로버"), | ||
| HEART("하트"), | ||
| SPADE("스페이드"), | ||
| DIAMOND("다이아몬드"); | ||
|
|
||
| private final String name; | ||
|
|
||
| CardSuit(final String name) { | ||
| this.name = name; | ||
| } | ||
|
|
||
| public String getName() { | ||
| return this.name; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package card.validator; | ||
|
|
||
| public class DrawCardInputValidator { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정적 유틸 클래스를 만들 때는 실수로 인스턴스 생성을 하지 않도록 유의해주세요! |
||
| public static void validate(final String drawCardInput) { | ||
| if (drawCardInput == null || drawCardInput.isBlank()) { | ||
| throw new IllegalArgumentException("카드를 더 뽑을지 y 또는 n을 입력해주세요."); | ||
| } | ||
| } | ||
|
Comment on lines
+3
to
+8
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. drawCardInput 에 대한 단순 empty string 검사하는 로직을 별도 클래스로 추출하다보니, drawCard에 관한 로직이 산재되어 응집도가 떨어진다고 느꼈어요. DrawCardRequest와 이 로직이 같이 있으면 더 자연스러울 것 같아요 :)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네 validator에 단순 문자열이 비어있는지 검사하는 로직만 있다보니 그렇게 느껴졌을 것 같아요! |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| package game.controller; | ||
|
|
||
| import card.model.CardDeck; | ||
| import card.controller.DrawCardRequest; | ||
| import game.domain.GameJudgement; | ||
| import participant.controller.ParticipantRequest; | ||
| import participant.domain.ParticipantRegister; | ||
| import participant.model.Participant; | ||
| import view.InputView; | ||
| import view.OutputView; | ||
|
|
||
| import java.util.List; | ||
| import java.util.stream.IntStream; | ||
|
|
||
| public class GameController { | ||
| private static final int FIRST_CARD_COUNT = 2; | ||
| private static final int DEALER_DRAW_CARD_SCORE = 16; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 16이라는 숫자가 하한인지, 상한인지 상수명을 통해 더 명확히 드러내면 가독성을 더 챙길 수 있을 것 같아요 :) |
||
|
|
||
| private final InputView inputView; | ||
| private final OutputView outputView; | ||
|
|
||
| private final CardDeck cardDeck = new CardDeck(); | ||
|
|
||
| public GameController(final InputView inputView, final OutputView outputView) { | ||
| this.inputView = inputView; | ||
| this.outputView = outputView; | ||
| } | ||
|
|
||
| public void run() { | ||
| List<Participant> participants = fetchParticipants(); | ||
| firstDrawCards(participants); | ||
| drawCardsWithoutDealer(participants); | ||
| drawCardDealer(participants.stream() | ||
| .filter(Participant::isDealer) | ||
| .findAny() | ||
| .orElseThrow(() -> new IllegalArgumentException("게임에 딜러가 존재하지 않습니다.")) | ||
| ); | ||
|
Comment on lines
+33
to
+37
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. drawCardDealer를 호출할 때마다 매번 dealer를 필터링해서 건네줘야하는 구조에요. dealer가 아닌 participant를 파라미터로 넘기기 쉬운 구조이기 때문에, 실수하기 쉽고 버그를 유발하기 좋은 구조에 해당해요. |
||
|
|
||
| this.outputView.printFinalResult(participants); | ||
| this.outputView.printGameJudgement(new GameJudgement(participants)); | ||
| } | ||
|
|
||
| private List<Participant> fetchParticipants() { | ||
| ParticipantRequest participantRequest = this.inputView.inputParticipants(); | ||
| ParticipantRegister participantRegister = new ParticipantRegister(participantRequest); | ||
| return participantRegister.registerParticipants(); | ||
| } | ||
|
Comment on lines
+43
to
+47
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 참여자들을 초기화 시키는 과정인데, 네이밍은 '어딜 가서 가져와라' 라고 되어있어서 조금 어색하게 느껴졌어요. |
||
|
|
||
| private void firstDrawCards(List<Participant> participants) { | ||
| this.outputView.firstDistributeCard(participants); | ||
| for (Participant participant : participants) { | ||
| IntStream.range(0, FIRST_CARD_COUNT).forEach(it -> { | ||
| participant.addCard(this.cardDeck.pickCard()); | ||
| }); | ||
| } | ||
| this.outputView.printParticipantsCard(participants); | ||
| } | ||
|
Comment on lines
+49
to
+57
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 컨트롤러가 카드 덱에서 카드도 직접 뽑고, 참여자들에게 직접 카드를 추가하는 책임까지 갖고 있네요. |
||
|
|
||
| private void drawCardsWithoutDealer(List<Participant> participants) { | ||
| for (Participant participant : participants.stream() | ||
| .filter(participant -> !participant.isDealer()) | ||
| .toList()) { | ||
| choiceDrawCard(participant); | ||
| } | ||
| } | ||
|
|
||
| private void choiceDrawCard(Participant participant) { | ||
| while (true) { | ||
| DrawCardRequest drawCardRequest = this.inputView.inputDrawCard(participant); | ||
| if (drawCardRequest.isNotDrawCard()) break; | ||
|
|
||
| participant.addCard(this.cardDeck.pickCard()); | ||
| this.outputView.printParticipantCard(participant); | ||
| } | ||
| } | ||
|
|
||
| private void drawCardDealer(Participant participant) { | ||
| if (participant.calculateCurrentScore() <= DEALER_DRAW_CARD_SCORE) { | ||
| this.outputView.printDealerDrawCard(); | ||
| participant.addCard(this.cardDeck.pickCard()); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| package game.domain; | ||
|
|
||
| import participant.model.Participant; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class GameJudgement { | ||
| private static final String WIN_PARTICIPANT_MESSAGE = "%s: 승"; | ||
| private static final String LOSE_PARTICIPANT_MESSAGE = "%s: 패"; | ||
|
Comment on lines
+1
to
+10
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기도 도메인이 UI로직을 알고 있네요! |
||
|
|
||
| private final Participant dealer; | ||
| private final List<Participant> participantWithoutDealers = new ArrayList<>(); | ||
|
|
||
| public GameJudgement(final List<Participant> participants) { | ||
| this.dealer = participants.stream() | ||
| .filter(Participant::isDealer) | ||
| .findAny() | ||
| .orElseThrow(() -> new IllegalArgumentException("게임에 딜러가 존재하지 않습니다.")); | ||
| this.participantWithoutDealers.addAll(participants.stream() | ||
| .filter(participant -> !participant.isDealer()) | ||
| .toList() | ||
| ); | ||
| } | ||
|
Comment on lines
+12
to
+24
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 딜러와 딜러가 아닌 참가자를 구분하는 코드가 소스 전반적으로 자주 보여요. 실수 방지와 버그 유발을 낮추기 위해서, '딜러가 아닌 참가자'를 나타내는 값 객체를 등장시켜보면 어떨까 싶어요 :) |
||
|
|
||
| public String fetchDealerJudge() { | ||
| final int dealerScore = this.dealer.calculateCurrentScore(); | ||
| final String dealerJudgeMessage = "딜러: %d승 %d패"; | ||
| int winCount = 0; | ||
| int loseCount = 0; | ||
|
|
||
| // 21점이 넘어가면 무조건 패배 - 참여자 수만큼 패배한 수로 세팅 | ||
| if (this.dealer.isOverWinningMaxScore()) { | ||
| loseCount = participantWithoutDealers.size(); | ||
| return dealerJudgeMessage.formatted(winCount, loseCount); | ||
| } | ||
|
|
||
| winCount = fetchDealerWinningCount(dealerScore); | ||
| loseCount = fetchDealerLoseCount(dealerScore); | ||
|
|
||
| return dealerJudgeMessage.formatted(winCount, loseCount); | ||
| } | ||
|
|
||
| private int fetchDealerWinningCount(final int dealerScore) { | ||
| int winCount; | ||
| winCount = participantWithoutDealers.stream() | ||
| .map(Participant::calculateCurrentScore) | ||
| .filter(participantScore -> dealerScore > participantScore) | ||
| .toList() | ||
| .size(); | ||
| return winCount; | ||
| } | ||
|
|
||
| private int fetchDealerLoseCount(final int dealerScore) { | ||
| return participantWithoutDealers.stream() | ||
| .map(Participant::calculateCurrentScore) | ||
| .filter(participantScore -> dealerScore < participantScore) | ||
| .toList() | ||
| .size(); | ||
| } | ||
|
|
||
| public List<String> fetchParticipantJudge() { | ||
| return participantWithoutDealers.stream() | ||
| .map(participant -> { | ||
| String loseMessage = LOSE_PARTICIPANT_MESSAGE.formatted(participant.getName()); | ||
| if (participant.isOverWinningMaxScore()) { | ||
| return loseMessage; | ||
| } | ||
|
|
||
| int participantScore = participant.calculateCurrentScore(); | ||
| if (participantWithoutDealers.stream() | ||
| .filter(p -> !(p.getName().equals(participant.getName()) || | ||
| p.isOverWinningMaxScore())) | ||
| .allMatch(innerParticipant -> participantScore > innerParticipant.calculateCurrentScore())) { | ||
| return WIN_PARTICIPANT_MESSAGE.formatted(participant.getName()); | ||
| } | ||
|
|
||
| return loseMessage; | ||
| }) | ||
| .toList(); | ||
| } | ||
|
Comment on lines
+62
to
+81
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. stream 안에 if 문이 중첩되고, 조건식 자체에 stream이 사용되어 있어서 이 메서드 로직을 파악하기가 많이 어려워요. 의미 있는 단위로 이름을 붙여서 가독성을 더 챙겨보면 좋을 것 같아요! |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package participant.controller; | ||
|
|
||
| import participant.validator.ParticipantInputValidator; | ||
| import utils.SplitUtils; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| public class ParticipantRequest { | ||
| private static final String SPLIT_DELIMITER = ","; | ||
|
|
||
| private final List<String> participantNames; | ||
|
|
||
| private ParticipantRequest(final List<String> participantNames) { | ||
| this.participantNames = participantNames; | ||
| } | ||
|
|
||
| public static ParticipantRequest from(final String participantInput) { | ||
| String trimmedInput = participantInput.replaceAll(" ", ""); | ||
| ParticipantInputValidator.validate(trimmedInput, SPLIT_DELIMITER); | ||
| final String[] splitInput = SplitUtils.split(trimmedInput, SPLIT_DELIMITER); | ||
| return new ParticipantRequest(Arrays.asList(splitInput)); | ||
| } | ||
|
|
||
| public List<String> getParticipantNames() { | ||
| return List.copyOf(participantNames); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package participant.domain; | ||
|
|
||
| import participant.controller.ParticipantRequest; | ||
| import participant.model.Participant; | ||
|
|
||
| import java.util.Comparator; | ||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class ParticipantRegister { | ||
| private static final String DEALER = "딜러"; | ||
|
|
||
| private final ParticipantRequest participantRequest; | ||
|
|
||
| public ParticipantRegister(final ParticipantRequest participantRequest) { | ||
| this.participantRequest = participantRequest; | ||
| } | ||
|
|
||
| public List<Participant> registerParticipants() { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 참여자를 '등록' 시키는 메서드가 실제로 어딘가에 '등록' 시킨다기보다, 단순히 참여자 이름을 통해 Participant 객체를 생성해서 리턴하는 걸로 보여요. (물론 이 과정 자체를 '등록'이란 과정으로 추상화를 하신 것 같기도 합니다.) 이런 로직이라면 |
||
| List<Participant> participants = participantRequest.getParticipantNames().stream() | ||
| .map(Participant::new) | ||
| .collect(Collectors.toList()); | ||
|
|
||
| participants.add(new Participant(DEALER)); | ||
|
|
||
| // 참여자 리스트 순서 정렬 - 딜러가 앞에 오도록 정렬 | ||
| return participants.stream() | ||
| .sorted(Comparator.comparing(Participant::getName).reversed()) | ||
| .collect(Collectors.toList()); | ||
|
Comment on lines
+26
to
+29
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (오늘 리뷰 중 가장 중요하게 생각하는 리뷰에요) ⭐️ 리스트에 저장된 순서에 따라서 누가 딜러인지, 누가 플레이어인지 정하고 있어요. 소스 전반적으로 딜러와 플레이어를 구분하는 로직이 여러 곳에 걸쳐 등장하고, 이에 따라 실수하기 쉬운 구조가 계속 만들어지는데, 저는 이것이 딜러와 플레이어 구분없이 Participant 하나로 설계를 하는 것에서 비롯한 비용이라고 생각해요.
딜러/플레이어를 체크하는 메서드를 둔다는 것은, 이 메서드의 구현을 항상 살펴봐야한다는 것이고(위 메서드도 이 예에 해당하죠.), 이는 곧 개발자가 직접, 지속적으로 신경써야하는 인지 부하 비용을 항상 떠안게 되게 됩니다.
딜러가 게임의 참가자라고 해서, 플레이어와 구분될 필요가 없는지, 구분해서 얻을 수 있는 장단점은 무엇이고 구분하지 않아서 생기는 장단점은 무엇인지 고민해보시면 좋을 것 같습니다 :D (앞으로 역할 관점에서 객체를 설계할 때 많이 도움될 거에요!)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 맞습니다. 사실 이번 미션에 딜러와 플레이어 간 발생하는 로직을 중복되지 않게 처리하기 위해 딜러와 플레이어를 같은 Participant로 구분하게 되었는데, 중복이 발생하지 않도록 하기 위한 조치가 복잡한 구조를 만들어버리는 아이러니에 빠져버렸죠. 게임의 로직을 생각해보면 딜러와 플레이어 간 동일한 동작은 결국 1. 게임 시작 시 두 장의 카드를 받는 것 2. 가지고 있는 카드의 점수 계산 2가지 뿐이었고, 그렇다면 이 두 가지 동작만 중복되지 않게 처리했다면 지금보다 덜 신경써도 되는 구조가 되지 않았을까 생각이 듭니다. 개발하면서도 가장 고민하던 부분이었는데, 역시나 잘 캐치하셔서 좋은 리뷰 남겨주신 점 감사합니다!😄 |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이미 DrawCard enum에 'y' 가 잘 정의되어있어서 상수로 추가로 더 정의해주는 것은 중복으로 보여요. enum.name()과 String.equalsIgnoreCase 를 활용해서 중복을 없애봐도 좋을 것 같습니다 :)