-
Notifications
You must be signed in to change notification settings - Fork 0
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
Dazzle 블랙잭 2단계 #14
base: woo-chang
Are you sure you want to change the base?
Dazzle 블랙잭 2단계 #14
Conversation
* docs: 요구사항 명세 작성 * feat: 이름의 길이 검증 기능 구현 * feat: 금지된 이름 검증 기능 구현 * docs: 기능 구현 목록 수정 Co-authored-by: woo-chang <[email protected]> * feat: 이름 도메인 생성 Co-authored-by: woo-chang <[email protected]> * feat: 문양 도메인 생성 Co-authored-by: woo-chang <[email protected]> * feat: 숫자 도메인 생성 Co-authored-by: woo-chang <[email protected]> * feat: 문양 이름 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 숫자 이름 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 점수 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 점수 계산 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 에이스인지 확인하는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 점수 합계 계산 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 점수 최댓값 초과 여부 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 이름 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 블랙잭 여부 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * fix: 메서드명 수정 및 잘못된 로직 수정 Co-authored-by: woo-chang <[email protected]> * feat: 카드 추가 여부 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 카드 추가 기능 구현 Co-authored-by: woo-chang <[email protected]> * chore: 테스트 어노테이션 추가 Co-authored-by: woo-chang <[email protected]> * feat: 카드를 받는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 점수 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 개수 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 카드 추가 여부 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 점수 확인 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 카드를 받는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 딜러 도메인 생성 Co-authored-by: woo-chang <[email protected]> * feat: 참가자 도메인 생성 Co-authored-by: woo-chang <[email protected]> * feat: 딜러와 플레이어가 참가자 상속 Co-authored-by: woo-chang <[email protected]> * feat: 플레이어의 이름 중복 검증 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 참가자 인원 검증 기능 구현 Co-authored-by: woo-chang <[email protected]> * refactor: 외부 참조 끊도록 수정 Co-authored-by: woo-chang <[email protected]> * feat: 카드를 뽑는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 덱 상태 검증 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 덱 섞는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 덱 팩토리 도메인 생성 Co-authored-by: woo-chang <[email protected]> * chore: 패키지 분리 및 import 최적화 Co-authored-by: woo-chang <[email protected]> * feat: 문자열 파싱 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 문자열 앞뒤 공백 제거 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 플레이어 이름 목록 입력 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 카드 받을 여부 입력 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 참가자들의 카드 현황 출력 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 딜러 카드 추가 여부 출력 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 최종 결과 출력 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 최종 승패 출력 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 빈 생성자로 생성될 수 있는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: Cards 도메인에 대한 DTO 생성 Co-authored-by: woo-chang <[email protected]> * feat: 딜러 상태에 대한 DTO 생성 Co-authored-by: woo-chang <[email protected]> * feat: 참가자에 대한 DTO 생성 Co-authored-by: woo-chang <[email protected]> * feat: 플레이어 결과에 대한 DTO 생성 Co-authored-by: woo-chang <[email protected]> * feat: 결과에 대한 열거형 도메인 생성 Co-authored-by: woo-chang <[email protected]> * feat: 점수에 대한 도메인 생성 Co-authored-by: woo-chang <[email protected]> * feat: 참가자들이 카드를 뽑는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 참가자들 중 딜러와 플레이어를 찾는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 이름으로만 생성될 수 있는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 덱에서 카드를 뽑아 참가자들에게 나눠주는 기능 구현 Co-authored-by: woo-chang <[email protected]> * feat: 블랙잭 게임 실행 기능 구현 Co-authored-by: woo-chang <[email protected]> * fix: 게임 결과 로직 수정 Co-authored-by: woo-chang <[email protected]> * refactor: TRUMP는 덱이 알도록 수정 * refactor: 입력 기능 가독성 위해 메서드명 수정 * refactor: 축약하지 않은 변수명으로 수정 * refactor: 딜러가 카드를 추가로 뽑을 수 있는 점수는 딜러가 알도록 수정 * refactor: ACE -> Ace 일관성있는 표현으로 수정 * refactor: 테스트 목적을 명확히하도록 수정 * refactor: 계층 구조 테스트로 의미를 명확하게 전달하도록 수정 * refactor: 자바 컨벤션에 따라 메서드명 수정 * refactor: 카드 뽑을 때 검증하도록 수정 * refactor: NPE 방지 및 변수, 메서드명 수정 * refactor: 참가자에게 딜러 여부에 대한 메시지를 던지도록 수정 * refactor: 거짓 성공을 막기위해 검증부에는 하드코딩 하도록 수정 * refactor: TRUMP 생성 시 flatMap 사용 및 덱 생성 시 섞도록 수정 * refactor: 플레이어 이름을 명시하도록 Name -> PlayerName 수정 * refactor: 참여자 목록 생성 책임을 생성자로 수정 * refactor: Deck 생성 책임은 Deck이 가지도록 수정 * refactor: 블랙잭 게임 컨트롤러 수정 * refactor: 딜러 승패 여부 확인 로직 수정 * refactor: 카드 목록에서 사용되지 않는 메서드 제거 * refactor: 딜러가 결과 확인하는 로직 수정 * test: 테스트하지 못했던 코드에 대한 테스트 코드 작성 * feat: 제네릭 미션 구현 --------- Co-authored-by: kokodak <[email protected]>
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.
같이 객체지향을 고민해 보아요 👍
final BlackJackGame blackJackGame = createBlackJackGame(); | ||
initialGame(blackJackGame); | ||
|
||
drawCardsForPlayers(blackJackGame); | ||
drawCardForDealer(blackJackGame); | ||
|
||
printResult(blackJackGame); |
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.
추상화 기준이 깔끔해서 구조를 이해하기 쉬웠어 👍
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.
허브 의견에 동의 합니다 굿굿
private static final int TRUMP_COUNT = 1; | ||
private static final int INITIAL_DRAW_COUNT = 2; | ||
private static final int BLACK_JACK_SCORE = 21; | ||
private static final double BLACK_JACK_BONUS_RATE = 1.5; |
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.
다른 ratio의 경우 결과에 위치하는데 이 부분만 BlackjackGame에 있는게 어색한 것 같아
BLACKJACK_WIN이라는 enum을 추가해보는건 어떨까?
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.
처음에는 이기는 상황이 2개라 어색하다고 판단했는데, 블랙잭이라는 특수한 경우이기 때문에 결과를 나누는 것도 좋은 방법인 것 같습니다. 좋은 리뷰 감사합니다!
private static final double BLACK_JACK_BONUS_RATE = 1.5; | ||
|
||
private final Participants participants; | ||
private final Deck deck; |
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.
요구사항을 지켜야하지 않을 명확한 이유가 없다면 나는 요구사항을 지키는게 연습에 도움이 된다고 생각해
Deck을 static으로 가져와서 사용해도 큰 문제가 없을 것 같다고 생각하는데, 다즐은 어떻게 생각해?
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.
요구사항을 잘 지키도록 연습하는 것 중요하다고 생각합니다! static
사용을 고려해 보았으나 도입하지 않은 이유는 아래와 같습니다.
Deck
은 카드를 뽑을 때마다 내부 상태가 변하기에 static
으로 선언해서 어디서든 사용할 수 있게 되어버리면, 내부 상태를 예측할 수 없게 되어버려서 사용하지 않았습니다!
허브는 static
메서드를 언제 사용해야한다고 생각하는지 궁금합니다 🌿
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.
내부 상태를 예측가능하다는 것은 BlackjackGame이 덱을 관리하는 부분에 대한 이야기겠지?
랜덤한 상태를 가지고 있는 덱의 내부 상태를 예측할 수 없는건 지금도 마찬가지라고 생각되고(필드로 관리하고 있긴 하지만) 현재의 상황에서 싱글톤 형태의 덱을 BlackjackGame만 static 메서드로 가져와서 사용하는거랑 큰 차이를 느끼지 못할 것 같아.
내 개인적인 생각이지만 BlackjackGame이 Deck을 생성하고 관리하는 느낌을 가질 수 있다는 장점이 있지만
테스트도 힘든 것 같다고 느껴져서, 필드를 3개로 사용하려면 덱 자체를 DI 받는건 어떻게 생각해?
static은 유틸리티 메서드? 정적 팩터리 메서드?
public int getDealerProfit() { | ||
final List<PlayerName> playerNames = participants.getPlayerNames(); | ||
final int playersProfit = playerNames.stream() | ||
.mapToInt(this::getPlayerProfit) | ||
.sum(); | ||
return -playersProfit; | ||
} |
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.
BettingTable에게 위임하는건 어때?
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.
이 부분도 고려해 보았습니다! 도입하지 않은 이유는 아래와 같습니다.
위임하기 위해서는 BettingTable
이 각 플레이어들의 승부 결과를 알야야하는데, 이는 BlackJackGame
이 알아야하는 정보라고 생각했습니다. 플레이어들의 정보를 Participants
로부터 받고 베팅 정보를 BettingTable
로부터 받아서 이를 취합해 이익을 계산하는 것은 BlackJackGame
의 역할이라고 생각합니다!
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.
나도 이 구조에서는 괜찮다고 생각해!
BettingTable이 승부 결과를 받아서 플레이어와 딜러의 이익을 계산하도록 책임을 가질 수 있는 방법도 괜찮을 것 같다는 이야기였어 👍
public class Betting { | ||
|
||
private static final int MINIMUM_BET = 100; | ||
private static final int MAXIMUM_BET = 1_000_000; |
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.
숫자 1_000_000 좋은데요? 나도 써먹어야지
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.
나도 써먹어야지
|
||
public Hand getHiddenHand() { | ||
final List<Card> cards = getHand().getCards(); | ||
return new Hand(cards.subList(0, cards.size() - 1)); |
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.
리스트를 새로 생성하지 않으려고 subList를 사용했나보구나
cards.size() - 1
보다 1을 상수로 사용해보는건 어때?
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.
마지막 장을 보여주지 않는다는 것을 표현하려고 했는데 1
로 변경하는게 좋을까요 🤔
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.
카드 사이즈에서 - 1 한 리스트를 만든다는게 이해하기 어려웠어
public List<PlayerName> getPlayerNames() { | ||
return participants.stream() | ||
.filter(participant -> !participant.isDealer()) | ||
.map(Player.class::cast) |
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.
cast에 대해서 고민을 많이 했는데 캐스팅이 OOP적이지 않은 느낌이 많이 들어서
캐스팅을 제거해보는건 어떨까?
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.
어떤 이유로 OOP
적이지 않은 느낌이 들었는지 들어보고 싶어요 :)
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.
cast를 해야한다면 추상화를 잘 못한게 아닐까 생각이 들었어! 내가 짠 코드도 그렇다고 생각되고
|
||
WIN("승", Betting::getValue), | ||
DRAW("무", profit -> 0), | ||
LOSE("패", profit -> profit.getValue() * -1); |
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.
승, 무, 패 name은 이제 필요없을 것 같아!
final Player player = new Player("toney"); | ||
player.drawCard(new Card(ACE, SPADE)); | ||
player.drawCard(new Card(QUEEN, SPADE)); | ||
final Participants participants = new Participants( | ||
new Dealer(), | ||
List.of(player, new Player("dazzle")) | ||
); | ||
final Map<PlayerName, Betting> betting = new HashMap<>(); | ||
betting.put(new PlayerName("toney"), new Betting(10000)); | ||
final BettingTable bettingTable = new BettingTable(betting); | ||
final BlackJackGame blackJackGame = new BlackJackGame(participants, bettingTable); |
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.
BlackjackGameTest니 BlackjackGame의 기능을 이용해 테스트 해보는건 어때?
void 카드를_받을_수_없는_상태라면_예외를_던진다() { | ||
final Dealer dealer = new Dealer(); | ||
dealer.drawCard(new Card(QUEEN, CLOVER)); | ||
dealer.drawCard(new Card(ACE, HEART)); |
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.
Fixture를 사용해서 중복을 제거해보는건 어때?
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.
아 허브가 이미 언급했군요. 밑에 있어서 못봤삼 ><
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.
늦어서 죄송해요,,,,, 하지만 늦은만큼 열심히 달았습니다ㅎㅎㅎ
p.s. 다즐 코드 너무 깔끔해서 좋아요. 뭔가 마음이 편안~~해져요!!!
final BlackJackGame blackJackGame = createBlackJackGame(); | ||
initialGame(blackJackGame); | ||
|
||
drawCardsForPlayers(blackJackGame); | ||
drawCardForDealer(blackJackGame); | ||
|
||
printResult(blackJackGame); |
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.
허브 의견에 동의 합니다 굿굿
} | ||
|
||
private BlackJackGame createBlackJackGame() { | ||
final Participants participants = new Participants(new Dealer(), gatherPlayers()); |
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.
Participants 생성자에 dealer와 player를 따로 넣어주는 방식 좋네요!!
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.
근데 제가 못 찾은 것일수도 있는데 Participants안의 validate에서 예외를 던져주는데 해당 예외들에 대한 핸들링이 이루어지지 않고 있는것 같네요..?!
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.
이번 미션에서는 예외가 발생했을 때 올바르지 않은 상황으로 판단하여 예외 처리를 하지 않았습니다 :)
public class Betting { | ||
|
||
private static final int MINIMUM_BET = 100; | ||
private static final int MAXIMUM_BET = 1_000_000; |
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.
나도 써먹어야지
public static ParticipantResponse ofDealerWithHidden(final BlackJackGame blackJackGame) { | ||
final Hand hand = blackJackGame.getDealerHiddenHand(); | ||
return new ParticipantResponse(blackJackGame.getDealerName(), CardsResponse.of(HIDDEN_SCORE, hand)); | ||
} |
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.
dto에 정적팩토리메소드 여러개둔거 인상깊네요!!
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.
dto
도 컨트롤러 레이어에 속하므로 컨트롤러에서 변환하는 로직을 dto
의 역할로 위임하였습니다!
participants.add(ParticipantResultResponse.ofDealer(blackJackGame)); | ||
participants.addAll(listOfPlayers(blackJackGame)); | ||
return participants; | ||
} |
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.
다즐 dto를 참 효율적으로 잘 쓰는 것 같아요. 멋집니다 👍
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.
정적팩토리메소드명도 너무 찰떡
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.
dto
를 꼼꼼히 작성하려고 노력했는데 알아봐주셔서 감사합니다~
@Override | ||
public String toString() { | ||
return symbol; | ||
} |
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.
state는 getState로 가져오고, symbol은 toString을 오버라이드한 이유는 먼가요??
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.
테스트, 디버깅에 toString
을 사용하지만 출력에 용이하게 하기 위해 사용했습니다 👾
|
||
blackJackGame.initialDraw(); | ||
|
||
assertAll( |
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.
박스터가 좋아하는 assertAll 발견 ㅋㅋㅋㅋㅋㅋㅋ
@Test | ||
void 딜러에게_진경우_베팅금액만큼_잃는다() { | ||
final Dealer dealer = new Dealer(); | ||
dealer.drawCard(new Card(TEN, HEART)); |
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.
(이것도 제 리뷰어께서 언급한 내용)
이번 미션 같은 경우에는 Card
가 많이 사용되는데 계속 만들어주기 번거로우니까 TestFixture를 써보는건 어떨까요??
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.
너무 좋은데요 👍
void 카드를_받을_수_없는_상태라면_예외를_던진다() { | ||
final Dealer dealer = new Dealer(); | ||
dealer.drawCard(new Card(QUEEN, CLOVER)); | ||
dealer.drawCard(new Card(ACE, HEART)); |
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.
아 허브가 이미 언급했군요. 밑에 있어서 못봤삼 ><
@@ -0,0 +1,25 @@ | |||
## 제네릭 이해하기 |
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.
다즐은 참 부지런하군요 .. 나는 이거 언제하지 ㅎㅎㅎ.. 이번주안에는 꼭..
객체지향의 길은 멀고도 험한 것 같습니다 😂
부족한 코드지만 리뷰를 통해 많이 배워가도록 하겠습니다 .. !