-
Notifications
You must be signed in to change notification settings - Fork 196
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
[Step3] 3단계 - 기능 우선 패키지 구성하기 #477
base: suzhanlee
Are you sure you want to change the base?
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.
안녕하세요, 수찬님. 리뷰가 늦어진 점 양해 부탁드립니다.
비즈니스 확장을 염두에 두고 미션을 진행해보시면 더 의미 있는 경험이 될 것 같습니다.
또한, 외부 서비스와의 통신 스펙(인터페이스)을 어디에 두는 것이 DIP 원칙에 부합할지 고민해보시면 더욱 좋은 학습이 될 것 같습니다.
관련해서 코멘트 남겨두었는데 확인 부탁드릴게요.
@@ -1,4 +1,4 @@ | |||
package kitchenpos.infra; | |||
package kitchenpos.menu.infrastructure.external; | |||
|
|||
public interface PurgomalumClient { |
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.
@@ -1,4 +1,4 @@ | |||
package kitchenpos.domain; |
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.
매장 내 식사 주문, 테이크 아웃 주문, 배달 주문이 한 곳에 뭉쳐있네요.
같은 주문이어도 바운디드 컨택스트(모델의 경계)가 다르다고 생각하는데요.
분리해보는것은 어떨까요?
@@ -1,4 +1,4 @@ | |||
package kitchenpos.domain; |
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.
의식적으로 확장에 대한 가능성을 염두하고 미션을 진행해보는것도 좋을 것 같습니다.
그런 관점에서 메뉴랑 상품도 바운디드 컨택스트를 분리해볼 수 있을 것 같아요.
어떻게 생각하시나요?
=> port 를 만들어 domain에 의존하도록 수정
…이 없어 port/adaptor 가 아닌 domain/sevice에 위치
안녕하세요 리뷰어님! 진행한 점
이런 경우에는 문제를 어떤 방식으로 해결하는게 좋을까요? 항상 도움이 크게 되는 피드백을 주셔서 많이 배우고 있습니다 ㅎㅎ |
안녕하세요 수찬님. 고민을 많이 하시는 것 같아서 좋습니다. 1,2번 질문에 대한 답변) 도메인 레이어는 비즈니스 로직의 핵심을 담당하는 영역입니다. 외부 시스템에 대한 의존성을 제거하면, 외부 변경이 발생하더라도 핵심 비즈니스 로직을 수정할 필요가 없어 더 안정적인 구조를 만들 수 있습니다. 예를 들어, 기존처럼 PurgomalumClient를 인프라 레이어에 위치시킨다면, MenuService는 PurgomalumClient의 시그니처가 변경될 때 함께 영향을 받아 컴파일 에러가 발생할 수 있습니다. 이러한 의존성 문제는 도메인 레이어가 인프라 변경에 의해 보호되지 못한다는 의미이며, 이를 컴파일 타임 의존성을 가진다고 표현할 수 있습니다. 제가 의도했던 방향은 PurgomalumClient를 도메인이 아닌 애플리케이션 레이어로 이동하는 것이었습니다. 애플리케이션 레이어에서 이를 관리하면 도메인이 직접 외부 API와 결합되지 않도록 보호할 수 있으며, DIP를 통해 유연한 구조를 유지할 수 있습니다. 여기까지가 DIP 개념인데요. 헥사고날 아키텍처의 포트 어댑터 패턴은 DIP 개념을 확장한 것입니다. 인바운드 요청: 컨트롤러에서 도메인 레이어로 요청이 들어올 때, 도메인 레이어에서 정의한 인터페이스(포트) 규격에 맞춰 요청이 전달됩니다. 아웃바운드 요청: 도메인 레이어에서 외부 시스템으로 요청을 보낼 때도, 도메인이 직접 외부 시스템을 호출하지 않고 포트를 통해 통신하도록 합니다. 인바운드로 요청이 들어올 때도 도메인 레이어에 선언한 인터페이스 규격에 맞춰서 요청을 넣어주고, 아웃바운드로 요청이 나갈때도 도메인 레이어에서 선언한 인터페이스에 맞게 요청이 나가는것을 의미합니다. 아웃바운드 요청의 경우, DIP 개념과 동일하게 인터페이스(포트)를 활용하여 도메인과 외부 시스템의 결합을 제거합니다. 인바운드 요청의 경우에는 애초에 컴파일 타임 의존성이 컨트롤러 → 서비스 방향이므로 DIP를 적용할 필요는 없습니다. 도메인 레이어를 더욱 견고하게 보호하기 위해 애플리케이션 레이어에서 스펙을 명시하고, 컨트롤러가 이를 준수하도록 설계하는 것입니다. 하지만 좀 더 견고하게 도메인 레이어를 지키기 위해서 어플리케이션 레이어에서 스펙을 명시하고 컨트롤러는 이를 준수하도록 권장함으로써 도메인 레이어를 안전하게 지키기 위함입니다. 돌아와서, 질문에서 언급하신 포트와 어댑터 개념은 아웃바운드 요청을 다루는 부분으로 보입니다. 이는 DIP를 적용하기 위한 “인터페이스와 구현체”의 개념과 크게 다르지 않습니다. 즉, 포트는 도메인에 강하게 의존하는 것이 아니라, 오히려 도메인을 외부 변경으로부터 보호하기 위한 장치입니다. 따라서, “포트가 도메인에 강하게 의존해야 할 때 포트/어댑터 패턴을 사용한다”는 표현보다는, “도메인을 보호하기 위해 포트/어댑터 패턴을 사용한다”는 것이 더 적절한 표현입니다. 3번 질문에 대한 답변) 즉, 배달 주문, 매장 내 식사 주문, 포장 주문은 주문이라는 루트 애그리거트의 하위 개념이 아닙니다. 각각의 주문 유형이 공통적으로 “주문”이라는 속성을 가지고 있지만, 비즈니스적으로는 서로 다른 경계를 가집니다. 이들은 앞으로 확장될 비즈니스 로직이 다를 가능성이 높기 때문에, 별도의 바운디드 컨텍스트로 나누는 것이 더 적절합니다. 제안 드리는 방식은 아래처럼 패키지 구조를 잡거나, order 또는 아래처럼 잡는게 어떨까요? delivery_order 또한 주문이라는 애그리거트에 포장 주문, 매장 내 식사 주문, 배달 주문이라는 별도 엔티티를 엮는 것 보다 각각의 엔티티를 만들어보는것은 어떨까요? 한번 고민해보셨으면 좋겠습니다. 이 과정이 큰 도움이 될 것이라고 믿어요. |
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를 기반으로 최대한 정리해봤습니다 ㅎㅎ)
감사합니다!