DevLog ๐Ÿ˜ถ

[์šฐํ…Œ์ฝ” 5๊ธฐ] ๋ธ”๋ž™์žญ ๊ตฌํ˜„ ๋ฏธ์…˜ ํšŒ๊ณ  ๋ณธ๋ฌธ

์šฐ์•„ํ•œํ…Œํฌ์ฝ”์Šค/๋ ˆ๋ฒจ 1

[์šฐํ…Œ์ฝ” 5๊ธฐ] ๋ธ”๋ž™์žญ ๊ตฌํ˜„ ๋ฏธ์…˜ ํšŒ๊ณ 

dolmeng2 2023. 4. 4. 11:43

์ง€ํ† ๋ž‘ ์ง„ํ–‰ํ•œ ์„ธ ๋ฒˆ์งธ ํŽ˜์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋‹ค. ์‚ฌ์‹ค ๋๋‚œ ์ง€ ํ•œ์ฐธ ๋์ง€๋งŒ... ๋’ค๋Šฆ๊ฒŒ ํšŒ๊ณ ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.
๋ธ”๋ž™์žญ๋ถ€ํ„ฐ ๋ฏธ์…˜์˜ ๋‚œ์ด๋„๊ฐ€ ํ™•์‹คํžˆ ๊นŒ๋‹ค๋กœ์›Œ์กŒ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค... ใ…Žใ…Ž ๊ทธ๋ž˜๋„ ๋ฐฐ์šด ๊ฒŒ ๋งŽ์•„์„œ ์ข‹๋‹ค.

 

โœ”๏ธ ์ž‘์„ฑํ•œ ์ฝ”๋“œ

GitHub - Cl8D/java-blackjack: ๋ธ”๋ž™์žญ ๋ฏธ์…˜ ์ €์žฅ์†Œ

๋ธ”๋ž™์žญ ๋ฏธ์…˜ ์ €์žฅ์†Œ. Contribute to Cl8D/java-blackjack development by creating an account on GitHub.

github.com

 

โœ”๏ธ 1์ฐจ PR

[1๋‹จ๊ณ„ - ๋ธ”๋ž™์žญ ๊ฒŒ์ž„ ์‹คํ–‰] ์ ธ๋‹ˆ(์ด์ง€์›) ๋ฏธ์…˜ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค. by Cl8D ยท Pull Request #452 ยท woowacourse/java-b

์•ˆ๋…•ํ•˜์„ธ์š”, ์ฝ”์ผ! ์šฐํ…Œ์ฝ” 5๊ธฐ ๋ฐฑ์—”๋“œ ํฌ๋ฃจ ์ ธ๋‹ˆ์ž…๋‹ˆ๋‹ค โ›„๏ธ ์ง€ํ† ์™€ ํ•จ๊ป˜ ์„ธ ๋ฒˆ์งธ ํŽ˜์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ํŽ˜์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์š”๊ตฌ์‚ฌํ•ญ์ด ๋ณต์žกํ•˜๊ณ , ์Šค์Šค๋กœ ์ƒ๊ฐํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„

github.com

 

โœ”๏ธ 2์ฐจ PR

[2๋‹จ๊ณ„ - ๋ธ”๋ž™์žญ(๋ฒ ํŒ…)] ์ ธ๋‹ˆ(์ด์ง€์›) ๋ฏธ์…˜ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค. by Cl8D ยท Pull Request #538 ยท woowacourse/java-blackja

์•ˆ๋…•ํ•˜์„ธ์š”, ์ฝ”์ผ! ์šฐ์„ , 1์ฐจ PR์—์„œ ์„œ๋กœ ์ด์•ผ๊ธฐ ์ฃผ๊ณ  ๋‚˜๋ˆด๋˜ ๋ถ€๋ถ„์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ์ฒจ๋ถ€ํ• ๊ฒŒ์š” ๐Ÿ˜Š ๐Ÿ’ฌ 1๋‹จ๊ณ„ ๋ฏธ์…˜ ๋‹ต๋ณ€ โœ”๏ธ ์ƒ์„ฑ์ž๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋‘๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ์‰ฌ์›Œ์ง„๋‹ค ๐Ÿ‘‰ ๋‹ต๋ณ€ โ†’ ์‚ฌ์‹ค ์ด๊ฑฐ

github.com

 

โœ”๏ธ ๊ธฐ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ

๋ธ”๋ž™์žญ ๊ฒŒ์ž„์„ ๋ณ€ํ˜•ํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ๊ตฌํ˜„ํ•œ๋‹ค. ๋ธ”๋ž™์žญ ๊ฒŒ์ž„์€ ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด ์ค‘ ์นด๋“œ์˜ ํ•ฉ์ด 21 ๋˜๋Š” 21์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ˆซ์ž๋ฅผ ๊ฐ€์ง€๋Š” ์ชฝ์ด ์ด๊ธฐ๋Š” ๊ฒŒ์ž„์ด๋‹ค. ํ”Œ๋ ˆ์ด์–ด๋Š” ๊ฒŒ์ž„์„ ์‹œ์ž‘ํ•  ๋•Œ ๋ฐฐํŒ… ๊ธˆ์•ก์„ ์ •ํ•ด์•ผ ํ•œ๋‹ค.
 
- ์นด๋“œ์˜ ์ˆซ์ž ๊ณ„์‚ฐ์€ ์นด๋“œ ์ˆซ์ž๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ํ•˜๋ฉฐ, ์˜ˆ์™ธ๋กœ Ace๋Š” 1 ๋˜๋Š” 11๋กœ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, King, Queen, Jack์€ ๊ฐ๊ฐ 10์œผ๋กœ ๊ณ„์‚ฐํ•œ๋‹ค.
- ๊ฒŒ์ž„์„ ์‹œ์ž‘ํ•˜๋ฉด ํ”Œ๋ ˆ์ด์–ด๋Š” ๋‘ ์žฅ์˜ ์นด๋“œ๋ฅผ ์ง€๊ธ‰ ๋ฐ›์œผ๋ฉฐ, ๋‘ ์žฅ์˜ ์นด๋“œ ์ˆซ์ž๋ฅผ ํ•ฉ์ณ 21์„ ์ดˆ๊ณผํ•˜์ง€ ์•Š์œผ๋ฉด์„œ 21์— ๊ฐ€๊น๊ฒŒ ๋งŒ๋“ค๋ฉด ์ด๊ธด๋‹ค. 21์„ ๋„˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์›ํ•œ๋‹ค๋ฉด ์–ผ๋งˆ๋“ ์ง€ ์นด๋“œ๋ฅผ ๊ณ„์† ๋ฝ‘์„ ์ˆ˜ ์žˆ๋‹ค. ๋‹จ, ์นด๋“œ๋ฅผ ์ถ”๊ฐ€๋กœ ๋ฝ‘์•„ 21์„ ์ดˆ๊ณผํ•  ๊ฒฝ์šฐ ๋ฐฐํŒ… ๊ธˆ์•ก์„ ๋ชจ๋‘ ์žƒ๊ฒŒ ๋œ๋‹ค.
- ์ฒ˜์Œ ๋‘ ์žฅ์˜ ์นด๋“œ ํ•ฉ์ด 21์ผ ๊ฒฝ์šฐ ๋ธ”๋ž™์žญ์ด ๋˜๋ฉด ๋ฒ ํŒ… ๊ธˆ์•ก์˜ 1.5 ๋ฐฐ๋ฅผ ๋”œ๋Ÿฌ์—๊ฒŒ ๋ฐ›๋Š”๋‹ค. ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๋ชจ๋‘ ๋™์‹œ์— ๋ธ”๋ž™์žญ์ธ ๊ฒฝ์šฐ ํ”Œ๋ ˆ์ด์–ด๋Š” ๋ฒ ํŒ…ํ•œ ๊ธˆ์•ก์„ ๋Œ๋ ค๋ฐ›๋Š”๋‹ค.
- ๋”œ๋Ÿฌ๋Š” ์ฒ˜์Œ์— ๋ฐ›์€ 2์žฅ์˜ ํ•ฉ๊ณ„๊ฐ€ 16์ดํ•˜์ด๋ฉด ๋ฐ˜๋“œ์‹œ 1์žฅ์˜ ์นด๋“œ๋ฅผ ์ถ”๊ฐ€๋กœ ๋ฐ›์•„์•ผ ํ•˜๊ณ , 17์  ์ด์ƒ์ด๋ฉด ์ถ”๊ฐ€๋กœ ๋ฐ›์„ ์ˆ˜ ์—†๋‹ค. ๋”œ๋Ÿฌ๊ฐ€ 21์„ ์ดˆ๊ณผํ•˜๋ฉด ๊ทธ ์‹œ์ ๊นŒ์ง€ ๋‚จ์•„ ์žˆ๋˜ ํ”Œ๋ ˆ์ด์–ด๋“ค์€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํŒจ์— ์ƒ๊ด€ ์—†์ด ์Šน๋ฆฌํ•ด ๋ฒ ํŒ… ๊ธˆ์•ก์„ ๋ฐ›๋Š”๋‹ค.
 


