상품(product)
을 생성한다.- 가격은 필수이고, 0원 이상이 아니면
상품(product)
을 생성할 수 없다.
- 가격은 필수이고, 0원 이상이 아니면
- 모든
상품(product)
목록을 조회한다.
메뉴 그룹(menu group)
을 생성한다.- 모든
메뉴 그룹(menu group)
목록을 조회한다.
메뉴(menu)
를 생성한다.- 가격은 필수이고, 0원 이상이 아니면
메뉴(menu)
를 생성할 수 없다. 메뉴(menu)
가 속한메뉴 그룹(menu group)
이 없으면메뉴(menu)
를 생성할 수 없다.메뉴(menu)
는 등록된메뉴 상품(menu product)
이 없을 수도 있고, 포함할 수도 있다.메뉴(menu)
의 가격이메뉴 상품(menu product)
의 가격의 합보다 크면메뉴(menu)
를 생성할 수 없다.
- 가격은 필수이고, 0원 이상이 아니면
- 모든
메뉴(menu)
목록을 조회한다.- 각
메뉴(menu)
의메뉴 상품(menu product)
을 같이 조회한다.
- 각
주문(order)
을 생성한다.주문(order)
에 필요한 주문 메뉴를 담은주문 항목(order line item)
이 없으면주문(order)
을 생성할 수 없다.- 모든
주문 항목(order line item)
의메뉴(menu)
는 등록되어 있어야한다. 주문(order)
할주문 테이블(order table)
이 없으면,주문(order)
을 생성할 수 없다.주문(order)
이 되면주문 상태(order status)
는 'COOKING' 이다.
- 모든
주문(order)
목록을 조회한다.- 각
주문(order)
의주문 항목(order line item)
을 같이 조회한다.
- 각
주문(order)
의주문 상태(order status)
를 변경한다.주문 상태(order status)
가 'COMPLETION' 인 경우 상태를 변경할 수 없다.
주문 테이블(order table)
을 생성한다.- 모든
주문 테이블(order table)
목록을 조회한다. 주문 테이블(order table)
을 비어있는 상태로 변경한다.주문 테이블(order table)
이 존재해야한다.주문 테이블(order table)
이단체 지정(table group)
되어 있으면 비어있는 상태로 변경할 수 없다.주문 테이블(order table)
의주문 상태(order status)
가 'COOKING' 이나 'MEAL' 상태가 이면 비어있는 상태로 변경할 수 없다.
주문 테이블(order table)
에방문한 손님 수(number of guests)
를 변경한다.- 하나의
주문 테이블(order table)
의방문한 손님 수(number of guests)
가 0명보다 적으면,방문한 손님 수(number of guests)
를 변경할 수 없다. 주문 테이블(order table)
이 비어있으면,방문한 손님 수(number of guests)
를 변경할 수 없다.
- 하나의
단체 지정(table group)
을 생성한다.단체 지정(table group)
으로 등록할주문 테이블(order table)
이 2개 미만이면 생성할 수 없다.단체 지정(table group)
할주문 테이블(order table)
은 비어있어야한다.단체 지정(table group)
할주문 테이블(order table)
이단체 지정(table group)
되어있으면 생성할 수 없다.
단체 지정(table group)
을 해제한다.단체 지정(table group)
된주문 테이블(order table)
에서주문 상태(order status)
가 'COOKING' 이나 'MEAL' 이면 해제할 수 없다.
주문 상태(order status)
는 'COOKING'(조리중), 'MEAL'(식사중), 'COMPLETION'(계산완료) 로 구성된다.주문 상태(order status)
의 상태 변경 순서는 'COOKING'(조리중) -> 'MEAL'(식사중) -> 'COMPLETION'(계산완료) 진행된다.
한글명 | 영문명 | 설명 |
---|---|---|
상품 | product | 메뉴를 관리하는 기준이 되는 데이터 |
메뉴 그룹 | menu group | 메뉴 묶음, 분류 |
메뉴 | menu | 메뉴 그룹에 속하는 실제 주문 가능 단위 |
메뉴 상품 | menu product | 메뉴에 속하는 수량이 있는 상품 |
금액 | amount | 가격 * 수량 |
주문 테이블 | order table | 매장에서 주문이 발생하는 영역 |
빈 테이블 | empty table | 주문을 등록할 수 없는 주문 테이블 |
주문 | order | 매장에서 발생하는 주문 |
주문 상태 | order status | 주문은 조리 ➜ 식사 ➜ 계산 완료 순서로 진행된다. |
방문한 손님 수 | number of guests | 필수 사항은 아니며 주문은 0명으로 등록할 수 있다. |
단체 지정 | table group | 통합 계산을 위해 개별 주문 테이블을 그룹화하는 기능 |
주문 항목 | order line item | 주문에 속하는 수량이 있는 메뉴 |
매장 식사 | eat in | 포장하지 않고 매장에서 식사하는 것 |
- 실제 변경 코드의 테스트를 고려하여, Service Layer 테스트를 통합 테스트로 변경
- Product 통합 테스트 적용
- test case -
상품
을 생성한다. - test case - 가격은 필수이고, 0원 이상이 아니면
상품
을 생성할 수 없다. - test case - 모든
상품
목록을 조회한다. - Service Layer 테스트 케이스 리팩터링
- test case -
- MenuGroup 통합 테스트 적용
- test case -
메뉴 그룹
을 생성한다. - test case - 모든
메뉴 그룹
목록을 조회한다. - Service Layer 테스트 케이스 리팩터링
- test case -
- Menu 통합 테스트 적용
- Menu Service Layer 테스트의 재사용되는 코드 응집화
- test case -
메뉴
를 생성한다. - test case - 가격은 필수이고, 0원 이상이 아니면
메뉴
를 생성할 수 없다. - test case -
메뉴
의 가격이메뉴 상품
의 가격의 합보다 크면메뉴
를 생성할 수 없다. - test case - 모든
메뉴
목록을 조회한다. - Service Layer 테스트 케이스 리팩터링
- OrderTable 통합 테스트 적용
- test case -
주문 테이블
을 생성한다. - test case -
주문 테이블
을 비어있는 상태로 변경한다. - test case -
주문 테이블
이단체 지정
되어 있으면 비어있는 상태로 변경할 수 없다. - test case -
주문 테이블
의주문 상태
가 'COOKING' 이나 'MEAL' 상태가 이면 비어있는 상태로 변경할 수 없다. - test case -
주문 테이블
에방문한 손님 수
를 변경한다. - test case - 하나의
주문 테이블
의방문한 손님 수
가 0명보다 적으면,방문한 손님 수
를 변경할 수 없다. - test case -
주문 테이블
이 비어있으면,방문한 손님 수
를 변경할 수 없다. - test case - 모든
주문 테이블
목록을 조회한다. - Service Layer 테스트 케이스 리팩터링
- test case -
- Order 통합 테스트 적용
- test case -
주문
을 생성한다. - test case -
주문
에 필요한 주문 메뉴를 담은주문 항목
이 없으면주문
을 생성할 수 없다. - test case -
주문
할주문 테이블
이 없으면,주문
을 생성할 수 없다. - test case - 모든
주문
목록을 조회한다. - test case -
주문
의주문 상태
를 변경한다. - test case -
주문 상태
가 'COMPLETION' 인 경우 상태를 변경할 수 없다.
- test case -
- TableGroup 통합 테스트 적용
- test case -
단체 지정
을 생성한다. - test case -
단체 지정
으로 등록할주문 테이블
이 2개 미만이면 생성할 수 없다. - test case -
단체 지정
할주문 테이블
은 비어있어야한다. - test case -
단체 지정
할주문 테이블
이단체 지정
되어있으면 생성할 수 없다. - test case -
단체 지정
을 해제한다. - test case -
단체 지정
된주문 테이블
에서주문 상태
가 'COOKING' 이나 'MEAL' 이면 해제할 수 없다. - Service Layer 테스트 케이스 리팩터링
- test case -
- Product 통합 테스트 적용
- Domain Logic 개선에 앞서, UI 전달되는 Domain Context를 Service Layer에 격리
- Product
- Service Layer에 Request DTO 적용
- Service Layer에 Response DTO 적용
- MenuGroup
- Service Layer에 Request DTO 적용
- Service Layer에 Response DTO 적용
- Menu
- Service Layer에 Request DTO 적용
- Service Layer에 Response DTO 적용
- OrderTable
- Service Layer에 Request DTO 적용
- Service Layer에 Response DTO 적용
- Order
- Service Layer에 Request DTO 적용
- Service Layer에 Response DTO 적용
- Order와 Menu의 정보와 갯수를 전달하기 위한 Request DTO 적용
- TableGroup
- Service Layer에 Request DTO 적용
- Service Layer에 Response DTO 적용
- TableGroup에서 OrderTable들과의 정보와 갯수를 전달하기 위한 Request DTO 적용
- Product
- Service Layer에 있는 Domain Logic를 Domain Layer로 이동
- OrderTable
- Service method 개선 : OrderTable 생성
- Service method 개선 : OrderTable Status 변경
- Service method 개선 : OrderTable 손님 수 변경
- Product
- Service method 개선 : Product 생성
- Order
- Service method 개선 : Order 생성
- Service method 개선 : Order Status 변경
- Menu
- Service method 개선 : Menu 생성
- TableGroup
- Service method 개선 : TableGroup 생성
- Service method 개선 : TableGroup 단체 지정 해제
- OrderTable
- JPA 도메인 리팩터링
- 모든 도메인에서 사용하는 PK와 시간 추상화 적용
- Product
- JPA Entity, Repository 적용
- price 필드 Embedded 타입 반영
- OrderTable
- JPA Entity, Repository 적용
- TableGroup
- JPA Entity, Repository 적용
- 잘못 지정된 orderTables의 @OneToMany 옵션 개선
- MenuProduct
- JPA Entity, Repository 적용
- 엔티티 필드 연관 관계 개선
- MenuGroup
- JPA Entity, Repository 적용
- Menu
- JPA Entity, Repository 적용
- 엔티티 필드 연관 관계 개선
- price 필드 Embedded 타입 반영
- 필드 제약사항 추가와 파라미터 검증
- OrderMenu
- JPA Entity, Repository 적용
- Order
- JPA Entity, Repository 적용
- 문자열 orderStatus @Enumerated OrderStatus 적용
- 누락된 필드 제약사항 수정
클래스간 방향 개선
- 보통 양방향이면 보통 "일대다" 관계의 성능상 이슈 때문에 개선 포인트가 된다.
- 또한, 이후에 서비스에 도메인을 다루게 되면서, 양방향으로 순환 참조되는 문제가 발생할 수도 있다. 그래서 컨텍스트를 끊어주어야한다.
- 성능적 이슈 때문에 "일대다" 관계를 없애고, "다대일"의 관계를 주인관계로 사용하고, "일대다" 정보를 어떻게 가져올지 생각해야한다.
- 물론 "일대다"로 가져오는 데이터의 갯수가 비즈니스에서 적다고 하면 문제가 발생하지 않는다. 하지만 유지보수 관점에서는 결국 기술부채라고 생각한다.
- 여기에서는 "일대다" 관계를 가진 엔티티의 필드를 제거하고, 쿼리를 통해서 직접 참조하는 방식으로 한다.
패키지 간 방향 개선
- DDD의 개념을 적용하면, 애그리거트 단위로 패키징을 하면 일관성 있는 구조를 가질 수 있다.
- 일관성이 확보되면 복잡한 도메인 모델을 단순하고 확장에 용이한 구조로 가져갈 수 있게 된다.
- 클래스 간 방향 개선
- 도메인 Menu-MenuProduct 간 도메인 일대다 제거
- 도메인 OrderTable-Order 간 도메인 일대다 제거
- 도메인 TableGroup-OrderTable 간 도메인 일대다 제거
- 도메인 Order-OrderMenu 간 도메인 일대다 제거
- 패키지 간 방향 개선
- Controller -> Service -> Domain Layer 별 방향성 단방향
- OrderTable-Order Service Layer에서 OrderTableAdapter를 통해서 양방향 참조 제거
- 이전 단계에서 패키지나 클래스 간 의존 방향을 단방향으로 정리하는 작업을 진행하였습니다. 하지만 여전히 유지보수 과정에서 코드를 변경하여 의존성이 꼬일 수 있는 여지가 존재합니다.
- 그래서 물리적인 코드 분리를 통해서 개발자가 의존성 방향을 인지할 수 있는 환경 구성이 필요하다고 생각합니다.
- 즉, 멀티모듈을 도입해서 서로 응집력 있는 코드들끼리 뭉쳐서, 응집도는 높이고, 멀티모듈로 분리해서 결합도를 낮추는게 필요하다고 생각합니다.
- 그리고 분리된 멀티모듈은 저장소에 버저닝하여 구분되어 관리될 수 있는 장점을 가질 수 있습니다.
- 또한 모듈을 필요한 곳에서 추가하여, 재사용성도 늘어날 수 있습니다.
모듈별 구성 내용
- web
- Controller, AcceptanceTest
- service
- Service, Dto, ServiceTest
- domain
- Entity, Repository, Infra
- 모듈 간 의존 관계를 설정할 때, 'api' 대신 'implementation'을 사용하여, 이후에 상속될 수 있는 의존성 제거
ex)
service에서 domain 의존설정
-> implementation project(':domain')
web에서 domain 의존설정
-> implementation project(':service')
-> implementation project(':domain')