Skip to content

HJ-Rich/jwp-refactoring

 
 

Repository files navigation

우아한테크코스

레거시 코드 리팩터링 - Kitchen POS


Generic badge Generic badge Generic badge

우아한테크코스 웹 백엔드 4기, 레거시 코드 리팩터링 - Kitchen POS 저장소입니다.



요구 사항

  • kitchenpos 패키지의 코드를 보고 키친포스의 요구 사항을 README.md에 작성한다.
    • 미션을 진행함에 있어 이 문서를 적극 활용한다.
  • 정리한 키친포스의 요구 사항을 토대로 테스트 코드를 작성한다.
    • 모든 Business Object에 대한 테스트 코드를 작성한다.
    • @SpringBootTest를 이용한 통합 테스트 코드 또는 @ExtendWith(MockitoExtension.class)를 이용한 단위 테스트 코드를 작성한다.
    • Controller에 대한 테스트 코드 작성은 권장하지만 필수는 아니다.
    • 미션을 진행함에 있어 아래 문서를 적극 활용한다.



리팩터링 계획

  • E2E, 서비스, 컨트롤러 테스트 구현
  • RestDocs, ERD, Postman 문서화
  • Request, Response DTO 도입
  • 서비스 인터페이스 추상화
  • 1단계 테스트를 통한 코드 보호 PR
  • JdbcTempalte -> JPA 전환
  • 프로덕트, 메뉴그룹 name 유니크 제약조건 제거. 기존 프로덕션 로직 및 스키마에 없는 제약조건.
  • 도메인 엔티티에 유효성 검증 및 비즈니스 로직 내재화
  • 2단계 서비스 리팩터링 PR
  • 일급 컬렉션 도입
  • 도메인 엔티티 VO 적용
  • 메뉴 이름 변경 시 기존 주문 이력이 변경되지 않도록 구현
  • 클래스간, 패키지 간 단방향으로 리팩터링
  • 가장 많이 팔린 메뉴 조회 가능해야함
  • Flyway 도입
  • 메뉴 정보가 변경되더라도 주문 항목이 변경되지 않게 구현한다.
  • 3단계 의존성 리팩터링 PR
  • Gradle의 멀티 모듈 개념을 적용해 자유롭게 서로 다른 프로젝트로 분리해 본다.



진행 경과

  • 로직 분석 후, E2E -> 서비스 레이어 테스트를 먼저 구현했습니다.
  • RestDocs를 통한 컨트롤러 테스트와 문서화를 진행하던 도중 컨트롤러와 서비스 레이어의 의존을 분리했습니다
    • 기존에는 컨트롤러에서 RequestBody로 받는 매개변수도 도메인 객체로 받고 있었습니다.
    • 그로인해 레이어간 결합이 발생했고, 엔드포인트마다 어떤 데이터가 필요하고 사용되는지 파악하기 어려웠습니다.
    • DTO를 도입하여 서비스 레이어 내에서 도메인 객체로 변환하여 처리하도록 구성하였습니다.
    • 컨트롤러에서는 RequestDTO를 받도록 구성하여 서비스 레이어와 의존성을 분리했고, 어떤 데이터가 사용되는지 파악하기 쉬워졌습니다.
  • JDBC에서 JPA 기반으로 마이그레이션 완료하였습니다.



요구사항 정리



요구사항 요약

Product

  • 프로덕트 생성과 조회가 가능하다.
  • 프로덕트 생성 시 이름가격을 받는다.
    • 유효성 검사
      • 이름은 반드시 존재해야 하고, 유효한 문자가 1개 이상 존재해야 한다.
      • 가격은 반드시 존재해야 하고, 0 이상이어야 한다.
      • 이름은 중복될 수 없다.

Table

  • 테이블 생성과 조회, 주문 가능 여부 수정, 고객 인원 수정이 가능하다.
  • 테이블 생성 시 고객 인원 수와, 주문 가능 여부를 받는다.
    • 고객 인원 수 기본값은 0이다.
    • 주문 가능 여부 기본값은 주문 불가 이다.
    • 유효성 검사
      • 고객 인원 수는 0 이상이어야 한다.
  • 테이블 주문 가능 여부 수정 시 주문 가능 여부를 받는다
    • 유효성 검사
      • 수정 요청한 테이블 아이디에 매칭되는 테이블이 반드시 존재해야 한다.
      • 조회된 테이블에 그룹 아이디가 존재하지 않아야 한다. 즉, 단체로 묶여있는 테이블은 주문 가능 여부 수정이 불가하다.
      • 조회된 테이블에 조리시작(COOKING) 또는 식사중(MEAL) 상태인 주문이 없어야 한다. 즉, 계산 완료(COMPLETION) 상태여야 수정할 수 있다.
  • 테이블 고객 인원 수정 시 고객 인원 수를 받는다
    • 유효성 검사
      • 고객 인원 수는 0 이상이어야 한다.
      • 수정 요청한 테이블 아이디에 매칭되는 테이블이 반드시 존재해야 한다.
      • 조회된 테이블이 주문 불가 상태일 경우 예외이다. 주문 불가 테이블에 대한 인원 수정 요청은 잘못된 요청이다.