๋งˆ์ฐฌ๊ฐ€์ง€๋กœ PR ๋‚ด์šฉ ์ค‘์—์„œ ์ธ์ƒ ๊นŠ์—ˆ๋˜ ๊ฒƒ๋“ค์— ๋Œ€ํ•ด์„œ ์ ์–ด๋ณด๊ณ ์ž ํ•œ๋‹ค ๐Ÿซ 
 

๐Ÿ’ฌ stream์„ ์‚ฌ์šฉํ•˜๊ธฐ vs for๋ฌธ์œผ๋กœ ๋ถ„๋ฆฌํ•˜๊ธฐ

๋‹น์‹œ์— ๋ชจ๋˜ ์ž๋ฐ” ์Šคํ„ฐ๋””์—์„œ ๊ฝค๋‚˜ ๊ฐ๋ช…์„ ๋ฐ›์•˜๋˜ ๋‚˜๋Š”, ๋ธ”๋ž™์žญ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์นด๋“œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด flatMap์„ ์‚ฌ์šฉํ–ˆ์—ˆ๋‹ค.

private static List<Card> makeCards(final List<CardPattern> cardPatterns, final List<CardNumber> cardNumbers) {
        return cardPatterns.stream()
        .flatMap(pattern -> cardNumbers.stream()
        .map(number -> Card.create(pattern, number)))
        .collect(Collectors.toList());
}

์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ ์ดํ›„์—๋Š” ๊ฝค๋‚˜ ๊น”๋”ํ•œ ์ฝ”๋“œ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์—ˆ์ง€๋งŒ, ๋ฆฌ๋ทฐ์–ด๋‹˜์€ ์˜คํžˆ๋ ค ์ด๊ฒƒ๋ณด๋‹ค for๋ฌธ์„ ํ™œ์šฉํ•˜๋Š” ๊ฒŒ ๊ฐ€๋…์„ฑ ์ธก๋ฉด์—์„œ ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ๋ฆฌ๋ทฐ๋ฅผ ์ฃผ์…จ๋‹ค.
 
๊ทธ๋ž˜์„œ 2์ค‘ for๋ฌธ์„ ์‚ฌ์šฉํ•œ ๋ฐฉ๋ฒ• 2๊ฐ€์ง€๋ฅผ ๊ณ ๋ คํ•ด๋ณด์•˜๋‹ค.

private static List<Card> makeCards(final List<CardPattern> cardPatterns, final List<CardNumber> cardNumbers) {
    List<Card> cards = new ArrayList<>();
    for (CardPattern cardPattern : cardPatterns) {
        makeCard(cardNumbers, cards, cardPattern);
    }
    return cards;
}

private static void makeCard(final List<CardNumber> cardNumbers, final List<Card> cards, final CardPattern cardPattern) {
    for (CardNumber cardNumber : cardNumbers) {
        cards.add(Card.create(cardPattern, cardNumber));
    }
}

๋ฉ”์„œ๋“œ ๋ถ„๋ฆฌ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค ๋ณด๋‹ˆ (depth ์ œํ•œ) ๋ถˆํ•„์š”ํ•˜๊ฒŒ ํ•„๋“œ๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฐ’์ด ๋งŽ์•„์ง„๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.
๋‹ค๋งŒ ์ด์ „๋ณด๋‹ค ์นด๋“œ ํŒจํ„ด๋ณ„๋กœ - ์นด๋“œ ์ˆซ์ž๋ณ„๋กœ ์กฐํ•ฉํ•˜์—ฌ ์นด๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์ž˜ ๋ณด์ด๋Š” ๊ฒƒ ๊ฐ™๊ธฐ๋Š” ํ•˜๋‹ค ๐Ÿค”
๊ทธ๋ž˜์„œ, ์œ„์˜ ๋ฐฉ๋ฒ•์—์„œ ํ•„๋“œ๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๊ณ ๋ คํ•ด๋ณด์•˜๋‹ค.

private static List<Card> makeCards(final List<CardPattern> cardPatterns, final List<CardNumber> cardNumbers) {
    List<Card> cards = new ArrayList<>();
    for (CardPattern cardPattern : cardPatterns) {
        List<Card> cardsByPattern = makeCard(cardNumbers, cardPattern);
        cards.addAll(cardsByPattern);
    }
    return cards;
}

private static List<Card> makeCard(final List<CardNumber> cardNumbers, final CardPattern cardPattern) {
    List<Card> cardsByPattern = new ArrayList<>();
    for (CardNumber cardNumber : cardNumbers) {
        cardsByPattern.add(Card.create(cardPattern, cardNumber));
    }
    return cardsByPattern;
}

์ด์ „ ๋ฐฉ๋ฒ•๋ณด๋‹ค๋Š” ์ด๊ฒŒ ๋” ๋‚˜์€ ๊ฒƒ ๊ฐ™๋‹ค. makeCard์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜ํ™˜ํ˜•์ด List<Card>์ธ ๊ฒŒ ๋” ๋ช…ํ™•ํ•˜๊ธฐ๋„ ํ•˜๊ณ ...
 
๋‹ค๋งŒ, ๋‚˜๋Š” ๊ณ ๋ฏผ๊นŒ์ง€๋งŒ ํ•˜๊ณ  ์‹ค์ œ๋กœ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€๋Š” ์•Š์•˜๋‹ค.
stream์€ ์„ฑ๋Šฅ ์ธก๋ฉด์—์„œ ๊ณ ๋ คํ•ด์•ผ ํ•˜๋Š” ์‚ฌํ•ญ์€ ๋งž์ง€๋งŒ, ํ˜„์žฌ๋Š” Pattern๊ณผ Number์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š์„ ๋„๋ฉ”์ธ์ด๊ธฐ๋„ ํ•˜๊ณ , 
์˜คํžˆ๋ ค stream์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๋ถˆํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ ๋ถ„๋ฆฌ ์—†์ด Card.create(pattern, number);๋ฅผ ํ†ตํ•ด ์นด๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์กฐ๊ฑด์ด ๋” ์ž˜ ๋ณด์ธ๋‹ค๊ณ  ํŒ๋‹จ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๊ฑฐ๋Š” ๊ฐœ์ธ์˜ ์„ฑํ–ฅ ์ฐจ์ด์ด๊ธฐ ๋•Œ๋ฌธ์— ์•„๋งˆ ์ฝ”๋“œ ์Šคํƒ€์ผ์— ๋”ฐ๋ผ ๋‹ค๋ฅด์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค!
์ด๋ฒˆ ๋ฏธ์…˜์—์„œ ํ•œ ๋ฒˆ์ฏค ๊ณ ๋ฏผํ•ด๋ณธ ๋ถ€๋ถ„์ด๋ผ ๋ธ”๋กœ๊ทธ ๊ธ€๋กœ ์ž‘์„ฑํ•œ๋‹ค :D
 


