-
Notifications
You must be signed in to change notification settings - Fork 153
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 (매장 식사 주문) #246
base: yuhwanwoo
Are you sure you want to change the base?
step3 (매장 식사 주문) #246
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.
환우님 안녕하세요 :)
미션 고생하셨습니다 👍
코멘트 달아놓은 것이 있는데 확인 부탁드려요!
@Column(name = "type", nullable = false) | ||
@Enumerated(EnumType.STRING) | ||
private OrderType type; |
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.
각각의 주문별로 바운디드 컨텍스트로 나누고 각각의 Table 도 분리해주신 것으로 보여져요. 😄
그렇다면 OrderType 을 제거해보는 것은 어떤가요?
Optional<Menu> findById(UUID id); | ||
List<Menu> findAllByIdIn(List<UUID> ids); |
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.
현재 주문 -> 메뉴로 한방향으로만 결합되어 있지만, 주문에서 메뉴 엔티티에 관심이 있기 보다는 메뉴의 가격과 노출여부, 등록되어 있는 메뉴여부에 더 관심이 있지 않을까 생각해요.
반환할 때 주문에서 필요한 정보만 VO를 새로 만들어서 리턴하는 것은 어떤가요?
@Transactional | ||
public EatInOrderDto complete(UUID orderId) { | ||
EatInOrder eatInOrder = eatInOrderRepository.findById(orderId) | ||
.orElseThrow(NoSuchElementException::new); | ||
eatInOrder.complete(); | ||
|
||
OrderTable orderTable = orderTableRepository.findById(eatInOrder.getOrderTable().getId()) | ||
.orElseThrow(NoSuchElementException::new); | ||
if (!eatInOrderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { | ||
orderTable.clear(); | ||
} | ||
return ConvertUtil.convert(eatInOrder, EatInOrderDto.class); | ||
} |
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.
전 주문 상태 Served로 수정했습니다! 🙇
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.
말씀드리고 싶었던 것은 현재 로직 중에 도메인로직으로 보이는 부분이 있어서 도메인 계층으로 위임하면 어떨까 의견을 드려본 것이였어요 😄
주문완료하는 로직에서 주문테이블과 매장주문 애그리거트간의 협력도 필요하다고 봐요.
그렇기 때문에 도메인 계층으로 위임할 때 여러 고민도 해보시면 좋을 것 같아서요
OrderTable
의 추가Order
는OrderTable
에 계속 쌓이며 모든EatInOrder
가 완료되면EmptyTable
이 된다.
Completed
가 되려면 전 주문은Served
상태여야 한다.
모델링 해주신 것을 봤을 때는 지금처럼 구현한 것도 좋지만, 응용계층에서 도메인에 대한 제어가 더 많아질 것 같아요
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.
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.
@ManyToOne | ||
@JoinColumn( | ||
name = "order_table_id", | ||
columnDefinition = "binary(16)", | ||
foreignKey = @ForeignKey(name = "fk_orders_to_order_table") | ||
) | ||
private OrderTable orderTable; |
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.
저는 환우님이 매장주문 컨텍스트에서 루트 애그리거트를 매장주문과 주문테이블 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.
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.
아 이해했습니다 감사합니다!
@@ -0,0 +1,71 @@ | |||
package kitchenpos.eatinorders.tobe.domain.ordertable; |
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.
매장 주문 애그리거트와 주문테이블 애그리거트를 패키지를 통해 분리해주셨네요 👍 👍
README.md
Outdated
| 한글명 | 영문명 | 설명 | | ||
| --- | --- |------------------------------------------------| | ||
| 배달 | delivering | 배달원이 매장을 방문하여 배달 음식의 픽업을 완료하고 배달을 시작하는 단계 | | ||
| 배달 대행사 | delivery agency | 준비한 음식을 고객에게 직접 배달하는 서비스 | | ||
| 배달 완료 | delivered | 배달원이 주문한 음식을 고객에게 배달 완료한 단계 | | ||
| 서빙 | served | 조리가 완료되어 음식이 나갈 수 있는 단계 | | ||
| 완료 | completed | 배달이 완료된 후 주문을 마무리 하는 단계 | | ||
| 접수 | accepted | 주문을 받고 음식을 조리하는 단계 | | ||
| 접수 대기 | waiting | 주문이 생성되어 매장으로 전달된 단계 | | ||
| 주문 | order | 집이나 직장 등 고객이 선택한 주소로 음식을 배달한다. | | ||
| 주문 상태 | order status | 주문이 생성되면 매장에서 주문을 접수하고 고객이 음식을 받기까지의 단계를 표시한다. | | ||
| 주문 항목 | order line item | 주문에 속하는 수량이 있는 메뉴 | | ||
| 주문 항목 | order line item | 주문에 속하는 수량이 있는 메뉴 | |
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.
환우님 안녕하세요 :)
리뷰가 너무 늦어져서 죄송합니다 🙏
개인적인 일들이 많아지면서 알림을 놓쳤습니다
피드백 잘 반영해주셨고 코멘트 추가한 부분이 있는데요 확인부탁드려요!
즐거운 주말되세요 😄
protected DeliveryOrder() { | ||
} | ||
|
||
public DeliveryOrder(UUID id, OrderStatus status, LocalDateTime orderDateTime, DeliveryOrderLineItems orderLineItems, DeliveryOrderAddress deliveryAddress) { |
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.
이 부분에 대해 고민을 했던 부분이
처음 주문을 생성하면 WAITING이라는 조건 때문에 정적 팩토리메소드로 생성 시 무조건 WAITING 상태로 DeliveryOrder를 생성 하는데요,
이렇게 되면 테스트 코드 작성 시 다른 상태값을 생성하지 못해 public으로 두었습니다.
정적 팩토리 메소드를 통해서 생성시에도 상태를 받도록 변경하는 하고 테스트 코드도 of를 통해 생성하는 쪽이 좋을까요?
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.
저도 많은 고민을 했었는데요~ 테스트코드를 작성하기 위해 프로덕션 코드에 손이 가는 것이 괜찮을까? 고민이 들기는 했어요.
정적 팩토리 메소드를 통해서 생성시에도 상태를 받도록 변경하는 하고 테스트 코드도 of를 통해 생성하는 쪽이 좋을까요?
말씀주신 방법으로 구현해도 좋아요. 다만, 프로덕션 코드에서는 배달주문을 생성할 때 Status 값이 무조건 WAITING 이라는 점때문에 찜찜하실수 있을 것 같아요
이런경우면 of 정적팩토리메서드 대신 ReflectionTestUtils
을 이용하는 방법도 있고, Fixture 를 이용하는 방법도 있을 것 같아요
위의 2가지 방법도 같이 찾아보시면서 고려해보시면 좋을 것 같아요 😄
@ManyToOne | ||
@JoinColumn( | ||
name = "order_table_id", | ||
columnDefinition = "binary(16)", | ||
foreignKey = @ForeignKey(name = "fk_orders_to_order_table") | ||
) | ||
private OrderTable orderTable; |
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개로 구성해주신것으로 저는 생각했어요~
저는 직접참조와 간접참조에 대해 루트애그리거트 내에서는 직접참조를 하고 루트 애그리거트 간은 간접참조하는 것이 좋다고 생각하고 있어요
루트 애그리거트의 핵심역할 중 하나가 애그리거트의 일관성은 깨지지 않도록 하는 것이기 때문에 타 애그리거트를 참조하게 되면 타 애그리거트를 수정하는 이슈가 발생할 수 있지 않을까해요.
@Transactional | ||
public EatInOrderDto complete(UUID orderId) { | ||
EatInOrder eatInOrder = eatInOrderRepository.findById(orderId) | ||
.orElseThrow(NoSuchElementException::new); | ||
eatInOrder.complete(); | ||
|
||
OrderTable orderTable = orderTableRepository.findById(eatInOrder.getOrderTable().getId()) | ||
.orElseThrow(NoSuchElementException::new); | ||
if (!eatInOrderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { | ||
orderTable.clear(); | ||
} | ||
return ConvertUtil.convert(eatInOrder, EatInOrderDto.class); | ||
} |
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.
말씀드리고 싶었던 것은 현재 로직 중에 도메인로직으로 보이는 부분이 있어서 도메인 계층으로 위임하면 어떨까 의견을 드려본 것이였어요 😄
주문완료하는 로직에서 주문테이블과 매장주문 애그리거트간의 협력도 필요하다고 봐요.
그렇기 때문에 도메인 계층으로 위임할 때 여러 고민도 해보시면 좋을 것 같아서요
OrderTable
의 추가Order
는OrderTable
에 계속 쌓이며 모든EatInOrder
가 완료되면EmptyTable
이 된다.
Completed
가 되려면 전 주문은Served
상태여야 한다.
모델링 해주신 것을 봤을 때는 지금처럼 구현한 것도 좋지만, 응용계층에서 도메인에 대한 제어가 더 많아질 것 같아요
- `EatInOrder`는 식별자와 `OrderStatus`, 주문 시간, `OrderLineItems`를 가진다. | ||
- `Menu`가 `Display Menu`되고 있으며 판매되는 메뉴 가격과 일치하면 `EatInOrder`가 생성된다. | ||
- `EatInOrder`는 접수 대기 ➜ 접수 ➜ 서빙 ➜ 계산 완료 순서로 진행된다. | ||
- `EatInOrder`가 생성되면 `OrderStatus`는 `Waiting` 상태이다. | ||
- `Accepted` 가 되려면 전 주문은 `Waiting` 상태여야 한다. | ||
- `Served` 가 되려면 전 주문은 `Accepted` 상태여야 한다. | ||
- `Completed` 가 되려면 전 주문은 `Served` 상태여야 한다. |
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.
모델링 업데이트 👍 👍
전략적 설계를 하면서 구성하신 모델링과 실제 구현한 코드간의 싱크를 맞춰주시는 것에 대해서도 꾸준히 유지보수가 필요하다고 생각해요
모델링과 구현코드간의 싱크가 맞지 않으면, 멘탈모델이 일치하지 않아 결국 DDD 도입 전과 같은 문제들이 계속 발생하게 되는 이슈가 있어요 😢
|
||
@Column(name = "type", nullable = false) | ||
@Enumerated(EnumType.STRING) | ||
private OrderType type; | ||
|
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.
피드백 잘 반영해주셨어요 👍 👍
배달주문뿐만 아니라 다른 주문도 같이 반영해보는 것은 어떤가요?
if (status != OrderStatus.ACCEPTED) { | ||
if (status != OrderStatus.SERVED) { |
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.
테스트 코드가 있으면 지금과 같은 상황이 없지 않을까 생각이 들어요 😄
도메인에 대한 테스트 코드가 많이 없는 것 같더라구요 😢
테스트 코드도 작성해보는 것은 어떤가요?
리뷰어님 안녕하세요.
배달 주문과 매장 주문에 대한 리팩토링을 진행했습니다.
질문이 일단 있는데요!
배달과 매장 주문 컨텍스트에서 menu client를 각각 작성했는데 사실 같은 기능인데
공통적으로 주문에 대한 패키지를 만드는 것이 맞을까요?
감사합니다! 🙇