[🚀 사이클2 - 미션 (블랙잭 베팅 기능)] 제제 미션 제출합니다.#1093
[🚀 사이클2 - 미션 (블랙잭 베팅 기능)] 제제 미션 제출합니다.#1093alstj2384 wants to merge 58 commits intowoowacourse:alstj2384from
Conversation
Gomding
left a comment
There was a problem hiding this comment.
안녕하세요 제제!
사이클2 빠르게 진행해주셨네요 🙇
코멘트 남겼으니 확인부탁드려요~
이전 PR 에 머지하면서 남겼던 코멘트는 이번에 고려하지 않으신것 같은데
함께 반영해주세요
추가로 궁금한 점 있으면 DM 이나 코멘트 남겨주세요!
There was a problem hiding this comment.
사이클1에서 제가 리뷰를 못드렸네요 😢
Controller 가 BlackjackGame 을 상태로 가지고 있어도 괜찮을지 고민해보면 좋겠어요~
There was a problem hiding this comment.
적절하지 않을 것 같습니다.
run() 메서드 안에서만 BlackjackGame이 사용되고 있기 때문에 run()의 지역 변수로 사용하도록 수정했습니다!
There was a problem hiding this comment.
어떤 이유로 적절하지 않다고 생각하셨는지도 궁금하네요!
Controller 가 상태를 가지면 어떤 단점이 있을까요?
There was a problem hiding this comment.
우선 컨트롤러 1개당 상태 1개로 매핑되어 여러 개의 상태가 필요한 경우 컨트롤러를 여러 개 만들어야 할 수도 있겠네요!
또한 동시성 이슈도 떠올랐습니다. 단일 스레드 환경에서는 상태를 가지는 게 잠재적 위험이 없을 수도 있지만, 다중 스레드 환경에서는 동시성으로 인한 잠재적 위험이 생길 수 있다는 생각이 드네요!
| public abstract class Participant { | ||
| protected final Name name; | ||
| protected final Hand hand; | ||
| protected BetMoney betMoney; |
There was a problem hiding this comment.
딜러에게 필요없는 부분까지 Participant가 포함하고 있던 것 같습니다!
Participant에는 플레이어와 딜러 모두에게 필요한 hand만 남기고, 나머지는 Player가 갖도록 수정했습니다!
부모 클래스가 정말 자식 클래스에게 공통적으로 필요한 정보만 담고있는지 잘 고민해야겠네요 😢
감사합니다!
| @@ -52,7 +58,7 @@ public void dealerHitStand(Consumer<Boolean> printDecisionOutput) { | |||
| } | |||
There was a problem hiding this comment.
indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다
규칙대로 리팩토링을 고려해보시죠! 😉
alstj2384
left a comment
There was a problem hiding this comment.
안녕하세요 찰리!
피드백 반영하여 제출합니다.
피드백을 통해 성장감을 많이 느끼고 있습니다. 정말 감사합니다! 😊
| public abstract class Participant { | ||
| protected final Name name; | ||
| protected final Hand hand; | ||
| protected BetMoney betMoney; |
There was a problem hiding this comment.
딜러에게 필요없는 부분까지 Participant가 포함하고 있던 것 같습니다!
Participant에는 플레이어와 딜러 모두에게 필요한 hand만 남기고, 나머지는 Player가 갖도록 수정했습니다!
부모 클래스가 정말 자식 클래스에게 공통적으로 필요한 정보만 담고있는지 잘 고민해야겠네요 😢
감사합니다!
There was a problem hiding this comment.
적절하지 않을 것 같습니다.
run() 메서드 안에서만 BlackjackGame이 사용되고 있기 때문에 run()의 지역 변수로 사용하도록 수정했습니다!
Gomding
left a comment
There was a problem hiding this comment.
안녕하세요 제제!
전체적으로 잘 수정해주셨네요 :)
추가로 코멘트 남겼으니 확인부탁드려요!
궁금한 점 있으면 언제든 DM 이나 코멘트 남겨주세요~
There was a problem hiding this comment.
어떤 이유로 적절하지 않다고 생각하셨는지도 궁금하네요!
Controller 가 상태를 가지면 어떤 단점이 있을까요?
src/main/java/domain/Rank.java
Outdated
| public static Score totalSum(int aceAmount, Score sum) { | ||
| for (int i = 0; i < aceAmount; i++) { | ||
| sum = sum.add(decideAceValue(sum, aceAmount - i - 1)); | ||
| public static Score sumWithAce(int aceAmount, Score sumWithOutAce) { |
There was a problem hiding this comment.
Ace가 여럿있을 떄 점수 합상에 버그가 있는것 같네요 🤔
수정하시고 테스트 코드도 함께 보강해주세요!
There was a problem hiding this comment.
변수명 리팩토링 과정에서 sumWithOutAce를 수정하지 않아 발생했던 거 같습니다 😭
변수명 바꿀 때도 제대로 바꿨는지 주의해야겠습니다..
반영하여 수정 및 테스트 추가했습니다!
There was a problem hiding this comment.
리팩토링 과정에서 휴먼에러가 많이 발생할 수 있죠 :)
그렇기 때문에 리팩토링에는 테스트 코드가 존재해야하는게 전재조건 입니다 😄
그래야 리팩토링 후에도 정상 동작하는지 검증이 가능하니까요!
경험해보면서 테스트 케이스를 놓치지 않기위해 고민을 계속 해보시면 됩니다!!
테스트 코드는 잘 작성하고 계시니 걱정없겠네요 👍
src/main/java/domain/card/Hand.java
Outdated
| } | ||
|
|
||
| public static Hand copyOf(Hand hand) { | ||
| return new Hand(hand.getCards()); |
There was a problem hiding this comment.
copy 라는 메서드 이름은 깊은 복사만을 생각할것 같은데
불변으로 반환할거라고는 예측하지 못할 수 있겠네요 🤔
다른 개발자가 복사후에 카드를 추가하고싶어서 add 를 호출한다면 에러가 발생할 수 있곘네요!
제제는 어떻게 생각하시나요?
There was a problem hiding this comment.
동의합니다.. 수정을 허용하기 위해 getCards가 아닌, new ArrayList<>(...) 형태로 내려주는 게 적절할 것 같습니다!
깊은 복사와 불변 컬렉션을 나누어 생각하지 못했던 거 같네요.
감사합니다!
There was a problem hiding this comment.
만약 복사하며 불변 반환을 원했다면
메서드 이름에 불변을 반환하는것이 드러나게 변경하는 방법도 있습니다 :)
| private BetMoney(BigDecimal value) { | ||
| this.value = value; | ||
| } |
There was a problem hiding this comment.
입력에서 어느정도 방어가 될 것 같지만
BetMoney 자체는 음수로 객체 생성이 가능하겠네요 🤔
There was a problem hiding this comment.
플레이어 패배 시 BetMoney가 음수가 되는 경우도 있어 검증을 추가하지 않았습니다!
입력은 음수로 받는 것이 잘못되었기에 검증하고, 내부적으로는 음수를 생성할 수 있게 의도했습니다.
There was a problem hiding this comment.
BetMoney 를 결과에서 사용하고 있는것은 몰랐네요 😅
동의합니다!
| private BetMoney(BigDecimal value) { | ||
| this.value = value; | ||
| } |
There was a problem hiding this comment.
플레이어 패배 시 BetMoney가 음수가 되는 경우도 있어 검증을 추가하지 않았습니다!
입력은 음수로 받는 것이 잘못되었기에 검증하고, 내부적으로는 음수를 생성할 수 있게 의도했습니다.
src/main/java/domain/card/Hand.java
Outdated
| } | ||
|
|
||
| public static Hand copyOf(Hand hand) { | ||
| return new Hand(hand.getCards()); |
There was a problem hiding this comment.
동의합니다.. 수정을 허용하기 위해 getCards가 아닌, new ArrayList<>(...) 형태로 내려주는 게 적절할 것 같습니다!
깊은 복사와 불변 컬렉션을 나누어 생각하지 못했던 거 같네요.
감사합니다!
src/main/java/domain/Rank.java
Outdated
| public static Score totalSum(int aceAmount, Score sum) { | ||
| for (int i = 0; i < aceAmount; i++) { | ||
| sum = sum.add(decideAceValue(sum, aceAmount - i - 1)); | ||
| public static Score sumWithAce(int aceAmount, Score sumWithOutAce) { |
There was a problem hiding this comment.
변수명 리팩토링 과정에서 sumWithOutAce를 수정하지 않아 발생했던 거 같습니다 😭
변수명 바꿀 때도 제대로 바꿨는지 주의해야겠습니다..
반영하여 수정 및 테스트 추가했습니다!
| public Result judge(State state) { | ||
| if (state instanceof Blackjack) { | ||
| return Result.LOSE; | ||
| } | ||
| if (state instanceof Bust) { | ||
| return Result.WIN; | ||
| } | ||
| return judgeByScore(state); | ||
| } |
There was a problem hiding this comment.
Hit와 Stay는 점수 계산 로직이 같아서 완전히 같은 코드가 Hit와 Stay에 중복으로 오버라이딩 되어야 했습니다.
이 중복을 줄이고자 State에서 기본 점수 계산 로직으로 구현 후,
특수한 계산이 있는 블랙잭, 버스트 클래스에서 오버라이딩하는 식으로 구성해 봤는데요!
Hit만의 계산 로직이 추가된다면 수정되어야 할 거 같고, Hit와 Stay의 judge 방식을 한 눈에 확인하기 어려운 구조라고도 생각이 들었습니다.
중복이 있더라도 각 클래스에 같은 로직을 작성하는 게 적절할까요?
There was a problem hiding this comment.
상속을 플랫한 구조로 생각하기 쉬운데
상속에도 계층 구조를 만들 수 있다는것을 힌트로 드려볼게요~ 😄
동물(부모 클래스) - 뱅갈 고양이, 시베리안 고양이, 리트리버, 말티즈, 진돗개 <-- 플랫한 구조
interface 동물 { sound() }
class 뱅갈고양이 extends 동물 { sound() { "냥냥" } }
class 시베리안 고양이 extends 동물 { sound() { "냥냥" } }
class 리트리버 extends 동물 { sound() { "멍멍" } }
class 말티즈 extends 동물 { sound() { "멍멍" } }
class 진돗개 extends 동물 { sound() { "멍멍" } }중복이 있는데 동물을 상속받은 클래스는 2개의 그룹으로 묶어볼 수 있곘죠? 😉
There was a problem hiding this comment.
좋은 예시와 의견 감사합니다!
상태 패턴을 적용하게 된 계기는 LMS의 강의 글을 보고 나서였는데요!
해당 강의에서는 계층 구조가 적용된 블랙잭의 상태 패턴을 예시로 보여주고 있었습니다.
처음에는 그 구조가 전혀 이해가 되지 않았기에, 부딪히면서 배워보자는 생각으로 리팩토링을 시도했던 거 같아요.
다만 "강의 글에서 이 구조로 했으니까 이 구조부터 만들고 시작하자" 라는 접근이 아니라, "내가 이 추상 클래스 계층의 필요성을 느끼면 넣겠다" 라고 나름 홍대병(?)걸린 마음가짐으로 하다보니 PR을 제출할 당시에는 그 이유를 찾지 못했습니다.
리팩토링 과정에서 남겨주신 피드백을 반영하기 위해 "논리적으로 맞지 않는 메서드(bust에서 draw가 가능한 것)의 예외를 추가"한 후, 각 구현체를 보니 공통된 로직을 발견했는데요.
바로 "끝난 상태의 구현체들은 draw와 stay에 모두 예외를 발생시키고 있다" 였습니다.
이에 이 구현체들의 공통점을 추상 클래스(Finished)에 정의하여 상속 계층을 추가했습니다.
현재는 이런식으로 점진적으로 상속 계층을 추가하여 반영한 상황입니다!
Gomding
left a comment
There was a problem hiding this comment.
안녕하세요 제제!
상태 패턴 도입해주셨네요 😄
몇가지 의견 남겼으니 확인해주세요~
궁금한 점 있으면 언제든 DM 이나 코멘트 남겨주세요!
src/main/java/domain/Rank.java
Outdated
| public static Score totalSum(int aceAmount, Score sum) { | ||
| for (int i = 0; i < aceAmount; i++) { | ||
| sum = sum.add(decideAceValue(sum, aceAmount - i - 1)); | ||
| public static Score sumWithAce(int aceAmount, Score sumWithOutAce) { |
There was a problem hiding this comment.
리팩토링 과정에서 휴먼에러가 많이 발생할 수 있죠 :)
그렇기 때문에 리팩토링에는 테스트 코드가 존재해야하는게 전재조건 입니다 😄
그래야 리팩토링 후에도 정상 동작하는지 검증이 가능하니까요!
경험해보면서 테스트 케이스를 놓치지 않기위해 고민을 계속 해보시면 됩니다!!
테스트 코드는 잘 작성하고 계시니 걱정없겠네요 👍
src/main/java/domain/card/Hand.java
Outdated
| } | ||
|
|
||
| public static Hand copyOf(Hand hand) { | ||
| return new Hand(hand.getCards()); |
There was a problem hiding this comment.
만약 복사하며 불변 반환을 원했다면
메서드 이름에 불변을 반환하는것이 드러나게 변경하는 방법도 있습니다 :)
| private BetMoney(BigDecimal value) { | ||
| this.value = value; | ||
| } |
There was a problem hiding this comment.
BetMoney 를 결과에서 사용하고 있는것은 몰랐네요 😅
동의합니다!
| public Result judge(State state) { | ||
| if (state instanceof Blackjack) { | ||
| return Result.LOSE; | ||
| } | ||
| if (state instanceof Bust) { | ||
| return Result.WIN; | ||
| } | ||
| return judgeByScore(state); | ||
| } |
There was a problem hiding this comment.
상속을 플랫한 구조로 생각하기 쉬운데
상속에도 계층 구조를 만들 수 있다는것을 힌트로 드려볼게요~ 😄
동물(부모 클래스) - 뱅갈 고양이, 시베리안 고양이, 리트리버, 말티즈, 진돗개 <-- 플랫한 구조
interface 동물 { sound() }
class 뱅갈고양이 extends 동물 { sound() { "냥냥" } }
class 시베리안 고양이 extends 동물 { sound() { "냥냥" } }
class 리트리버 extends 동물 { sound() { "멍멍" } }
class 말티즈 extends 동물 { sound() { "멍멍" } }
class 진돗개 extends 동물 { sound() { "멍멍" } }중복이 있는데 동물을 상속받은 클래스는 2개의 그룹으로 묶어볼 수 있곘죠? 😉
src/main/java/domain/state/Bust.java
Outdated
| @Override | ||
| public State draw(Card card) { | ||
| hand.add(card); | ||
| return new Bust(hand); | ||
| } |
There was a problem hiding this comment.
draw 도 마찬가지 입니다 :)
현실세계에서 bust 된 플레이어가 카드를 뽑으려하면 당장 경고를 하고 멈추라 하겠죠?
프로그램에서는 어떻게 해야할까요~
+) 다른 상태 클래스들도 점검해주세요!
There was a problem hiding this comment.
이 부분도 고민이 많았습니다 😭
처음 생각은 Bust된 플레이어는 draw를 할 수 없으므로 예외를 발생시키려고 했습니다.
하지만 협업 관점에서 다른 개발자가 "얘는 draw 구현되어 있네? 써도 되겠다"라고 착각할 수도 있다는 생각도 들었습니다.
이에 "필요하지 않은 인터페이스는 갖지 않게 해야한다" 라는 생각으로 구조를 고민했으나, 답을 찾기 어려웠습니다 😭
따라서 일단 다른 개발자가 사용해도 혼동이 없도록 모든 인터페이스를 그럴듯하게 구현했습니다.
Blackjack에서 카드를 뽑을 수 없는 게 맞지만, 뽑게 된다면 Bust가 된다 라는 느낌입니다.
다만 다시 생각해 보면, 오히려 예외를 적절히 발생시키는 게 객체의 책임이라는 생각도 들었네요.
리팩토링 과정에서 논리적으로 불가능한 동작들은 모두 예외를 발생하도록 수정했습니다!
감사합니다!
There was a problem hiding this comment.
Controller에서 도메인을 활용해 흐름을 제어하자 라는 생각에 "게임의 흐름"을 담당하는 클래스의 필요 유무를 느끼지 못해서 삭제했습니다.
현재 Controller의 collectPlayerResults, calculatePlayerProfits, calculateDealerResult 메서드들은 그대로 BlackjackGame에 옮겨도 위화감이 없다고 느껴져서, Controller에서 수행하지 않아도 될 거 같다는 생각이 드네요.
너무 도메인을 직접 활용하려고 하니 Controller가 비대해진 느낌도 듭니다.
리팩토링을 통해 BlackjackGame을 다시 만들지 않은 이유는 HitStand 로직이 결국 getPlayers를 통해 컨트롤러에서 수행되어야 하기 때문인 거 같습니다.
약간 반쪽짜리 흐름 제어 객체다 라는 느낌이 들어 선뜻 다시 만들고 싶진 않았던 거 같아요 😭
더 깔끔한 (상태를 보관할 수 있는) 도메인을 만들어 냈다면, BlackjackGame의 역할도 분명하게 나뉠 수 있었을 거 같은데, 도메인 설계 역량이 부족한 탓이라는 생각도 드네요 😭
There was a problem hiding this comment.
상태 패턴 도입 배경은 학습을 위해서 일 것 같은데 맞을까요? 😄
상태 패턴을 도입하면서 어떤 장점이 느껴졌나요?
There was a problem hiding this comment.
LMS의 강의 글을 통해 상태 패턴을 적용할 수 있음을 깨달아 학습을 위해서 적용해 봤습니다.
상태 패턴을 적용하기 전에는 플레이어가 어떤 상태인지 cards에 계속해서 질의를 날려 계산해야 했습니다.
또한, 상태별 행위(draw, stay)가 구분되지 않는 하나의 메서드에서 뭉쳐져 있어 두 행위를 구분하기 어려웠습니다.
상태 패턴을 도입하고 상태별 행위가 메서드로 분명히 구분될 수 있었고, 메서드의 결과에 따라 상태 구현체가 변경되면서 자동으로 동작이 변경되어 "상태가 변경되었는가?"에 대한 확인 수요가 없어졌습니다.
결과적으로 유저가 Hit인지, Bust인지 확인하지 않고, 그저 클라이언트는 draw()를 호출하기만 하면 될 뿐이었습니다.
이런 부분이 정말 좋았던 것 같습니다!
다음 미션때도 적용할 수 있는 부분이 있다면 꼭 고려해 적용해 보고 싶네요!
src/main/java/domain/state/Hit.java
Outdated
| public State draw(Card card) { | ||
| hand.add(card); | ||
| if (hand.isBust()) { | ||
| return new Bust(hand); | ||
| } | ||
| return new Hit(hand); |
src/main/java/domain/state/Hit.java
Outdated
| hand.add(card); | ||
| if (hand.isBust()) { | ||
| return new Bust(hand); | ||
| } | ||
| return new Hit(hand); |
There was a problem hiding this comment.
상태 전이 시 hand 를 그대로 넘겨주고 있는데
가능하면 새로 만들거나 불변으로 넘겨주는것은 어떻게 생각하시나요?
어떤 장점이 있을까요~
There was a problem hiding this comment.
가능하면 새로 만들거나 불변으로 넘겨주는것은 어떻게 생각하시나요?
저는 이 부분이 "기존 객체(컬렉션)가, 전이된 상태에 영향을 줄 수 없는 구조로 바꾸는 것은 어떤가?" 라고 해석됐습니다.
이를 바탕으로 생각해 보니, 현재 코드는 state의 객체는 계속해서 바뀌는데, hand 자체는 같은 객체로 유지되고 있었습니다.
만약 외부에서 hand를 변경하면, 이를 가지고 있는 상태는 책임과 맞지 않는 값을 지니게 됩니다.
예를 들면, 블랙잭 상태인 상태의 hand에 클로버 7을 추가하면, 손패 상태는 버스트인데 상태 자체는 블랙잭인 미스매치가 발생하게 됩니다.
이로 인해 의도치 않은 동작이 수행될 수 있다고 판단이 드네요!
현재 구조상 불변으로 넘겨주는 것은 불가능할 거 같아서 깊은 복사(기존 컬렉션과 연결을 끊어서 제공)하는 방법으로 수정했습니다!
감사합니다
There was a problem hiding this comment.
LMS의 강의 글을 통해 상태 패턴을 적용할 수 있음을 깨달아 학습을 위해서 적용해 봤습니다.
상태 패턴을 적용하기 전에는 플레이어가 어떤 상태인지 cards에 계속해서 질의를 날려 계산해야 했습니다.
또한, 상태별 행위(draw, stay)가 구분되지 않는 하나의 메서드에서 뭉쳐져 있어 두 행위를 구분하기 어려웠습니다.
상태 패턴을 도입하고 상태별 행위가 메서드로 분명히 구분될 수 있었고, 메서드의 결과에 따라 상태 구현체가 변경되면서 자동으로 동작이 변경되어 "상태가 변경되었는가?"에 대한 확인 수요가 없어졌습니다.
결과적으로 유저가 Hit인지, Bust인지 확인하지 않고, 그저 클라이언트는 draw()를 호출하기만 하면 될 뿐이었습니다.
이런 부분이 정말 좋았던 것 같습니다!
다음 미션때도 적용할 수 있는 부분이 있다면 꼭 고려해 적용해 보고 싶네요!
사이클 2 블랙잭 미션 제출합니다! 🙋🏻♂️
저번 미션에서는 제출이 늦었지만, 이번에는 가이드에 따라 기능 구현 완료 시점에 맞춰 바로 제출합니다!
사이클 1에서 주신 피드백을 모두 반영하고 싶었으나, 우선순위를 신규 기능 구현(제출 기간 고려)에 두어 아직 반영하지 못한 부분이 많습니다. 😢
리뷰어님이 많은 리뷰이를 관리하시느라 이전 피드백을 기억하시기 어려울 수 있으니, 지난 피드백 중북 여부와 상관없이 편하게 피드백 남겨주세요! 😃
지난 피드백과 종합하여 반영하겠습니다!
체크 리스트
test를 실행했을 때, 모든 테스트가 정상적으로 통과했나요?어떤 부분에 집중하여 리뷰해야 할까요?
금액 처리에 대하여
[현재 상황]
사용자의 자산과 관련된 금액 데이터는 엄격해야 한다고 들어서, 이번 미션에서는 이 부분을 신경써보고 싶었습니다. 현재는 단판이지만, 여러 라운드가 진행되는 상황과 금액 제한 없는 배팅이 가능하도록 혼자만의 규칙을 세워 고민했습니다.
[고민 지점]
블랙잭 승리 시 배당률(1.5배)로 인해 소수점이 발생할 수 있는 상황에서, 두 가지 방향을 검토했습니다.
[최종 결정: BigDecimal]
두 방식 모두 구현해 본 결과, BigDecimal이 더 명확하게 관리할 수 있다고 판단하여 선택했습니다.
Player와 BetMoney 설계
[현재 상황]
현재 BlackjackGame이
List<String>으로 이름을 한 번에 받아 플레이어를 생성하는 구조다 보니, 이름 입력 후 배팅 금액을 추가로 받는 과정에서 설계를 세 가지 방향으로 고민했습니다.1번: Player에서 BetMoney 필드를 final로 관리 & BetMoney 가변
장점 : 기존 생성 방식 유지 가능
단점: BetMoney가 가변으로, 방어적 복사 필요 및 잠재적 버그 위험 존재, 결국 setter가 필요함.
2번: Player에서 BetMoney final없이 관리 & BetMoney 불변
장점 : 기존 생성 방식 유지 가능, BetMoney 불변으로 관리 가능
단점: Setter 사용 필요, 객체 생성 후 상태가 변하므로 잠재적 버그 위험 존재
3번: Player에서 BetMoney 필드를 final로 관리 & BetMoney 불변
장점 : 모두 불변으로, 잠재적 버그 위험에서 상대적으로 안전함.
단점: 현재 생성 로직 전면 수정 필요 및 View에서 이름/금액을 모두 한 번에 넘겨야 함
저는 우선 빠른 구현을 위해 2번을 선택했습니다.
금액 데이터(BetMoney) 자체는 불변하게 보호할 수 있었으나, 여전히 Player의 Setter를 통해 상태가 변경될 수 있다는 점이 마음에 걸렸습니다.
그래서 구조적 안전성을 위해 3번으로 리팩토링을 수행할까 합니다. (아직 못 했습니다!)
다만 3번 도입 시 발생하는 중복 검증에 대해 고민해 보았고, 다음과 같은 결론을 내렸습니다.
결국 다음과 같은 구조를 갖게됩니다:
[질문]
위와 같은 상황(입력 시기가 다른 데이터를 처리할 때)에 더 적절한 방법이 있을까요?
3번으로 리팩토링을 수행하기로 결정한 이유와 사고 과정은 타당하다고 생각하시나요?
도메인과 입출력의 분리에 대해서 (03.13 20:15 추가)
[질문]
"입력 방식의 추가로 도메인이 수정되는 상황"에 대해 크루와 토론을 통해 "입력 방식이 도메인에 영향을 주는 구조는 적절하지 않다" 라는 결론에 도달했습니다.
도메인은 외부의 입력 방식과 무관하게 본질적인 형태를 유지하고, Controller나 View 같은 외부 계층에서 도메인이 원하는 형태로 데이터를 가공해서 넘겨줘야 한다는 의견인데요!
이런 방향성은 적절할까요? 현업에서도 이런 구조로 개발이 진행되는지 궁금합니다!