๐Ÿ’ฌ ์ดˆ๊ธฐํ™”์™€ ์„ ์–ธ์ด ๋ถ„๋ฆฌ๋˜๋ฉด? (do-while)

์ง€๊ธˆ๊นŒ์ง€ ์ง„ํ–‰ํ–ˆ๋˜ ์šฐํ…Œ์ฝ” ๋ฏธ์…˜์—์„œ ๊ณตํ†ต์ ์ธ ๋ถ€๋ถ„์ด ์žˆ๋Š”๋ฐ, ๋ฐ”๋กœ ์‚ฌ์šฉ์žํ•œํ…Œ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
์‚ฌ์šฉ์ž์—๊ฒŒ ์ฒ˜์Œ ํ•œ ๋ฒˆ์€ ๋ฌด์กฐ๊ฑด ์ž…๋ ฅ๋ฐ›๊ณ , ๊ทธ๋’ค๋กœ ์ž…๋ ฅ๋ฐ›์•˜์„ ๋•Œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์— ๋”ฐ๋ผ์„œ ์‹คํ–‰์ด ์ข…๋ฃŒ๋˜๊ฑฐ๋‚˜, ๊ณ„์†๋˜๊ฑฐ๋‚˜ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜๋‹ค.
๋‚˜๋Š” ์ด๋Ÿฐ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋ณด์ž๋งˆ์ž do-while๋ฌธ์ด ๋– ์˜ฌ๋ž๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋ฒˆ ๋ฏธ์…˜์—์„œ๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•˜์˜€๋‹ค.

DrawCardCommand drawCardCommand;
do {
    drawCardCommand = getDrawCardCommand(player);
    checkDraw(gameManager, playerIndex, drawCardCommand);
    outputView.printPlayerCard(player.getName(), player.getCard());
} while (canDrawCard(player, drawCardCommand));

ํ•˜์ง€๋งŒ, ๋ฆฌ๋ทฐ์–ด๋‹˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ”ผ๋“œ๋ฐฑ์„ ์ฃผ์…จ๋‹ค.

์ดˆ๊ธฐํ™”์™€ ์„ ์–ธ์ด ๋”ฐ๋กœ ๋–จ์–ด์ ธ์žˆ๋Š” ๋ฐฉ์‹์€ ์ข‹์ง€์•Š์Šต๋‹ˆ๋‹ค-!
์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์‹œ๋‚˜์š”-?!

์‚ฌ์‹ค ์ง€๊ธˆ๊นŒ์ง€ do-while์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ด๋Ÿฐ ์ƒ๊ฐ์„ ํ•œ ๋ฒˆ๋„ ํ•ด๋ณธ ์ ์ด ์—†์—ˆ์–ด์„œ ๋†€๋ž๋‹ค.
๊ทธ๋ž˜์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ๊ฐ์„ ์ •๋ฆฌํ–ˆ๋‹ค.
 
1. ์„ ์–ธ๋ถ€ ์ด์ „์— ์–ด๋– ํ•œ ๋กœ์ง์ด ๋“ค์–ด์˜จ๋‹ค๋ฉด, NPE๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
2. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ํ•ญ์ƒ null ์ฒดํฌ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๋ถ€๋ถ„์ด ํ•„์š”ํ•ด์ง„๋‹ค.
3. ๊ฐ€๋…์„ฑ ์ธก๋ฉด์—์„œ๋„ ์ข‹์ง€ ์•Š๋‹ค. ๋ณ€์ˆ˜์˜ ์ถ”์ ์ด ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ๋‹ค.
 
์ƒ๊ฐํ•ด๋ณด๋ฉด NPE๋ผ๋Š” ๊ฑด ํ”ผํ•ด์•ผ ํ•˜๋Š” ์ฃผ์  ์ค‘ ํ•˜๋‚˜์ด๋‹ค. NPE๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค๋‹ˆ... ๐Ÿฅฒ
์ง€๊ธˆ์€ ํ˜ผ์ž ์ž‘์„ฑํ•œ ์ฝ”๋“œ์ง€๋งŒ, ํ˜„์—…์—์„œ ๋ณต์žกํ•œ ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋‹ค ๋ณด๋ฉด ๋ถ„๋ช… ์ด๋Ÿฌํ•œ ์ฝ”๋“œ๋Š” ๋ฒ„๊ทธ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฆฌํŒฉํ„ฐ๋ง์—์„œ๋Š” ์žฌ๊ท€๋ฅผ ํ™œ์šฉํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์˜€๋‹ค.

private void handleDrawCard(final GameManager gameManager,
                            final Participant player) {
    DrawCardCommand drawCardCommand = getDrawCardCommand(player);
    checkDraw(gameManager, player, drawCardCommand);
    outputView.printParticipantCard(player.getName(), player.getCard());
    if (cannotDrawCard(player, drawCardCommand)) {
        return;
    }
    handleDrawCard(gameManager, player);
}

if๋ฌธ์˜ ์กฐ๊ฑด๋„ ๋ฐ˜์ „์„ ์‹œ์ผฐ๋‹ค. (!์„ ํ†ตํ•ด ๋ถ€์ •ํ˜• ์กฐ๊ฑด์„ ์ฃผ์ง€ ์•Š๊ณ , ๋ถ€์ •ํ˜•์— ๋Œ€ํ•œ ์กฐ๊ฑด์„ ๋‹ด์€ ๋ฉ”์„œ๋“œ๋กœ ๋ถ„๋ฆฌ)
์ด๋ ‡๊ฒŒ ๋งŒ๋“œ๋‹ˆ๊นŒ ์นด๋“œ๋ฅผ ๋” ์ด์ƒ draw ํ•˜์ง€ ์•Š์„ ๋•Œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ๋น ์ ธ๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ์กฐ๊ฑด์ด ๋ช…ํ™•ํ•ด์ ธ์„œ ๋” ๋ณด๊ธฐ ์ข‹์€ ๊ฒƒ ๊ฐ™๋‹ค.
 


๐Ÿ’ฌ Enum์— ๋Œ€ํ•œ ์บ์‹ฑ ์ง„ํ–‰ํ•˜๊ธฐ

public final class Card {
    private static final int CARD_SIZE = 52;
    private static final Map<String, Card> CACHE = new ConcurrentHashMap<>(CARD_SIZE);

    private final CardPattern pattern;
    private final CardNumber number;

    private Card(final CardPattern pattern, final CardNumber number) {
        this.pattern = pattern;
        this.number = number;
    }

    public static Card create(final CardPattern pattern, final CardNumber number) {
        return CACHE.computeIfAbsent(toKey(pattern, number), mapping -> new Card(pattern, number));
    }

    private static String toKey(final CardPattern pattern, final CardNumber number) {
        return pattern.name() + number.name();
    }
}

ํŽ˜์–ด์˜€๋˜ ์ง€ํ† ๊ฐ€ ์•Œ๋ ค์ฃผ์—ˆ๋˜ ๋ฐฉ๋ฒ•์ด๋‹ค. ์นด๋“œ๋Š” ํ•œ ๋ฒˆ ์ƒ์„ฑ๋˜๋ฉด ๊ณ„์†ํ•ด์„œ ์žฌ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์บ์‹ฑ์„ ํ•ด๋‘๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.
key ๊ฐ’์œผ๋กœ ํŒจํ„ด๊ณผ ๋ฒˆํ˜ธ์— ๋Œ€ํ•œ name ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ณ , map์˜ computeIfAbsent๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์บ์‹ฑ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์ธ์ƒ ๊นŠ์—ˆ๋‹ค ๐Ÿ‘

