DevLog ๐ถ
[์ฐํ ์ฝ 5๊ธฐ] ๋ธ๋์ญ ๊ตฌํ ๋ฏธ์ ํ๊ณ ๋ณธ๋ฌธ
[์ฐํ ์ฝ 5๊ธฐ] ๋ธ๋์ญ ๊ตฌํ ๋ฏธ์ ํ๊ณ
dolmeng2 2023. 4. 4. 11:43์งํ ๋ ์งํํ ์ธ ๋ฒ์งธ ํ์ด ํ๋ก๊ทธ๋๋ฐ์ด๋ค. ์ฌ์ค ๋๋ ์ง ํ์ฐธ ๋์ง๋ง... ๋ค๋ฆ๊ฒ ํ๊ณ ๋ฅผ ์์ฑํด๋ณด๊ณ ์ ํ๋ค.
๋ธ๋์ญ๋ถํฐ ๋ฏธ์
์ ๋์ด๋๊ฐ ํ์คํ ๊น๋ค๋ก์์ก๋ค๋ ์๊ฐ์ด ๋ค์๋ค... ใ
ใ
๊ทธ๋๋ ๋ฐฐ์ด ๊ฒ ๋ง์์ ์ข๋ค.
โ๏ธ ์์ฑํ ์ฝ๋
โ๏ธ 1์ฐจ PR
โ๏ธ 2์ฐจ PR
โ๏ธ ๊ธฐ๋ฅ ์๊ตฌ์ฌํญ
๋ธ๋์ญ ๊ฒ์์ ๋ณํํ ํ๋ก๊ทธ๋จ์ ๊ตฌํํ๋ค. ๋ธ๋์ญ ๊ฒ์์ ๋๋ฌ์ ํ๋ ์ด์ด ์ค ์นด๋์ ํฉ์ด 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๋ ๊ฐ์ง๊ณ ์์ง ์๊ณ ๊ทธ๋ฅ ๋ทฐ์์ ๊ฒฐ๊ณผ๋ฅผ ๊ณ์ฐํ ๋ ํ๋ ์ด์ด์ ์ด ๊ธ์ก์์ ๊ณ์ฐํ๋ฉด์ ๋ง๋ค์ง ์์์๊น... ์๊ฐ์ด ๋ ๋ค. + ๋ถ๋ณ์ฑ ๋ณด์ฅ (์ํ ํจํด๋ ์ ์ฉํ์ง ์์์๊น?)
์ฌ์ค ๋ธ๋์ญ ๋ฏธ์
์ ์ฌ๋ฌ๋ชจ๋ก ์์ฌ์์ด ๋ง์ด ๋จ์๋ ๋ฏธ์
์ด๋ค. ๊ตฌ์กฐ ๋ณ๊ฒฝ์ ๊ณ์ ์งํํ ๊ฑด ์ฌ๋ฐ์์ง๋ง, ๊ทธ๋งํผ ์๊ฐ์ด ๋ง์ด ์ด๋ฐํ๊ธฐ๋ ํ๊ณ , ์ฒด์ค ๋ฏธ์
์ด ๋ค๊ฐ์ค๋ฉด์ ์ฌ์ ์ผ๋ก ๋ง์ด ํ๋ค์๊ธฐ ๋๋ฌธ์ด๋ค... ใ
๊ทธ๋๋ ์ด๋ ๊ฒ ๋ธ๋ก๊ทธ ๊ธ๋ก ์์ฑํ๋ค ๋ณด๋๊น ์ ๋ง ๋ง์ ๋๊ณต์ฌ๊ฐ ๋ค์ด๊ฐ์๋ค๋ ๊ฒ์ ๋ค์ ํ ๋ฒ ๋์๊ธธ ์ ์์๋ค.
๊ณ์ ํ๋ค ๋ณด๋ฉด ๋์ค์๋ ๋ ๋ฐ์ ํ ์ ์์ง ์์๊น... ํ์ดํ
!! ๐ช
'์ฐ์ํํ ํฌ์ฝ์ค > ๋ ๋ฒจ 1' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์ฐํ ์ฝ 5๊ธฐ] ๋ ๋ฒจ 1 ๋ ๋ฒจ ์ธํฐ๋ทฐ ์ ๋ฆฌ ๋ฐ ๊ฐ์ ํ๊ณ (4) | 2023.04.06 |
---|---|
[์ฐํ ์ฝ 5๊ธฐ] ์ฒด์ค ๊ฒ์ ๊ตฌํ ๋ฏธ์ ํ๊ณ (0) | 2023.04.05 |
[์ฐํ ์ฝ 5๊ธฐ] ์ฌ๋ค๋ฆฌ ํ๊ธฐ ๊ฒ์ ๋ฏธ์ ํ๊ณ (0) | 2023.04.03 |
[์ฐํ ์ฝ 5๊ธฐ] ์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์ ํ๊ณ (0) | 2023.02.22 |
[์ฐํ ์ฝ 5๊ธฐ] 1์ฃผ์ฐจ ํ๊ณ ๋ก - ์ฐ๊ทน, ์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์ ๊ตฌํํ๊ธฐ (2) | 2023.02.13 |