-
Notifications
You must be signed in to change notification settings - Fork 389
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단계 - 블랙잭 구현] 현구막(최현구) 미션 제출합니다. #147
Conversation
안녕하세요 미립! 추가 질문이 있습니다! 1.
|
[JDK] Stream - 1내용
링크[TDD] 점진적 리팩토링 - 3내용
링크[OOP] 캐싱 - 2내용
링크[OOP] Service layer, Dto - 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.
피드백 반영 빠르게 잘해주셨네요 💯
질문하신 내용들중 조금 더 고민해보면 좋을 부분이 있어서 Request changes 하였습니다.
제가 남긴 피드백과 질문을 다시 한 번 고민해보고 리펙토링 진행해주세요.
수정할 부분이 없다고 생각하시면 그대로 PR 주셔도 무방합니다.
-
BlackjackManager 를 컨트롤러가 필드로 가지는게 나았을까요?
근본적으로 BlackjackManager 가 할 수 있는 일을 Controller가 대신 하고 있기때문에 파라미터로 계속해서 전달해야하는것 같다는 생각이드네요
BlackjackManager에서 현재 차례의 플레이어 이름 외에 다른 정보를 노출하지 않도록 리펙토링 해보는건 어떤가요? 인스턴스 필드로 가진다면
동시에 한게임 밖에 실행 할 수 없을 것 같아요. Game 과 Controller 의 경계가 모호해지네요. -
Players.findPlayerByName() 메서드의 인자도 포장?
편의를 위해 다양한 인자를 받는 find 메소드를 만들 수 있을 것 같아요. String, Name, Player 모두 가능하도록요.
그런데 Player 를 이미 가지고 있는데 해당하는 이름으로 Player 를 찾는게 의미가 있을까요? -
Dto를 어디까지 구현해주어야 하는지...
저는 VIEW 에 전달되기전에 DTO 로 변환되어야 한다고 생각해요
VIEW 와 컨트롤러가 통신할떄 무조건 DTO를 통해서만 통신한다고 생각하면 어떨까요?
DTO 를 왜 사용하려고하시는지 조금 더 고민해보면 좋겠네요 관련한 코멘트도 하나 남겨놓았으니 같이 확인해보면 좋을 것 같아요.
|
||
private void initBlackjack(final BlackjackManager blackjackManager) { | ||
blackjackManager.initDrawCards(); | ||
ParticipantDto dealerDto = blackjackManager.createDealerDto(); |
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.of(dealer) 서비스에 따라 DTO 의 형태는 여러가지로 변할 수있지만 도메인은 그렇지 않거든요
예를들어 게시글의 조회수는 관리자만 볼 수 있다면 관리자를 위한 DTO 는 조회수가 포함되고
그렇지 않은 DTO 는 조회수가 포함되지 않겠죠. 그럴때마다 도메인에 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생성 객체를 구현했습니다!
} | ||
} | ||
|
||
private void hitCardPlayer(final Player player, final BlackjackManager blackjackManager) { |
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.
플레이어를 외부로 꺼내지 말고
BlackjackManager 가 현재 플레이어를 인식하고 있는것은 어떤가요 ?
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.
시도해봣습니다!!
delete state methods, add judge method in Player delete judge method in Dealer
안녕하세요 미립!! 오래걸렸습니다!! DM 드렸던대로 유한 상태 머신을 중점적으로 리팩토링 해봤어요! 1. 테스트를 위한 CardDeck 생성 팩터리 메서드를 만들어버렸어요..리팩토링 과정에서 테스트코드부터 작성했다면 문제될 일이 없었겠지만, 2. 유한 상태 머신에서 승패 비교를 플레이어가 하는게 더 유리한거같아요....???!?
합계 7대6으로 플레이어의 상태 쪽에서 딜러의 상태를 비교하는 것이 경우의 수가 더 적어서 플레이어쪽에 구현했어요! 3. 유한 상태 머신에서 승패 비교를 딜러도 할 수 있어요...승패 비교 로직을 2번처럼 구현했을 때 "딜러 입장에서도 저 코드를 사용할 수 있는거 아니에요? 그럼 결과가 잘못 나오잖아요." 라고 라이언이 의문을 제기했어요.
정도가 있었어요. 하지만 두 가지 방법 모두 오버엔지니어링이 아닌가? 하는 고민도 함께 하게 됐어요. 4. 컨트롤러의 모든 메서드가 매니저를 인자로 가져가는 건 똑같아요...컨트롤러 쪽에 Players, Player, Dealer 가 빠져나가지 않게 해봤어요! 그런데 여전히 컨트롤러의 모든 메서드들이 블랙잭 매니저를 인자로 가져가네요 😭 😭 😭 |
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.
많은 고민을 하셨군요 💯
그만큼 많은 것을 얻으셨다고 생각합니다.
이번 미션은 여기까지 하고 이어서 다음 미션 진행해주시면 될 것 같아요.
-
테스트를 위한 CardDeck 생성 팩터리 메서드를 만들어버렸어요..
현재 구조가 크게 나쁘다고 생각이 들진 읺지만, 아쉬움이 남는다면 리펙토링 진행해보는것도 좋을 것 같아요.
유연한 설계로 변경하는 방법은 다양하니까 고민해보면 좋을 것 같네요. -
유한 상태 머신에서 승패 비교를 플레이어가 하는게 더 유리한거같아요....???!?
경우의 수로 위치를 정하는 접근법 좋네요 💯
나중에 확률이나 빈도수로 접근해봐도 좋겠네요 👍 -
유한 상태 머신에서 승패 비교를 딜러도 할 수 있어요...
현재 규모에서는 상태를 외부로 노출하지 않고 플레이어만 비교하는 인터페이스를 구현하고 있으니 큰 문제는 없어보여요. -
컨트롤러의 모든 메서드가 매니저를 인자로 가져가는 건 똑같아요...
출력을 대화식으로 해야한다는 생각을 버리면 조금 더 간소화 가능할 것 같아요. 해당하는부분에 코멘트로 설명해놓았어요 확인 해주세요.
OutputView.printNewLine(); | ||
} | ||
|
||
private void hitOrStayDealer(BlackjackManager blackjackManager) { |
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.
해당 로직이 blackjackManager 밖에 나와 있을 필요가 있나요 ?
딜러가 모든 패를 받고 출력을 해도 될 것 같아요
현재
[3 ,7]
[3 ,7, 4] HIT
출력
[3, 7, 4, J] BUST
출력
변경
[3 ,7]
[3 ,7, 4] HIT
[3, 7, 4, J] BUST
출력
[3 ,7]
[3 ,7, 4]
[3, 7, 4, J]
ex )
for (int i = 1; i < cards.size(); i++) {
for (int j = 0; int j = i; j++) {
System.out.print(cards.get(j));
}
}
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.
아... 출력 예시만 따라서 구현을 했는데, 더 유연하게 생각해볼 수 있었네요. 😮😮😮
미립 안녕하세요! 현구막이라고 합니다. 데드라인을 지키는게 우선인 것 같아서 우선 기능이 구현되자마자 PR을 진행하고 있습니다. 😃
(복잡한 레거시 코드를 리팩토링 하는것도 의도된 사항이 아닐까 합리화를 하면서) 미립이 주시는 피드백과 함께 열심히 리팩토링 할게요!
찰리와 함께 구현하면서 궁금한 점이 몇 가지 있었어요!
1. 카드덱 셔플을 딜러가 해야할까요?
현실세계에서 카드 게임이 진행될 땐 매 게임이 진행될 때마다 딜러가 직접 카드덱을 셔플하는데, 저희는 미리 셔플된 카드를 딜러가 가지도록 구현했어요.
객체지향이 현실세계를 완전하게 모방할 필요는 없다고 생각해서 이런 결정을 했는데, 혹시 딜러가 셔플하도록 하는게 더 나았는지, 카드덱이 미리 섞일 필요는 없었는지 고민이 돼요!
2. 캐싱은 제네레이터 클래스가 아닌, 자기 자신이 직접?
카드를 캐싱하고 덱에 채워넣는 제네레이터 클래스를 따로 구현했어요. 그런데 오늘 인비가 공유해줬던 이야기 중에 "캐싱은 캐싱되는 객체에 구현해야한다." 가 떠올라서 고민이 생겼어요. 사실 새로운 카드를 만들 때도
Card
로 먼저 접근할 생각을 하기 때문에Card
쪽에static
블럭을 이용해 구현하는게 나았나? 하면서 고민중이에요. 미립이 생각하시기엔 어떤지 궁금해요!3. Enum 클래스가 각각의 출력양식을 가진 것에 대하여.
카드 번호를 표현하는
Number
Enum 클래스와 게임 승패를 표현하는GameResult
Enum 클래스의 상수들이 각각 출력 양식을 가지고 있어요.사실 이전에 Enum 클래스들이 출력 양식을 가지는 것에 대해 코니가 피드백을 주셨었는데, 결론은 Enum 클래스들이 출력 양식을 가져선 안된다 였어요.
이번에 블랙잭을 구현하면서 저랑 찰리는
"OutputView 쪽에서 Enum별로 분기를 나눠서 출력을 하는건 도메인 역할을 침범하는게 아닐까?" 라는 생각과
"분기를 OutputView 에서 나누기엔 Enum 상수 개수가 너무 많지 않나?" 라는 생각 때문에 피드백을 받고도 똑같은 결정을 했어요...
그러지 말았어야 했을까요?
4. 일급 컬렉션에 메세지를 보내라를 잘 못지켰어요.
이번 블랙잭 미션에서 각 플레이어들이 매 차례마다 카드를 받기 위해 "y", "n" 입력을 받는데, 이걸 View-Controller로부터 받아오기 위해서
Player
들을 묶어놓은Players
일급 컬렉션에 메세지를 보내지 못하고 리스트로 가져왔어요.'객체에 메세지를 보내라'를 지키려했다면
Players
쪽에 View를 요청하는 코드가 들어갔을 것 같은데, 다른 방법이 있는건지 아니면 View-Controller 의 입력을 받기 위해서는 어쩔 수 없는것인지 궁금해요!감사합니다!!