public enum PatternMessage {
    HEART(CardPattern.HEART, "ํ•˜ํŠธ"),
    DIAMOND(CardPattern.DIAMOND, "๋‹ค์ด์•„๋ชฌ๋“œ"),
    CLOVER(CardPattern.CLOVER, "ํด๋กœ๋ฒ„"),
    SPADE(CardPattern.SPADE, "์ŠคํŽ˜์ด๋“œ");

    private static final Map<CardPattern, String> CACHE = Stream.of(PatternMessage.values())
            .collect(Collectors.toUnmodifiableMap(patternMessage -> patternMessage.pattern,
    patternMessage -> patternMessage.message));

    private final CardPattern pattern;
    private final String message;

    PatternMessage(final CardPattern pattern, final String message) {
        this.pattern = pattern;
        this.message = message;
    }

    public static String findMessage(CardPattern pattern) {
        return CACHE.get(pattern);
    }
}

๋˜ํ•œ, ๋ทฐ์— ์ถœ๋ ฅ๋  ๋ฉ”์‹œ์ง€๋ฅผ ๊ด€๋ฆฌํ•  ๋•Œ๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์บ์‹ฑ์„ ์ง„ํ–‰ํ•˜์˜€๋‹ค.
 


๐Ÿ’ฌ BiConsumer ํ™œ์šฉํ•˜๊ธฐ

์ด๊ฒƒ๋„ ๋ชจ๋˜ ์ž๋ฐ”์˜ ์˜ํ–ฅ์„ ์ •๋ง ๋งŽ์ด ๋ฐ›๊ณ  ์ž‘์„ฑํ•œ ์ฝ”๋“œ์ด๋‹ค. 
๋ฒ ํŒ…์— ๋Œ€ํ•œ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ณ„๋„์˜ BettingManager๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค.

public enum BettingManager {
    FIRST_TURN_DEALER_WIN(BettingManager::distributeDealerFirstTurnWin),
    FIRST_TURN_PLAYER_WIN(BettingManager::distributePlayerFirstTurnWin),
    IS_DEALER_WIN(BettingManager::distributeDealerWin),
    IS_PLAYER_WIN(BettingManager::distributePlayerWin);

    private final BiConsumer<Dealer, Player> referee;

    BettingManager(final BiConsumer<Dealer, Player> referee) {
        this.referee = referee;
    }

    private static void distributeDealerFirstTurnWin(final Dealer dealer, final Player player) {
        if (dealer.isBlackJack() && !player.isBlackJack()) {
            dealer.earnMoney(ParticipantMoney.create(player.getMoney()));
            player.loseMoney();
        }
    }

    private static void distributePlayerFirstTurnWin(final Dealer dealer, final Player player) {
        if (!dealer.isBlackJack() && player.isBlackJack()) {
            player.earnBonusMoney();
            dealer.loseMoney(ParticipantMoney.create(player.getMoney()));
        }
    }

    private static void distributeDealerWin(final Dealer dealer, final Player player) {
        if (dealer.isBlackJack()
                || dealer.isBust() && player.isBust()
                || !dealer.isBust() && dealer.calculateScore() > player.calculateScore()) {
            dealer.earnMoney(ParticipantMoney.create(player.getMoney()));
            player.loseMoney();
        }
    }

    private static void distributePlayerWin(final Dealer dealer, final Player player) {
        if (player.isBlackJack()
                || dealer.calculateScore() < player.calculateScore()) {
            player.earnMoney();
            dealer.loseMoney(ParticipantMoney.create(player.getMoney()));
        }
    }

    public BiConsumer<Dealer, Player> getReferee() {
        return referee;
    }
}

private static ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์™ธ๋ถ€์—์„œ ์ž˜๋ชป ํ™œ์šฉ๋˜๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด์˜ ์ŠนํŒจ ํŒ๋‹จ์— ๋Œ€ํ•œ ๋ณต์žกํ•œ ๋กœ์ง์„ ๋ฉ”์„œ๋“œ๋ณ„๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ๊ฐ€๋…์„ฑ ์ธก๋ฉด์—์„œ๋„ ๋งˆ์Œ์— ๋“œ๋Š” ์ฝ”๋“œ์ด๋‹ค ๐Ÿซ  
(์‚ฌ์‹ค ์ฒ˜์Œ 2๊ฐœ ์กฐ๊ฑด - ์ฒซ ํ„ด์— ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด์˜ ์ŠนํŒจ๋ฅผ ํŒ๋‹จํ•˜๋Š” ๋กœ์ง์€ ์„ค๊ณ„๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ์•„๋งˆ ์—†์• ๋„ ๋˜๋Š” ๋ถ€๋ถ„์ด์—ˆ์„ ํ…Œ์ง€๋งŒ... ใ…Ž ๋‚˜๋Š” ์ฒ˜์Œ์— ์นด๋“œ 2์žฅ์„ ๋ถ„๋ฐฐํ–ˆ์„ ๋•Œ ๋”œ๋Ÿฌ๊ฐ€ ์• ์ดˆ๋ถ€ํ„ฐ ๋ธ”๋ž™์žญ์ด๊ฑฐ๋‚˜ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๋ธ”๋ž™์žญ์ด๋ฉด ๊ฒŒ์ž„์„ ๋ฐ”๋กœ ์ข…๋ฃŒํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ๋ฅผ ๋‘์—ˆ๋‹ค.)
 
์•„๋ฌดํŠผ, ์™ธ๋ถ€์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ‘๊ทผํ•˜์—ฌ ์ŠนํŒจ๋ฅผ ํŒ๋‹จ ๋ฐ ๋ˆ์„ ๋ถ„๋ฐฐํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

public void judgeFirstBettingResult() {
    final Dealer dealer = participants.getDealer();
    participants.getPlayers()
            .forEach(player -> {
                FIRST_TURN_DEALER_WIN.getReferee().accept(dealer, player);
                FIRST_TURN_PLAYER_WIN.getReferee().accept(dealer, player);
            });
}

 


๐Ÿ’ฌ ๋ช…์‹œ์  ํ˜•๋ณ€ํ™˜ ์—†์• ๊ธฐ

๐Ÿ’ก ๊ธฐ์กด ์„ค๊ณ„

์‚ฌ์‹ค ์ด๋ฒˆ ๋ฏธ์…˜์—์„œ ๊ฐ€์žฅ ์• ๋ฅผ ๋จน์—ˆ๋˜ ๋ถ€๋ถ„ ์ค‘์— ํ•˜๋‚˜์ด๋‹ค.
๋‚˜๋Š” ์ด๋ฒˆ ๋ฏธ์…˜์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด๋ฅผ ๋‚˜๋ˆ ์„œ, ํ•˜๋‚˜์˜ ์ฐธ๊ฐ€์ž๋กœ ๊ด€๋ฆฌํ•˜์˜€๋‹ค. (๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด๋Š” Participant๋ฅผ ์ƒ์†๋ฐ›์Œ)
์ฐธ๊ฐ€์ž ๋ฆฌ์ŠคํŠธ์— ๋”œ๋Ÿฌ๋ฅผ ๊ฐ€์žฅ ์ฒ˜์Œ์— ๋„ฃ์–ด์ฃผ์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ€์žฅ ์ฒซ ๋ฒˆ์งธ ์ธ๋ฑ์Šค์— ์กด์žฌํ•˜๋Š” ์ฐธ๊ฐ€์ž๋Š” ๋”œ๋Ÿฌ๋ผ๋Š” ์˜๋ฏธ๋กœ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

// Participants.java
public class Participants {
    private static final int DEALER_ORDER = 0;
    private static final int PARTICIPANT_START_ORDER = 1;