Menu

  • 메뉴 생성, 조회가 가능하다.
  • 메뉴 생성 시 이름, 가격, 메뉴 그룹 아이디, 메뉴 프로덕트 목록을 받는다. 메뉴 프로덕트 목록은 프로덕트 아이디와 수량을 담은 배열이다.
    • 유효성 검사
      • 가격은 반드시 존재해야 하고, 0 이상이어야 한다.
      • 메뉴 그룹 아이디는 실재하는 유효한 아이디여야 한다. 즉, 메뉴 생성 시점부터 메뉴는 특정 메뉴 그룹에 속해야 한다.
      • 메뉴 프로덕트 목록은 반드시 존재해야 하고, 1개 이상의 메뉴 프로덕트가 담겨있어야 한다.
      • 메뉴 가격은 메뉴 프로덕트 목록의 총합계액 보다 클 수 없다. 즉, 낱개의 합 보다 더 비싸게 가격을 책정할 수 없다.
        • 0 <= 메뉴 가격 <= 메뉴 프로덕트 목록 총합계액

Table Groups

  • 테이블 그룹은 테이블을 묶어서 단체 손님으로 설정하는 것을 의미한다.
  • 테이블 그룹의 생성과 삭제가 가능하다.
  • 테이블 그룹 생성 시 그룹화할 테이블 아이디 목록을 받는다.
    • 유효성 검사
      • 테이블 아이디 목록은 반드시 존재해야 하고, 2개 이상의 테이블 아이디가 존재해야 한다.
      • 모든 테이블 아이디 마다 각각 매칭되는 테이블이 반드시 존재해야 한다.
      • 모든 테이블이 다른 그룹에 이미 할당되어 있지 않아야 한다. 즉, 테이블 그룹 아이디가 없어야 한다.
      • 모든 테이블이 주문 불가 상태 상태여야 한다.
    • 테이블 그룹으로 묶여질 때 모든 테이블의 주문 가능 여부가 주문 가능으로 변경된다.
  • 테이블 그룹 삭제 시 테이블 그룹 아이디를 받는다.
    • 유효성 검사
      • 테이블 그룹 아이디로 조회된 모든 테이블에 조리 시작(COOKING) 또는 식사중(MEAL) 상태인 주문이 존재하지 않아야 한다
    • 테이블 그룹 삭제 시 모든 테이블의 테이블 그룹아이디가 제거된다

Menu Groups

  • 메뉴 그룹은 개별 메뉴가 소속되는 곳이다. 가령 한 마리 메뉴 라는 메뉴 그룹에 후라이드 한 마리가 속하는 식이다.
  • 메뉴 그룹 생성, 조회가 가능하다
  • 메뉴 그룹 생성 시 이름을 받는다.
    • 유효성 검사
      • 이름은 반드시 존재해야 하고, 공백이 아닌 문자가 존재해야 한다.
      • 이름은 중복되지 않아야 한다.

Order

  • 주문 생성, 전체 조회, 주문 상태 수정이 가능하다
  • 주문 생성 시 테이블 아이디, 주문 아이템 목록을 받는다 주문 아이템 목록의 요소는 메뉴 아이디와 수량이다.
    • 유효성 검사
      • 주문 아이템 목록은 반드시 존재해야 하고 하나 이상의 요소를 가지고 있어야 한다.
      • 메뉴 아이템 목록 내 모든 메뉴 아이디가 실재하는 유효한 메뉴 아이디여야 한다.
      • 테이블 아이디로 조회한 테이블이 주문 가능한 상태여야 한다.
  • 주문 상태 수정 시 주문 아이디와 수정하고자 하는 주문 상태값을 받는다.
    • 유효성 검사
      • 요청한 주문 아이디로 주문을 조회했을 때 존재하지 않으면 예외이다.
      • 주문의 상태가 이미 계산 완료(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 포장하지 않고 매장에서 식사하는 것



About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 54.8%
  • HTML 45.2%