Skip to content
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

[블랙잭 1단계] 타마 미션 제출합니다. #112

Open
wants to merge 30 commits into
base: etama123
Choose a base branch
from

Conversation

etama123
Copy link

@etama123 etama123 commented Mar 7, 2025

셀프 체크리스트

  • 프로그램이 정상적으로 작동하는가?
  • 모든 테스트가 통과하는가?
  • 이전에 받은 피드백을 모두 반영하였는가?
  • 코딩 스타일 가이드를 준수하였는가?
    • IDE 코드 자동 정렬을 적용하였는가?
    • 린트 검사를 통과하였는가?
  • 프로그래밍 요구 사항을 준수하였는가?
  • README.md에 기능 목록을 정리하고 명확히 기술하였는가?

어떤 부분에 집중하여 리뷰해야 할까요?

크롱, 안녕하세요! 🦖
안드로이드 크루 타마입니다. 이번 리뷰 잘 부탁드립니다!

  • 프로그램 내부 로직 구현에 집중하다 보니, 아직 예외 처리까지 신경 쓰지 못했습니다.
    다음 피드백을 반영하기 전까지, 이번 PR에서 다루지 못한 예외 처리 부분도 보완해보려고 합니다.

또한, 궁금한 점들은 코드 내부에 남겨두었으니 참고 부탁드립니다! 감사합니다 ☺️