    public Participant getDealer() {
        return participants.get(DEALER_ORDER);
    }

    public List<Participant> getPlayer() {
        return participants.subList(PARTICIPANT_START_ORDER, participants.size());
    }
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ปจํŠธ๋กค๋Ÿฌ์—์„œ๋Š” 'Participant'๋ผ๋Š” ์ •๋ณด๋งŒ ๊ฐ€์ง€๊ณ  ์‹ค์ œ๋กœ ํ•„์š”ํ•  ๋•Œ ๋”œ๋Ÿฌ๋ฅผ ๊บผ๋‚ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ,
๊บผ๋‚ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ถ€๋ถ„์—์„œ (Dealer)๋ฅผ ํ†ตํ•ด ๋ช…์‹œ์ ์œผ๋กœ ํ˜•๋ณ€ํ™˜์„ ํ•˜๋Š” ๋ถ€๋ถ„์ด ๋“ค์–ด๊ฐ€์•ผ ํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์กด์žฌํ–ˆ๋‹ค.
 
๋˜ํ•œ, ์ธ๋ฑ์Šค๋กœ ๊ด€๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฐธ๊ฐ€์ž๋“ค์— ๋Œ€ํ•œ ๊ฐ์ฒด๋ฅผ ์ ‘๊ทผํ•  ๋•Œ ์ˆœ์„œ์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž˜๋ชป ์‚ฌ์šฉ๋  ์œ„ํ—˜๋„ ๋†’์•˜๋‹ค. (๋‹น์‹œ์— ์ธ๋ฑ์Šค๋กœ ๊ด€๋ฆฌํ•˜๋˜ ์ด์œ ๋Š”, ์ฐธ๊ฐ€์ž๋“ค์— ๋Œ€ํ•œ ์นด๋“œ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ ์š”๊ตฌ์‚ฌํ•ญ์—์„œ ๋”œ๋Ÿฌ - ํ”Œ๋ ˆ์ด์–ด ์ˆœ์œผ๋กœ ์ถœ๋ ฅ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ์ˆœ์„œ๋ฅผ ๋งž์ถ”๊ธฐ ์œ„ํ•จ์ด์—ˆ๋‹ค.)

private void printDealerCard(final Participants participants) {
	final Dealer dealer = (Dealer) participants.getDealer();
}

๋Œ€๋žต ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ์˜€๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฐ˜ํ™˜์„ Participant ํƒ€์ž…์œผ๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ž์‹ ํƒ€์ž…์ธ Dealer๋กœ ์บ์ŠคํŒ…์„ ํ–ˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. (ํ˜น์€ ํ•„์š”ํ•˜๋‹ค๋ฉด Player๋กœ ์บ์ŠคํŒ…)
 
 

๐Ÿ’ก instanceof ๋„์ž… 

์ฒ˜์Œ์— ๋ฆฌ๋ทฐ์–ด๋‹˜์ด ๋ช…์‹œ์  ํ˜•๋ณ€ํ™˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ตฌ์กฐ๋กœ ๋ณ€๊ฒฝํ•ด๋‹ฌ๋ผ๊ณ  ๋ง์”€ํ•ด ์ฃผ์…”์„œ, ํ˜•๋ณ€ํ™˜์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์ž˜๋ชป๋œ ํƒ€์ž… ์บ์ŠคํŒ…์ด ์ผ์–ด๋‚  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์„œ ํ•˜์ง€ ๋ง๋ผ๋Š” ์˜๋ฏธ๋กœ ๋ฐ›์•„๋“ค์˜€๋‹ค. ๊ทธ๋ž˜์„œ, ํƒ€์ž… ์ฒดํฌ๋ฅผ ํ•˜๊ณ  ์บ์ŠคํŒ…์„ ํ•˜๋ฉด ์•ˆ์ „ํ•˜์ง€ ์•Š์„๊นŒ? ๋ผ๋Š” ์ƒ๊ฐ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด instanceof๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋กœ ๋ณ€๊ฒฝํ•˜์˜€๋‹ค ๐Ÿฅฒ (์ƒ๊ฐํ•ด๋ณด๋ฉด ๋ฐ”๋ณด ๊ฐ™์€... ๋ฐฉ๋ฒ•์ด๋‹ค)

if (participant instanceof Dealer) {
    return (Dealer) participant;
}

ํ•˜์ง€๋งŒ, instanceof๋Š” ์—ฌ๋Ÿฌ ๋ฐฉ๋ฉด์œผ๋กœ SOLID๋ฅผ ๋ฌด์‹œํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.
 

1. ์บก์Šํ™”๊ฐ€ ๊นจ์ง„๋‹ค.

: ํด๋ผ์ด์–ธํŠธ๊ฐ€ Participant์˜ ๊ตฌ์ฒด ํƒ€์ž…์ธ Dealer์— ๋Œ€ํ•ด์„œ๋„ ์•Œ๊ฒŒ ๋œ๋‹ค. 
 

2. OCP ์œ„๋ฐ˜

: ์บก์Šํ™”๊ฐ€ ๊นจ์ง€๋ฉด OCP๋„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์œ„๋ฐ˜ํ•˜๊ฒŒ ๋œ๋‹ค. ๋งŒ์•ฝ ์š”๊ตฌ์‚ฌํ•ญ์ด ๋ณ€ํ™”ํ•˜์—ฌ Dealer ์ž์ฒด๊ฐ€ ํ•„์š”์—†์–ด์ง„๋‹ค๋ฉด, ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ ์„ ์–ธ๋˜์—ˆ๋˜ Dealer์— ๋Œ€ํ•œ ์ฝ”๋“œ๋„ ๋ชจ๋‘ ์ œ๊ฑฐํ•ด์•ผ ํ•œ๋‹ค. ํ™•์žฅ์— ๋งค์šฐ ์ทจ์•ฝํ•ด์ง€๋Š” ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ํ™•์žฅ์—๋Š” ์—ด๋ ค ์žˆ๊ณ , ๋ณ€๊ฒฝ์—๋Š” ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•˜๋Š” OCP๋ฅผ ์œ„๋ฐ˜ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
 
+ ์ด์™ธ์—๋„ SRP ์œ„๋ฐ˜, ์„ฑ๋Šฅ ๋ฌธ์ œ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๋“ค์„ ์•ผ๊ธฐํ•œ๋‹ค... ๐Ÿซ ...
 
 

๐Ÿ’ก Participant์—์„œ ๊ฐ ํƒ€์ž… ๋ฐ˜ํ™˜ํ•˜๊ธฐ

๊ทธ๋ž˜์„œ, ์•„์˜ˆ Participant ์ž์ฒด์—์„œ Dealer๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค. ์‚ฌ์‹ค ์ด๋ ‡๊ฒŒ ๋˜๋ฉด, ์• ์ดˆ์— ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ Participant๋งŒ ๋ฐ”๋ผ๋ณด๋„๋ก ํ•˜๋ ค๊ณ  ํ–ˆ์—ˆ๋˜ ์„ค๊ณ„๊ฐ€ ๊นจ์ง„๋‹ค. (ํ•˜์ง€๋งŒ... ๋‹น์‹œ์—๋Š” ๋ช…์‹œ์  ํ˜•๋ณ€ํ™˜์„ ์—†์• ๋ ค๋Š” ๋…ธ๋ ฅ์„ ๋” ์ง„ํ–‰ํ–ˆ๋‹ค ใ… )

// Participant.java
public static Dealer createDealer() {
    return Dealer.create();
}

์šฐ์„ , ์ธ๋ฑ์Šค๋กœ ๊ด€๋ฆฌํ•˜๋˜ ๊ฒƒ ์ž์ฒด๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  Dealer๋Š” Participant๋ฅผ ์ƒ์†๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€๋ชจ ํด๋ž˜์Šค์ธ Participant์—์„œ ์ž์‹ ํด๋ž˜์Šค์ธ Dealer๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค. ๋‹ค๋งŒ, ์ž‘์„ฑํ•˜๊ณ  ๋‚˜์„œ๋„ ์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ๋งž์„๊นŒ...? ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

Participant์™€ Dealer ์‚ฌ์ด์˜ ๊ฒฐํ•ฉ๋„๊ฐ€ ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋˜๋ฉฐ, ๋‘˜์ด ์ƒํ˜ธ ์ฐธ์กฐ๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์œ„ํ—˜๋„๊ฐ€ ๋†’๋‹ค๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.
์Šคํ”„๋ง๋งŒ ์ƒ๊ฐํ•ด๋ด๋„ ์˜์กด ๊ด€๊ณ„์˜ ์–‘๋ฐฉํ–ฅ์„ฑ์ด ์ •๋ง ์œ„ํ—˜ํ•œ๋ฐ, ์ด๋ฅผ ๊ณ ๋ คํ•˜์ง€ ์•Š์€ ๋‚˜์œ ์ฝ”๋“œ์˜€๋‹ค...๐Ÿฅฒ
 
 

๐Ÿ’ก Stream ํ™œ์šฉํ•˜๊ธฐ

๊ทธ๋ž˜์„œ, ๋˜ ๋‹ค์‹œ ๊ณ ๋ฏผ์„ ์‹œ์ž‘ํ–ˆ๋‹ค... ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•ด์•ผ ํ• ๊นŒ?
์ด์ฏค์— 1๋‹จ๊ณ„๊ฐ€ merge๊ฐ€ ๋˜๊ณ , 2๋‹จ๊ณ„ ๋ฏธ์…˜์ด ์‹œ์ž‘ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด ์š”๊ตฌ์‚ฌํ•ญ์ด ์ถ”๊ฐ€๋˜์—ˆ์—ˆ๋‹ค.
๋ฐ”๋กœ, ์ฐธ๊ฐ€๋ณ„ ๋ฒ ํŒ… ๊ธˆ์•ก์„ ๊ด€๋ฆฌํ–ˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ๋‚˜๋Š” ParticipantInfo๋ผ๋Š” ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๊ด€๋ฆฌํ•˜๊ณ ์ž ํ–ˆ๋‹ค.
(์ฐธ๊ฐ€์ž๊ฐ€ Money ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒŒ ๊ฐ€์žฅ ๊น”๋”ํ•˜๊ฒ ์ง€๋งŒ, ์ธ์Šคํ„ด์Šค ํ•„๋“œ ๋ณ€์ˆ˜๊ฐ€ 3๊ฐœ ์ด์ƒ์ด ๋˜์ง€ ์•Š๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋ ‡๊ฒŒ ๋ถ„๋ฆฌํ•˜์˜€๋‹ค...)

public class ParticipantInfo {
    private final Map<Participant, ParticipantMoney> participantInfo;

    private ParticipantInfo(final Map<Participant, ParticipantMoney> participantInfo) {
        this.participantInfo = participantInfo;
    }

    public static ParticipantInfo create(final Map<Participant, ParticipantMoney> participantAsset) {
        return new ParticipantInfo(participantAsset);
    }

    public Participant findDealerInfo() {
        return participantInfo.keySet()
                .stream()
                .filter(participant -> DEALER_NAME.isSame(participant.getName()))
                .findFirst()
                .orElseThrow(() -> {
            throw new IllegalStateException("๋”œ๋Ÿฌ ์ •๋ณด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        });
    }

    public List<Participant> findPlayerInfo() {
        return participantInfo.keySet()
                .stream()
                .filter(Predicate.not(participant -> DEALER_NAME.isSame(participant.getName())))
                .collect(Collectors.toUnmodifiableList());
    }
}

๋‹น์‹œ ์ž‘์„ฑํ•˜๋˜ ์ฝ”๋“œ๋‹ค. ๋ฌผ๋ก  ์ด๊ฒƒ๋„ ์ข‹์€ ์ฝ”๋“œ๋Š” ์•„๋‹ˆ๋‹ค... ใ…Ž
์ฐธ๊ฐ€์ž์˜ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค๋Š” ์˜๋ฏธ๋กœ ParticipantInfo๋ผ๋Š” ๋„ค์ด๋ฐ์„ ์‚ฌ์šฉํ•˜์˜€๊ณ , ๊ฐ ์ •๋ณด์—์„œ ์ฐธ๊ฐ€์ž์™€ ๋”œ๋Ÿฌ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค๋Š” ์˜๋ฏธ๋กœ ์œ„์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค. ๋˜ํ•œ, ์ธ๋ฑ์Šค๋กœ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ  ๋”œ๋Ÿฌ์˜ ๊ณ ์œ  ์ด๋ฆ„์„ ํ†ตํ•ด ์ฐธ์—ฌ์ž์˜ ์ •๋ณด๋ฅผ ์ฐพ๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค. (๋ฌผ๋ก , ํ”Œ๋ ˆ์ด์–ด์˜ ์ด๋ฆ„์—๋Š” '๋”œ๋Ÿฌ'๊ฐ€ ๋“ค์–ด์˜ค์ง€ ๋ชปํ•˜๋„๋ก ํ•˜์˜€๋‹ค!)
 
๊ทธ๋ž˜์„œ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ๋Š” Dealer, Player์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์•Œ ํ•„์š” ์—†์ด Participant๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

// GameController.java
private Map<Participant, ParticipantMoney> getParticipantInfo() {
    final Map<Participant, ParticipantMoney> participantInfo = new LinkedHashMap<>();
    participantInfo.put(Participant.createDealer(), ParticipantMoney.zero());
    for (Participant player : makePlayers()) {
        participantInfo.put(player, getPlayerBettingMoneys(player));
    }
    return participantInfo;
}

๊ทธ๋ฆฌ๊ณ  ๋”œ๋Ÿฌ์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•  ๋•Œ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฐพ์•„์™€์„œ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

public void calculateProfit(final Map<Participant, ParticipantMoney> initMoneyInfo) {
    final Participant dealer = participantInfo.findDealerInfo();
    if (dealer.isBust()) {
        resetPlayerBettingMoney(dealer, initMoneyInfo);
        return;
    }
    calculatePlayerMoney(dealer, initMoneyInfo);
}

์ถ”๊ฐ€๋กœ, Participant์— ๋Œ€ํ•ด์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋”œ๋Ÿฌ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ Player๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
์ด์— ๋Œ€ํ•ด ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด Player์—๋Š” Exception์„ ํ„ฐํŠธ๋ฆฌ๋„๋ก ํ•˜์˜€๋‹ค.

// Dealer.java
public final class Dealer extends Participant {
    ...

    @Override
    public Card getFirstCard() {
        return hand.getFirstCard();
    }

    @Override
    public boolean canGiveCard() {
        return STANDARD_GIVEN_SCORE.isGreaterThanAndEqual(hand.calculateScore());
    }
}

// Player.java
public final class Player extends Participant {
    ...

    @Override
    public Card getFirstCard() {
        throw new UnsupportedOperationException("๋”œ๋Ÿฌ๋งŒ ์นด๋“œ ํ•œ ์žฅ์„ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.");
    }

    @Override
    public boolean canGiveCard() {
        throw new UnsupportedOperationException("๋”œ๋Ÿฌ๋งŒ 16์  ์ดํ•˜์ผ ๋•Œ ์นด๋“œ๋ฅผ ์ถ”๊ฐ€๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.");
    }
}

๋‹ค๋งŒ, ์ด๋Ÿฐ ์‹์œผ๋กœ Exception์„ ํ„ฐํŠธ๋ฆฌ๋Š” ๊ฑด ์ƒ๋‹นํžˆ ์ฐ์ฐํ•˜๋‹ค. ๋‹น์‹œ์—๋Š” ์ด๋Ÿฐ ์ƒ๊ฐ์„ ๊ฐ€์ง€๊ณ  ์ž‘์„ฑํ•˜์˜€๋‹ค.

ํ•˜์ง€๋งŒ, ๋ฆฌ๋ทฐ์–ด๋‹˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ”ผ๋“œ๋ฐฑ์„ ๋‚จ๊ฒจ์ฃผ์…จ๋‹ค.

UnsupportedOperationException ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ๊ณผ๋Š” ์ƒํ™ฉ์ด ์กฐ๊ธˆ ๋‹ค๋ฅผ์ˆ˜๋„ ์žˆ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด๋“œ๋„ค์š”!
์ž๋ฐ”์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ API์˜ ๊ฒฝ์šฐ ๊ณผ๊ฑฐ ๋ฒ„์ „์˜ ํ˜ธํ™˜์„ฑ์ด ์ตœ์šฐ์„ ์œผ๋กœ ํŒ๋‹จ๋˜๋Š” ๊ฒฝ์šฐ์ด๊ณ  (๋ฒ„์ „ ์—…์— ๋”ฐ๋ผ ์ด์ „ ๋ฒ„์ „์— ๋ฌธ์ œ๊ฐ€ ์ „ํ˜€ ์—†์–ด์•ผํ•˜๋Š” ๊ฒŒ ๋ณด์žฅ๋˜์–ด์•ผํ•จ) ์ง€๊ธˆ์˜ ๊ฒฝ์šฐ์—๋Š” ํ•™์Šต์ด๊ธฐ๋„ ํ•˜๊ณ  ๊ตฌ์กฐ๋ฅผ ๊ณ„์† ๋ณ€๊ฒฝํ•˜๋ฉฐ ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์„ ์ฐพ์„ ์ˆ˜๋„ ์žˆ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด์„œ์š”-!

์‚ฌ์‹ค ์ž๋ฐ” API์™€ ๋น„๊ตํ•˜๋Š” ๊ฑด ๋งž์ง€ ์•Š์€ ์˜ˆ์‹œ์ด๊ธด ํ–ˆ๋‹ค. ๋‚ด๊ฐ€ ์„ค๊ณ„ํ•œ ๊ฒƒ์€ ํ˜ธํ™˜์„ฑ ๋•Œ๋ฌธ์— ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ–ˆ๋‹ค๊ธฐ๋ณด๋‹ค๋Š”, ์–ด๋–ป๊ฒŒ๋“  Participant์— Dealer๋ฅผ ๋ผ์›Œ๋งž์ถ”๊ธฐ ์œ„ํ•ด์„œ ์ž‘์„ฑํ•œ ์ฝ”๋“œ์™€ ๋‹ค๋ฆ„์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
 
๋˜ํ•œ, XXXInfo๋ผ๋Š” ๋„ค์ด๋ฐ์€ ๊ฐ์ฒด์ง€ํ–ฅ์  ๊ด€์ ์—์„œ ์ƒ๊ฐํ•ด๋ณด์•˜์„ ๋•Œ ๋ถˆ๋ถ„๋ช…ํ•œ ๋„ค์ด๋ฐ์ด๋‹ค.
ParticipantInfo ๋Œ€์‹  Participant๋ผ๊ณ ๋งŒ ํ•˜๋”๋ผ๋„ ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ์ฐธ๊ฐ€์ž์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค๋Š” ๊ฒƒ ์ •๋„๋Š” ๋ช…ํ™•ํ•˜๊ฒŒ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Info๋Š” ์˜คํžˆ๋ ค ์–ด๋– ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ์˜ˆ์ƒํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
 
 

๐Ÿ’ก ์ƒ์† ๋Œ€์‹  ์กฐํ•ฉ ์‚ฌ์šฉํ•˜๊ธฐ

๊ฒฐ๊ตญ, ์ตœ์ข…์ ์œผ๋กœ ์ƒ์† ๊ตฌ์กฐ๋ฅผ ํฌ๊ธฐํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋งˆ์Œ์„ ๋Œ๋ ธ๋‹ค.
์ปจํŠธ๋กค๋Ÿฌ์—์„œ Dealer, Player๋ฅผ ๋ชจ๋ฅด๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ์‹คํŒจํ•˜์˜€์ง€๋งŒ, ์ด๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ๊ทธ๋‚˜๋งˆ ๊น”๋”ํ•œ ๊ตฌ์กฐ๋ผ๊ณ  ํŒ๋‹จํ•˜์˜€๋‹ค.

public interface Playable {
    void addCard(final Card... cards);

    boolean canDrawCard();

    boolean isBlackJack();

    boolean isBust();

    int calculateScore();

    void resetMoney(final ParticipantMoney initMoney);
}

์šฐ์„ , ํ”Œ๋ ˆ์ด์–ด์™€ ๋”œ๋Ÿฌ๊ฐ€ ๊ณตํ†ต์ ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ํ–‰์œ„์— ๋Œ€ํ•ด์„œ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

public final class Dealer implements Playable {
    private static final ParticipantName DEALER_NAME = ParticipantName.create("๋”œ๋Ÿฌ");

    private final Participant participant;
    private ParticipantMoney participantMoney;

    private Dealer(final Participant participant, final ParticipantMoney money) {
        this.participant = participant;
        this.participantMoney = money;
    }

    static Dealer create() {
        return new Dealer(Participant.create(DEALER_NAME.getName(), ParticipantCard.create()), ParticipantMoney.zero());
    }

    public Card getFirstCard() {
        return participant.getHand().get(FIRST_CARD_INDEX);
    }
	
    ...

    @Override
    public void addCard(final Card... cards) {
        participant.addCard(cards);
    }

   	...
}

Dealer๋Š” Playable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ํ•„๋“œ๋กœ Participant๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์„œ ๊ณตํ†ต์ ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ํ–‰์œ„์— ๋Œ€ํ•ด์„œ๋Š” Participant์—๊ฒŒ ๋ฉ”์„œ๋“œ๋ฅผ ์œ„์ž„ํ•˜์—ฌ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค. ๋˜ํ•œ, Map์œผ๋กœ ์ฐธ๊ฐ€์ž์˜ ๋ฒ ํŒ… ๊ธˆ์•ก ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋กœ ParticipantMoney๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์„œ ๋ฒ ํŒ…ํ•  ๋•Œ๋งˆ๋‹ค ๊ธˆ์•ก ์ •๋ณด๊ฐ€ ๋ณ€๊ฒฝ๋˜๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค.
(ํ•œ ๊ฐ€์ง€ ์•„์‰ฌ์šด ๊ฑด, Money์— ๋Œ€ํ•ด ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค์ง€ ๋ชปํ–ˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค ๐Ÿฅฒ ์ด ๋ถ€๋ถ„์€ ๋ฐฐํŒ… ๊ธˆ์•ก์„ ๊ณ„์‚ฐํ•˜๋Š” ๋กœ์ง์„ ๋œฏ์–ด ๊ณ ์ณ์•ผ ํ•ด๊ฒฐ๋˜๋Š” ๋ถ€๋ถ„์ด๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ๊นŒ์ง€๋Š” ์ˆ˜์ •์„ ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.)

public final class Player implements Playable {
    private final Participant participant;
    private ParticipantMoney participantMoney;

    private Player(final Participant participant) {
        this.participant = participant;
    }

    public static Player create(final String name) {
        validatePlayerName(name);
        return new Player(Participant.create(name, ParticipantCard.create()));
    }

  	 ...
    @Override
    public void addCard(final Card... cards) {
        participant.addCard(cards);
    }
}

๊ธฐ์กด์—๋Š” Player๊ฐ€ ํ•˜๋ฉด ์•ˆ ๋˜๋Š” ํ–‰์œ„์— ๋Œ€ํ•ด์„œ UnsupportedOperationException์„ ๋˜์กŒ์–ด์•ผ ํ–ˆ์ง€๋งŒ, ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๊ตณ์ด ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์œผ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— (์• ์ดˆ์— ์žฌ์ •์˜ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง) ์ฝ”๋“œ์ƒ์œผ๋กœ ๋” ๊น”๋”ํ•ด์กŒ๋‹ค๋Š” ์ ์ด๋‹ค.
๋‹ค๋งŒ ๊ฐœ์ธ์ ์ธ ๊ด€์ ์ด์ง€๋งŒ, bypassํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ๋งŽ๋‹ค ๋ณด๋‹ˆ๊นŒ TDD๋ฅผ ์ง„ํ–‰ํ•  ๋•Œ ์ƒ๋‹นํžˆ ํž˜๋“ค์—ˆ๋‹ค ๐Ÿ˜… (์ง€์˜ฅ์˜ ํ…Œ์ŠคํŠธ...)
 
๊ทธ๋ฆฌ๊ณ , ์ฐธ๊ฐ€์ž์™€ ๋”œ๋Ÿฌ์— ๋Œ€ํ•œ ์ •๋ณด๋Š” ๋ณ„๋„์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฐ›์•„์˜ค๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค.

public class Participants {
    private final Dealer dealer;
    private final Players players;

    private Participants(final Dealer dealer, final Players players) {
        this.dealer = dealer;
        this.players = players;
    }

    public static Participants create(final Players players) {
        return new Participants(Dealer.create(), players);
    }

    public Dealer getDealer() {
        return dealer;
    }

    public List<Player> getPlayers() {
        return players.getPlayers();
    }
}

ํ•„๋“œ๋กœ Dealer์™€ Players๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” Participants๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ์„œ ๊ฐ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค.
๊ฐ์ฒด์˜ ์˜์กด์„ฑ์€ Participants -> dealer, players์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ๋ฐฉํ–ฅ์„ฑ์ด๊ณ , ํ•„๋“œ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํ•„์š”ํ•œ ๊ฒฐํ•ฉ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ๋„ ์•„๋‹ˆ์–ด์„œ ์„ค๊ณ„ ์ธก๋ฉด์—์„œ๋Š” ๊ทธ๋‚˜๋งˆ ์ด ๋ฐฉํ–ฅ์ด ๊ฐ€์žฅ ๋‚˜์€ ๊ฒŒ ์•„๋‹ˆ์—ˆ์„๊นŒ ์‹ถ๋‹ค.

public final class GameManager {
    private final Deck deck;
    private final Participants participants;

    private GameManager(final Deck deck, final Participants participants) {
        this.deck = deck;
        this.participants = participants;
    }
}

๊ทธ๋ž˜์„œ, ๊ฒŒ์ž„์— ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ๊ด€๋ฆฌ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” GameManager๊ฐ€ Deck๊ณผ ์ฐธ๊ฐ€์ž ์ „์ฒด ์ •๋ณด์ธ Participants๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์„œ ํ•„์š”ํ•  ๋•Œ ๋”œ๋Ÿฌ์™€ ํ”Œ๋ ˆ์ด์–ด๋ฅผ ๊บผ๋‚ด์“ธ ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค.
 

private void printCardResult(final GameManager gameManager) {
    final Participants participants = gameManager.getParticipants();
    final Dealer dealer = participants.getDealer();
    outputView.printCardResult(dealer.getName(), dealer.getHand(), dealer.calculateScore());
    participants.getPlayers().forEach(player ->
    outputView.printCardResult(player.getName(), player.getHand(), player.calculateScore()));
}

๋‹ค๋งŒ, ์ปจํŠธ๋กค๋Ÿฌ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด Dealer, Players์— ๋Œ€ํ•œ ์˜์กด์ด ์ƒ๊ธธ ์ˆ˜๋ฐ–์— ์—†์–ด์„œ ์ด ๋ถ€๋ถ„์€ ์•„์‰ฝ๋‹ค ๐Ÿฅฒ
ํ•˜์ง€๋งŒ ์ฒซ ์ฝ”๋“œ์™€ ๋น„๊ตํ•ด๋ณด์•˜์„ ๋•Œ ํ˜•๋ณ€ํ™˜๋„ ์—†์• ๊ณ , ๊ฐ ๊ฐ์ฒด๊ฐ€ ํ•ด์•ผ ํ•  ํ–‰์œ„์— ๋Œ€ํ•ด ์ž˜ ์ •์˜ํ•œ ๊ฒƒ ๊ฐ™์•„์„œ ์ด ๊ตฌ์กฐ๊ฐ€ ๊ทธ๋‚˜๋งˆ ๊ฐ€์žฅ... ๋‚ซ์ง€ ์•Š์•˜์„๊นŒ ์‹ถ๋‹ค. 
 
๋งŒ์•ฝ ์ง€๊ธˆ ๋‹ค์‹œ ์„ค๊ณ„๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค๋ฉด, ์ฒ˜์Œ๋ถ€ํ„ฐ ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๊ณ  ๋ฒ ํŒ… ๊ธˆ์•ก ์—ญ์‹œ Dealer๋Š” ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๊ณ  ๊ทธ๋ƒฅ ๋ทฐ์—์„œ ๊ฒฐ๊ณผ๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ ํ”Œ๋ ˆ์ด์–ด์˜ ์ด ๊ธˆ์•ก์—์„œ ๊ณ„์‚ฐํ•˜๋ฉด์„œ ๋งŒ๋“ค์ง€ ์•Š์•˜์„๊นŒ... ์ƒ๊ฐ์ด ๋“ ๋‹ค. + ๋ถˆ๋ณ€์„ฑ ๋ณด์žฅ (์ƒํƒœ ํŒจํ„ด๋„ ์ ์šฉํ•˜์ง€ ์•Š์•˜์„๊นŒ?)
 


์‚ฌ์‹ค ๋ธ”๋ž™์žญ ๋ฏธ์…˜์€ ์—ฌ๋Ÿฌ๋ชจ๋กœ ์•„์‰ฌ์›€์ด ๋งŽ์ด ๋‚จ์•˜๋˜ ๋ฏธ์…˜์ด๋‹ค. ๊ตฌ์กฐ ๋ณ€๊ฒฝ์„ ๊ณ„์† ์ง„ํ–‰ํ•œ ๊ฑด ์žฌ๋ฐŒ์—ˆ์ง€๋งŒ, ๊ทธ๋งŒํผ ์‹œ๊ฐ„์ด ๋งŽ์ด ์ด‰๋ฐ•ํ•˜๊ธฐ๋„ ํ–ˆ๊ณ , ์ฒด์Šค ๋ฏธ์…˜์ด ๋‹ค๊ฐ€์˜ค๋ฉด์„œ ์‹ฌ์ ์œผ๋กœ ๋งŽ์ด ํž˜๋“ค์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค... ใ…  ๊ทธ๋ž˜๋„ ์ด๋ ‡๊ฒŒ ๋ธ”๋กœ๊ทธ ๊ธ€๋กœ ์ž‘์„ฑํ•˜๋‹ค ๋ณด๋‹ˆ๊นŒ ์ •๋ง ๋งŽ์€ ๋Œ€๊ณต์‚ฌ๊ฐ€ ๋“ค์–ด๊ฐ”์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๋˜์ƒˆ๊ธธ ์ˆ˜ ์žˆ์—ˆ๋‹ค.
๊ณ„์† ํ•˜๋‹ค ๋ณด๋ฉด ๋‚˜์ค‘์—๋Š” ๋” ๋ฐœ์ „ํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ... ํŒŒ์ดํŒ…!! ๐Ÿ’ช

Comments