-
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
[2단계 - 블랙잭 구현] 배럴(김나은) 미션 제출합니다. #209
Conversation
1. Dto 분리 2. 결과를 담는 객체 생성
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단계 구현하시느라 고생 많으셨어요 👏
피드백 남겨보았는데요, 일급컬렉션의 역할을 중점적으로 고민해보면 좋겠어요!
수정 후 재요청 부탁드려요 🙂
System.out.println("게임에 참여할 사람의 이름을 입력하세요.(쉼표 기준으로 분리)"); | ||
return sc.nextLine(); | ||
final String namesValue = sc.nextLine(); | ||
return namesValue.split(","); |
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.
스트링과 관련하여 상수화하는 의견이 궁금합니다~! 모든 스트링은 상수화해주는게 좋은가요? 아니면 위와 같이 온전한 문장?! 으로 이루어졌을 경우 상수화해주는 것이 좋을까요? (위와 같다면 모든 예외 메세지도 상수화해주는 것은 좋은 편인가요?)
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.
OutputView에서 출력을 위해서 잘게 쪼개져서 있는 단어?들도 매직 스트링으로 만들어 주는게 좋을까??라는 생각이 들어서 질문 남깁니당!ㅎㅎㅎ
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.
- 저는 모든 String을 무조건 상수화해야한다고는 생각하지 않아요. 예외 메시지 등은 그냥 놔두는 편이에요.
상수로 관리하는 경우는 애플리케이션, 핵심 로직에서 명확한 역할을 담당하고 있는 문자열과 숫자들일 경우입니다.
예를 들어 예외 메시지가 조금 변경된다고 애플리케이션의 큰 흐름이 바뀌거나 하지는 않지만,
위와 같이 외부에서 들어온 input의 구분자 라는 역할은 요구사항이 바뀌어서 구분자가;
,|
등으로 변경되거나 했을 경우에 해당 문자열을 변경해야 하는관리 포인트
를 가지기 때문에, 유지보수 측면에서 상수로 관리해야한다고 생각해요. - 같은 이유로 OutputView에서 굳이 모든 문자열을 상수로 가지고 있지 않아도 된다고 생각하지만,
,
같은 joining을 위한 구분자는 상수로 관리해야 한다고 생각해요. - 추가적으로 OutputView에서 전체적으로 String.format을 이용해 print를 해보면 좋겠어요 :)
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.
관리 포인트로 들어가는 것들을 상수화하는게 좋군요!! ㅎㅎㅎ 문자열을 +
로 println으로 하는 것보다 format 방식이 선호되는 것은 가독성 때문일까요?
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.
수정하였습니다~!
학습로그[Java] Cache - 3내용
|
안녕하세요:) 닉! 즐거운 주말 보내셨나요?ㅎㅎㅎ 피드백 주신 내용에 맞춰서 리팩토링 해보았어요! 리팩토링 하면서 몇가지 질문사항이 있어서 해당 내용은 resolve conversation하지 않고 남겨두었습니다 :) 지난 피드백 내용을 반영한다고 했는데 여기저기 고치다 보니 놓친 부분들도 많았네요! 같은 부분 다시 피드백 보내게 해서 죄송해요 🙏 꼼꼼한 피드백과 더불어 여러 질문사항에 친절하게 답변해주셔서 감사해요❤ |
[Java] interface, abstract class - 4내용
|
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 Player turnForPlayer(final Player player) { | ||
if (player.isAbleToTake()) { | ||
player.takeCard(cardDeck.pop()); | ||
} | ||
return player; | ||
} | ||
|
||
public void turnForDealer() { | ||
gameTable.giveCard(dealer); | ||
if (dealer.isAbleToTake()) { | ||
dealer.takeCard(cardDeck.pop()); | ||
} | ||
} |
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.
이 부분은 생각해봤는데ㅠㅠ View 로직이 달라서 온전히 합치기 어려울 것 같다는 생각이 들었어요. 메소드의 리턴해주는 값이 달라서 합치기 어렵더라구요. Player들에게는 한번씩 물어보고 대답을 듣고 받을 때마다 그에 따른 카드 내역을 보여주어야 합니다. 하지만 Dealer의 카드받기는 1회적이고, 내부적으로 16 이하인 경우에만 1장을 더 받고 단순히 받았습니다
메세지만을 던져주고 있어서요.
if (dealer.isAbleToTake()) {
dealer.takeCard(cardDeck.pop());
}
다만 이 부분 로직이 겹쳐서 해당 부분은 메소드로 분리했어요! 혹시 이걸 의도하신 걸까요? :) 더 좋게 합칠 수 있는 방법이 있다면 힌트 부탁드려요🙏 View 부분이랑 겹치는 부분 뭔가 가능하면 더 좋게 만들고 싶은데ㅠㅠ 현재 저에게는 이 방법 말고는 방안이 보이지 않아요. 혹시 View와 묻고 응답하는 부분을 더 내부적으로 처리할 수 있는 방안이 있을까요??
.map(Card::getCardName) | ||
.collect(Collectors.toList()); | ||
|
||
return Collections.unmodifiableList(cards); |
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 리스트를 가공한 형태이기 때문에 불변 리스트일 필요는 없어보여요 :)
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.
무의식중에 불변을 리턴한 것 같아요!ㅎㅎㅎ 그런데 가공한 데이터여도 해당 리스트에 새로운 이름을 추가하지 못하게 unmodifiableList로 리턴하는건 어떻게 생각하세요? 지나친 생각일까요..?ㅠ
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.
아뇨 불변으로 리턴하지 않는 것이 좋습니다.
일급컬렉션(Cards)에서 필드(List<Card>
)를 리턴할 때 불변 리스트로 반환하는 이유는 무엇일까요?
외부에서 Cards의 내부 필드인 List<Card>
를 조작할 수 없게 하기 위함입니다. 방어 로직인 것이죠.
반대로 클라이언트 입장에서 생각해볼까요?
List<Card>
는 Cards 일급컬렉션의 핵심 필드니 조작할 수 없도록 반환되어도 납득을 할 수 있지만,
이미 가공된 List<String>
등이 불변이라면, 클라이언트는 이를 사전에 인지하기도 힘들 뿐더러 가공된 데이터를 받아도 자유로운 사용을 위해서는 추가 가공을 거쳐야하는 불편함이 생기게 됩니다.
일급컬렉션은 그 자체로 확장성이 결여된, 제한된 기능만을 제공하는 객체가 되어버리죠.
이미 한번 가공을 거친 반환값은 원재료인 필드와 무관한 값이 되었기 때문에, 불변
이라는 방어로직
을 가질 필요가 없습니다 :)
안녕하세요 :) 닉! 해당 코멘트 준 부분들 다시 리팩토링 해보았어요! 세세한 부분까지 코멘트 주셔서 하면서 도움이 많이 되네요! 간단하고 분명한데 신경쓰지 못한 부분들도 많아서 반성도 하고 있습니다!😂 좀 더 세세하게 신경쓰는 습관을 들여야 되는데 아직은 놓치는 부분이 많은가봐요ㅋㅋㅋ 같은 내용 피드백하시느라 좀 피곤하실 텐데 덕분에 반성하게 되고 좋은 습관 들일 수 있는 것 같아요:) 감사합니다!ㅎㅎㅎ 이번에도 몇가지 질문들이 있네요ㅎㅎㅎ 해당 부분은 resolve conversation 하지 않고 남겼습니다 :) 오늘도 좋은하루 보내세요😀 |
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.
마지막까지 피드백 반영 감사합니다 ㅎㅎ
질문 주신 부분 중에 일급컬렉션에 관련한 내용 답변 남겼어요!
이번 미션도 고생 많으셨고 다음 미션도 화이팅입니다 🙂
안녕하세요 😃 닉, STEP2 코드리뷰 요청드립니다 😁 저번에 많이 많이 고쳐보는 것에 대해 걱정하지 않아도 된다는 말을 해주셔서 힘이 되었습니다❤ 그리고 가독성을 좀 더 좋게 하는 방식으로 주시는 팁 등이 도움이 많이 됩니다. 평소에 크게 생각하지 않아서 무의식중에 넘어갔던 것들을 짚어주셔서 이런 것들을 작게 나누면 리팩토링할 때 도움이 많이 되는 것 같아요!
더 많이 리팩토링하고 부딪혀보면서 많이 배울게요! 리팩토링 하면서 어렵고 고민되는 부분도 많지만 재미있네요😁 여기 저기 뜯어 고쳐서 코드 보기도 더 혼란스러울 것 같은데 피드백 꼼꼼하게 해주셔서 감사합니다. 👍
느낀점 및 질문
수업시간에 상태패턴을 배워서 적용해보려고 했는데, 아무리 생각해봐도 왜 적용해야하는지ㅠㅠ 모르겠더라구요ㅠㅠ 그래서 몇일 고민 끝에 적용을 포기하고 제 방식대로 작성해보았습니다! 승패로직과 카드를 받을 수 있는지 여부는 또 별개의 작동방식이라는 생각이 들어서
상태패턴이 적용되는 것이 어떤 의미를 가지는거지??
라는 생각이 계속 들더라구요. (카드를 받을 수 있는지 여부가 상태로 관리되고 승패는 따로 관리되는 것 같아서요.) 제가 만든 로직에서는 카드를 받을 수 있는지 여부를 Score를 통해서 Player, Dealer 스스로 해주는 느낌이 들었어요.DM으로 Outcome 로직에서 Score로 값을 2개 받지 않고 Player를 넘기는 것을 질문드렸는데.. 이것 역시 아무리 고민해도ㅠㅠ 떠오르지가 않았어요ㅠㅠ 어떤 의도인지 최대한 반영해보고 싶은데 변화할 수 있는 해결방안이 저에게는 안 보이나 봅니다.😂
해결방안을 찾기 위해 객체의 역할과 책임과 관련하여 실제 게임과 관련해서 생각해보려고 했습니다.
카드를 나눠주는 것도 딜러가 아닌 제3자(GameTable)가 하였으니 점수계산에 대한 승패 판단 역시 제 3자기 해주는 것이 옳다고 생각했어요. 그게 Outcome이 되는 것이고, 다만 이번에는 ScoreBoard라는 객체를 만들어서 Score값을 그대로 넘겨주는 것에 대한 오류 상황을 최대한 줄여주려고 해보았습니다! 여기서 피드백에 제가 상당히 어려워하는 것 같은데 혹시 좀 더 구체적인 로직방향에 대해 힌트를 주시면 찾아보겠습니다~! 😃
이렇게 객체를 나누다보니 궁금한 점이 생겼습니다. PlayerResult, ScoreBoard는 도메인에 관련된 결과를 가지는 객체인데, 이것들이 Dto라고 하기엔 실질적 정보를 가진 객체이니 애매하다는 생각이 들었습니다. 하지만, 도메인 로직을 가지는 객체라고 하기엔 Dto에 정보를 넘겨주는 성격이 강해서 getter로 Dto에게 정보를 넘겨줄 수 밖에 없는 것 같습니다. 이런 애매한 객체들은 무엇일까요..??
리팩토링하면서 TDD를 적용하기가 너무 어렵네요ㅠㅠ 여기저기 얽혀있는 순간 (특히 생성자를 고치는 순간) TDD는 포기하게 되는 것 같아요ㅠㅠ 결국 프로덕션 먼저 다 고치고 돌려보고 단위테스트를 작성하는 방식으로 하게 됩니다. 여기서 TDD를 좀 더 잘 적용할 수 있는 팁이 있을까요?
학습로그
[Java] Stream - 2
내용
원하는 대로 출력하려면 flatMap 내부 스트림에서 map을 한 번 더 연결해준다.
[OOP] 가독성 - 3
내용
[OOP] abstract class - 3
내용
링크
stackoverflow 관련 답글
[Java] BigDecimal VS BigInteger - 1
내용
[Java] Integer.compare() - 1
내용
Integer.compare(score, o.score)