Comment on lines +7 to +11
fun getCard(deck: Deck) {
while (canHit()) {
addCard(deck.draw())
}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

블랙잭 게임에서 딜러는

  1. 딜러는 첫 번째 카드만 오픈하기 때문에
  2. hit / stay 여부를 외부에서 입력받지 않기 때문에
  3. 로직 자체에서 hit의 여부가 결정되기 때문에
    딜러 내부에서 카드를 뽑는 로직을 설정했습니다.

하지만 이처럼 카드를 미리 뽑아두는게, 현실 세계에서의 게임 진행과 다르기 때문에 괜찮을 까 의문이 들었어요. 해당 코드에 대한 크롱의 생각이 궁금합니다 !

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

카드를 미리 뽑아둔다는 말을 이해하지 못했는데, 더 자세하게 설명해주시면 이야기를 나눠볼 수 있을 것 같아요.

이와는 별개로 현실 세계의 블랙잭 딜러랑 객체 딜러가 어떤 차이가 있는지 잘 생각해보면 좋겠어요 🤠
현실에서는 딜러가 가지고 있는 카드를 나눠주지만, 객체지향에서는 참가자와 마찬가지로 카드를 받는 존재로 볼 수 있습니다!

Comment on lines +4 to +5
val dealerResult = DealerResult()
private val playerResult: MutableList<PlayerResult> = mutableListOf()
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

결과를 저장하는 로직에서 Dealer와 Player 모두 같은 Participant이므로, 결과도 비슷한 형태로 저장할 수 있지 않을까 고민했습니다.

현재 PlayerResult가 PlayerGameResultStatus를 가지는 것처럼, ResultParticipantGameResult를 가지는 방식으로 구조를 개선하는 것을 고민 중입니다.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PlayerResult의 설계 의도와 방향을 설명해주실 수 있을까요? 🤠

Comment on lines +9 to +14
fun GameResultStatus.toDisplayName(): String {
return when (this) {
GameResultStatus.PLAYER_WIN -> ""
GameResultStatus.PLAYER_LOSE -> ""
GameResultStatus.DRAW -> ""
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OutputView에서 원하는 형식으로 출력하기 위해, Rank와 Suit 같은 클래스에 확장 함수를 추가했습니다.

이 함수들은 View의 역할에 가깝다고도 볼 수 있지만, 동시에 각 Enum 클래스와 밀접한 관련이 있기 때문에 해당 클래스 아래에 위치하는 것이 가독성과 직관성 측면에서 더 적절하다고 생각합니다.

크롱은 어떻게 생각하시나요? 이 방식이 적절한지, 혹은 더 나은 방법이 있을지 의견이 궁금합니다! 😊

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

언급해주신 것처럼 View의 역할에 가까운 친구들로 보여요.
관련이 있는 enum클래스에 함께 작성하는 것과 OutputView에 작성하기 모두 장단점이 있어서 트레이드 오프의 영역이라고 볼 수 있어요.

현재의 구현 방식은 출력의 형태를 Win, Lose, Draw 로 변경하려 할 때 Domain역시 변경이 필요한데요.
이에 대해서도 고민해보면 좋을 것 같습니다.

그런데 이와는 별개로 꼭 확장 함수를 사용해야할까요? 🤔

Copy link

@krrong krrong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 타마, 만나서 반갑습니다 🤠
🃏미션 고생많으셨어요!

코멘트로 질문을 남겨주셔서 리뷰하는데 도움이 되었어요!
답변과 함께 고민해보면 좋을 부분들을 남겨두었으니 확인해주세요.

어려운 부분이나 의논이 필요한 부분은 언제든 dm이나 코멘트로 남겨주세요 🙇‍♂️

Comment on lines +8 to +10
override fun toString(): String {
return rank.toDisplayName() + suit.toDisplayName()
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toString을 오버라이드 한 이유에 대해 생각해보고 도메인에서 필요로 하는 것인가 고민해보면 좋겠어요 🤔

Comment on lines +5 to +6
class Deck(shuffledDeck: List<Card>) {
private val deck = LinkedList(shuffledDeck)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LinkedList...요? 🤔

abstract class Participant {
var totalSum: Int = 0
private set
val cards: MutableList<Card> = mutableListOf()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

카드들을 갖는 일급 컬렉션을 만들어볼까요? 어떤 장점을 얻을 수 있을까요? 🤔

Comment on lines +10 to +13
fun addCard(card: Card) {
cards.add(card)
totalSum = calculateTotalSum()
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addCard라는 메서드명을 보고 카드를 뽑겠구나라고 기대했지만 내부에서는 총합을 함께 계산하고 있어요.
하나의 함수가 하나의 일만 할 수 있도록 변경해볼까요 🤠

}

companion object {
const val BLACKJACK_LIMIT = 21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

21은 BUST의 기준! 으로 네이밍하는게 더 적절해 보이네요 🤠

Comment on lines +12 to +13
class DeckTest {
private val testDeck = Deck(Card.getAllCard())
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testDeck을 위처럼 선언하면 어떤 문제가 생길 수 있을까요? 🤔

Comment on lines +15 to +21
@Test
fun `카드를 뽑을 수 있다`() {
val original = testDeck.getSize()
testDeck.draw()
val change = testDeck.getSize()
assertThat(original - 1).isEqualTo(change)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트 코드의 가독성을 높이기 위한 전략으로 given when thenactualexpected를 사용하곤 하는데요.
이에 대해 한번 찾아보시고 반영해주세요 🤠 (모든 테스트 포함)

Comment on lines +30 to +37
@Test
fun `뽑은 카드는 덱에 존재하지 않는다`() {
val card1 = testDeck.draw()
assertThat(card1).isEqualTo(Card.of(Rank.ACE, Suit.SPADE))
repeat(51) {
assertThat(testDeck.draw()).isNotEqualTo(Card.of(Rank.ACE, Suit.SPADE))
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suit 혹은 Rank의 순서가 변경되면 어떻게 될까요? 🤔

Comment on lines +7 to +11
fun getCard(deck: Deck) {
while (canHit()) {
addCard(deck.draw())
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

카드를 미리 뽑아둔다는 말을 이해하지 못했는데, 더 자세하게 설명해주시면 이야기를 나눠볼 수 있을 것 같아요.

이와는 별개로 현실 세계의 블랙잭 딜러랑 객체 딜러가 어떤 차이가 있는지 잘 생각해보면 좋겠어요 🤠
현실에서는 딜러가 가지고 있는 카드를 나눠주지만, 객체지향에서는 참가자와 마찬가지로 카드를 받는 존재로 볼 수 있습니다!

Comment on lines +4 to +5
val dealerResult = DealerResult()
private val playerResult: MutableList<PlayerResult> = mutableListOf()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PlayerResult의 설계 의도와 방향을 설명해주실 수 있을까요? 🤠

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants