회고

[우테코 6기 BE] 프리코스 4주차 회고 - 크리스마스 프로모션

띵지니어 2023. 11. 17. 17:14

🧑‍🎄 크리스마스 프로모션 링크

4주차 미션은 좀 특별하게 진행 되었기 때문에

private 저장소, PR 제출이 없이 진행 되었습니다.

미션 이후 public으로 변경


📃 과정

- 과제 시작

이번 미션은 마지막 미션만큼 가장 재미있는 미션이었습니다.

처음에 작업하는 방식, 제출 방식부터 달랐기 때문입니다.

첫 메일부터 흥미 진진 했습니다.

과제시작은 

과제 미션 저장소 -> Use Template 로 개인 레포를 만들고(private) -> ⭐️ Collaborator 초대하기

이 순서로 만들고 clone을 하여 진행을 해야 했습니다

 

- 또 중요했던 부분

평소에는 개인 브랜치를 파서 진행했어야 했었는데, 이번에는 main 브랜치에서 작업을 했어야 했습니다.

안하면? 응 0점 이야..

 

- 과제 내용 📃

 

과제 요구사항이 꽤 많았습니다.
그에 따라 README 에 예외 처리, 요구사항을 꼼꼼하게 확인하였습니다.
이번에 정리한 기능 목록입니다.

 

 

 

 

📑 README.md 전체 를 보려면 더보기를 클릭해 주세요!

더보기
# 크리스마스 프로모션
- 특히 `기능을 구현하기 전에 기능 목록`을 만들고, `기능 단위로 커밋 하는 방식`으로 진행한다.
---
## 제출 방법 ⭐️⭐⭐⭐

- [x] `main 브랜치`가 아닌 다른 이름의 브랜치에 커밋한 경우 0점 처리되니 주의해 주세요.
- [x] 원본레포 -> `Use this template` -> repository name : `java-christamas-6-thingineeer` -> `Private` -> `Create Repository`
- [x] woowa-course 계정 `Collaborator` 등록
- [x] 초대한 이후 레포 이름 수정 내역이 있다면 새로 초대 -> `나는 수정 안해서 해당 없음`
- [x] 화요일(11월 14일) 오후 2시 정각까지 `woowa-course` 계정을 collaborator로 초대하지 않은 경우 0점 처리됩니다.
- [x] 11월 14일 최종 기능 구현
- [x] 우테코 채점 프로그램 통과

---
## 기능 목록

- [x]  방문 날짜 입력 기능 #컨트롤러 -> `#Date`
- [x] 주문 할 메뉴와 개수 입력 기능 (e.g. 해산물파스타-2,레드와인-1,초코케이크-1) `#컨트롤러 -> #주문`
- [x] 방문 날짜에 해당하는 이벤트 혜택 미리보기 출력 기능
  - 12월 {date} 일에 우테코 식당에서 받을 이벤트 혜택 미리보기! `#outputView`
- [x] 주문 메뉴 확인 기능 `#OrderManager`
  - 순서는 자유롭게 이기 때문에, Map을 활용해도 ok
- [x] 할인 전 총 주문 금액 출력 기능 `#orderPrice`
  - 포맷팅 해결 `#Utils`
- [x] 증정 메뉴 출력 기능 `#GiftMenu`
  - 할인 전 총주문 금액이 12만 원 이상일 때, 샴페인 1개 증정
  - 100만원 이여도 샴페인 1개 증정 합니다. ⭐️
- [x] 혜택 내역 출력 기능 `#BenefitInformation`
  - 혜택 내역 계산 로직
    - 총주문 금액 10,000원 이상부터 이벤트가 적용됩니다. ⭐
      - [x] 주말 할인 , 평일 할인 확인 출력 확인  ⭐️
- [x] 총 혜택 금액 출력 기능 `#BenefitInformation`
  - 총 혜택금액 계산 기능
- [x] 할인 후 예상 결제금액 출력 기능 `#BenefitInformation`
  - 총 금액 - 할인 금액(샴페인 가격 미포함)
- [x] 이벤트 배지 출력기능 `#EventBadge`
  - 할인기능에 따라 뱃지 관리
  - 뱃지에는 샴페인 가격도 포함(25000)


---


## 도메인

- 방문날짜
- 이벤트
- 메뉴
- 주문 금액
- 증정메뉴
- 혜택내역
- 총 혜택금액
- 총 금액
- 이벤트 배지

---

## 메세지

- 날짜를 입력하라()
- 주문할 메뉴와 수량을 입력하라()
- 날짜별 이벤 혜택 미리보기 메세지 출력하라()
- 주문메뉴를 출력하라()
  - 메뉴와 수량을 명세에 맞게 출력하라()
- 할인 전 총주문 금액을 출력하라()
  - 주문한 메뉴들의 가격들을 더해라()
- 증정 메뉴를 출력하라()
  - 증정 메뉴의 조건이 되는지 확인하라()
- 혜택 내역을 출력하라()
  - 크리스마스 디테이 할인 확인()
  - 평일 할인 확인()
  - 특별 할인 확인()
  - 증정 이벤트 확인()
- 총 혜택 금액을 출력하라()
  - 혜택 내역을 전부 합하라()
- 할인 후 예상 결제 금액
  - 받은 할인 합산 하여 총 금액에서 빼라()
- 12월 이벤트 뱃지 확인하라()
  - 혜택 금액을 확인하여 차등 지급 하라()


## 예외 처리

### 예외 입력이 들어왔을때, 메세지 출력 후 재입력 하게 동작

- 날짜입력
  - 숫자가 아닌 경우 예외 [요청 메시지 존재]
  - 숫자가 1이상 31이하가 아닌 경우 예외 [요청 메시지 존재]
- 주문할 메뉴와 수량 입력
  - Map<String, Integer> 의 올바른 형식이 아닌 경우 예외 [요청 사항 존재]
  - 메뉴(key) 부분이 String, 즉 문자열(한글,영어)이 아니면 예외처리
  - 음료 클래스만 있으면 예외처리 ⭐
  - 수량이 1이상 20이하 가 아니면 예외처리 [요청 사항 존재] ⭐️
  - 없는 메뉴일지 예외처리 ( ex) T본스테이크 ) [요청 사항 존재]
  - 중복된 메뉴가 있을시 예외처리 [요청 사항 존재]
  - 메뉴 개수의 합이 20개가 초과할시 예외처리


---

## 커밋 메시지 컨벤션

- **Commit Message Rule**
    - `prefix(Option: File) : <Description>`

### 규칙

 ```
- 로컬 환경에서 작업 후 Add -> Commit -> Push -> Pull Request의 과정을 거친다.
- Description은 공백포함 20자를 초과 하지 않는다. 초과시 body에 적는다.
- Prefix의 의미
   > feat : 새로운 기능 구현
   > add : 코드 변경 없는 단순 파일 추가
   > fix : 버그, 오류 해결, 코드 수정
   > style : 코드 포맷팅, 코드 변경이 없는 경우, 주석 수정
   > docs : README나 WIKI 등의 문서 개정
   > refactor : 전면 수정이 있을 때 사용합니다 ex) 구조 설계
   > test : 테스트 코드 추가/변경 할때 사용합니다.
   > chore : 그 이외의 잡일/ 버전 코드 수정, 패키지 구조 변경, 파일 이동, 파일이름 변경
```
 <br>

---

## 🔥 프로그래밍 요구 사항 🔥

- [x] indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.
    - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
    - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
- [x] 3항 연산자를 쓰지 않는다.
- [x] 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라.
- [x] JUnit 5와 AssertJ를 이용하여 본인이 정리한 기능 목록이 정상 동작함을 테스트 코드로 확인한다.
- [x] 함수(또는 메서드)의 길이가 15라인을 넘어가지 않도록 구현한다.
    - 함수(또는 메서드)가 한 가지 일만 잘 하도록 구현한다.
- [x] else 예약어를 쓰지 않는다.
    - 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
    - else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
- [x] Java Enum을 적용한다.
- [x] 도메인 로직에 단위 테스트를 구현해야 한다. 단, UI(System.out, System.in, Scanner) 로직은 제외한다.🔥
    - 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 분리해 구현한다.
- [x] 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.
  - `Exception`이 아닌 `IllegalArgumentException`, `IllegalStateException` 등과 같은 명확한 유형을 처리한다.


## ⭐️ 추가된 요구 사항 ⭐️

- [x] 아래 있는 InputView, OutputView 클래스를 참고하여 입출력 클래스를 구현한다.
  - 입력과 출력을 담당하는 클래스를 별도로 구현한다.
  - 해당 클래스의 패키지, 클래스명, 메서드의 반환 타입과 시그니처는 자유롭게 구현할 수 있다.
```
 public class InputView {
    public int readDate() {
        System.out.println("12월 중 식당 예상 방문 날짜는 언제인가요? (숫자만 입력해 주세요!)");
        String input = Console.readLine();    
        // ...
    }
    // ...
}
 ```

 ```
public class OutputView {
    public void printMenu() {
        System.out.println("<주문 메뉴>");
        // ...
    }
    // ...
}
 ```
---

## ✅ 1주차 피드백 체크 리스트

- [x] 요구사항을 정확히 준수한다. ⭐️⭐️⭐️
- [x] 커밋 메시지를 의미 있게 작성한다.
- [x] git을 통해 관리할 자원에 대해서도 고려한다.
- [x] Pull Request를 보내기 전 브랜치를 확인한다.
    - [x] PR을 한 번 작성했다면 닫지 말고 추가 커밋을 한다.
- [x] 이름을 통해 의도를 드러낸다.
- [x] 축약하지 않는다.
- [x] 공백도 코딩 컨벤션이다 -> 공백 라인을 의미 있게 사용한다.
- [x] space와 tab을 혼용하지 않는다.
- [x] 의미 없는 주석을 달지 않는다.
- [x] IDE의 코드 자동 정렬 기능을 활용한다. `⌥ + ⌘ + L`
- [x] Java에서 제공하는 API를 적극 활용한다.
- [x] 배열 대신 Java Collection을 사용한다.

## ✅ 2주차 피드백 체크 리스트

- [x] README.md를 상세히 작성한다
- [x] 기능 목록을 재검토한다.
- [x] 기능 목록을 업데이트 한다.
- [x] 값을 하드 코딩 하지 않는다.
- [x] 구현 순서도 코딩 컨벤션이니,구현 순서도 지킨다.
    - 클래스는 상수, 멤버 변수, 생성자, 메서드 순으로 작성한다.
- [x] 변수 이름에 자료형은 사용하지 않는다.
- [x] 한 함수가 한 가지 기능만 담당하게 한다.
    - 안내 문구 출력, 사용자 입력, 유효값 검증 등 여러 일을 하고 있다면 이를 적절하게 분리한다.
    - 이 부분은 조금 이해하지 못하였다
- [x] 함수가 한 가지 기능을 하는지 확인하는 기준을 세운다.
    - 메서드의 바디는 10줄을 넘지 않는다. ‼️
- [x] 테스트를 작성하는 이유에 대해 본인의 경험을 토대로 정리해본다.
- [x] 처음부터 큰 단위의 테스트를 만들지 않는다.
    - 그래서 문제를 작게 나누고, 그 중 핵심 기능에 가까운 부분부터 작게 테스트를 만들어 나간다.

## ✅ 3주차 피드백 체크 리스트
- [x] 함수(메서드) 라인에 대한 기준
  - 메서드의 마디 라인 15라인으로 제한 ‼️, main() 함수에도 포함
- [x] 발생할 수 있는 예외 상황에 대해 고민한다.
  - 모든 예외처리를 케이스 별로 완료 하였다.
- [x] 비즈니스 로직과 분리한다.
- [x] 연관성이 있는 상수는 static fianl 대신 enum을 활용한다.
- [x] final 키워드를 사용해 값의 변경을 막는다.
- [x] 객체의 상태 접근을 제한한다.
  - 인스턴스 변수의 접근 제어자는 private로 구현한다.
- [x] 객체는 객체스럽게 사용한다.
  - getter를 사용하는 대신 객체에 메시지를 보내자. 🔥
- [x] 필드(인스턴스 변수)의 수를 줄이기 위해 노력한다.
  - 필드의 수가 많은 것은 객체의 복잡도를 높이고, 버그 발생 가능성을 높일 수 있다.
  - 필드에 중복이 있거나, 불필요한 필드가 없는지 확인해 필드의 수를 최소화 한다..
- [x] 성공하는 케이스 뿐만 아니라 예외에 대한 케이스도 테스트 한다.
- [x] 테스트 코드도 "코드"다.
  - 여러 개의 테스트 받을시, `@ValueSource(strings = {"999", "0", "-123"})` 활용
- [x] 테스트를 위한 코드는 구현 코드에서 분리되어야 한다.
- [x] 단위 테스트하기 어려운 코드를 단위 테스트 하기
  - 메서드 시그니처를 수정하여 테스트하기 좋은 메서드로 만들기!!
- [x] private 함수를 테스트 하고 싶다면 클래스(객체) 분리를 고려한다.
  - 너무 많은 역할을 하고있는 함수나 객체를 어떻게 의미 있는 단위로 분할할지에 초점을 맞춰 진행한다.

Class Diagram ( 종속성 포함 )

Class Diagram

이번에도 Validator를 추상화하여, 날짜 입력과, 주문 메뉴 입력에서의 예외 처리를 하였습니다.

이렇게 보니까 너무 많은 기능을 담고 있는 부분도 보이는군요 ㅠㅠ

지난 과제들과 차별점이 있다면, TDD 기법으로 코드를 구현해 보았습니다.
테스트 코드를 짜보고 기능을 구현하는 식으로 하였는데, 이렇게 시간이 오래 걸린 적은 처음입니다.
하루에 8시간 이상은 쏟았던 것 같네요...

 


📃 테스트 코드

 


마지막 제출 전까지 코드를 완전히 수정했습니다.

완벽했던 코드와 테스트 코드인 줄 알았는데, 생각보다 각기 다른 히든 케이스들이 꽤 있었습니다.

과제의 요구사항이 많은 만큼 마지막을 꼼꼼하게 장식하였습니다.

총 커밋수는 58개 였습니다

 

 

- 파일구조

 


👷🏾‍♂️ 힘들었던점

이번에도 역할과 책임을 나누는 것이 가장 힘들었던 것 같습니다.

사실 정답이란 것이 없고, 단일 책임 원칙을 지키면서 최대한 하나의 메서드는 하나의 일만 하게 만드는 게 쉬운 일이 아니었습니다.

특히 혜택 부분은 "혜택"이라는 부분을 관리하는 부분인데,

혜택 내역, 총 혜택 금액 담당하였는데 메서드가 좀 많아져서 이게 한 역할이 맞나 싶었습니다.


메시지는 메서드라고 생각하면 됩니다.

객체지향과 사실과 오해라는 책을 읽으면서 메시지의 중요성을 느꼈습니다.

하지만 좀 더 디테일하게 나누고, 정리할 필요가 있어 보입니다.

 

 

 

 

 

 

 

 

 


💻 코드 리뷰

아직 완료하지 않았습니다.


☑️ 프리코스 목표 체크 리스트

1. ✅ 코드 리뷰 최대한 많이 하기 ⭐️⭐️⭐️ 

크리스마스 프로모션은 진행중이지만

지난 과제들을 봤을때 매우 잘 지켰습니다.


2. ✅ 타인의 회고 보면서 남의 경험 배우기

커뮤니티에 올라온 블로그 글은 모두다 읽었는데 다들 고수들이 정말 많다는걸 느꼈습니다..

 

3. ✅ "객체 지향과 사실과 오해" 책 모두 읽기

전부 다 읽었습니다.

 

4. ✅ JAVA 기본 문법 공부 하기

이제 자바는 고수가 되었습니다..

Stream 들어와..

 

5. ✅ 금주 하기 

수요일 프리코스 끝나자마자 맥주 한잔 하였습니다 ㅎㅎ

 

6. ✅ 스터디, 러닝 외 약속 잡지 않기

한달동안 스터디, 러닝외 약속을 잡지 않은 저에게 칭찬을..

고생했다 ‼️

 


 

마지막으로 프리코스 하면서 러닝을 하는 느낌이 들었습니다.
저는 평소에 주 1-2회 러닝을 즐겨 합니다. 처음에는 1km 를 6분, 7분 페이스로 천천히 달리다 보면 완주를 할 수 있습니다.
처음부터 3분 30초, 4분 페이스로 달리면 지쳐서 1km도 완주를 못합니다.
프리코스 역시 1주 차부터 이것저것 도입하려고 했으면, 4주 차까지 해내지 못했을 겁니다.

1주 차에 자바 언어에 익숙해지고, 2주 차에 쪼개어보고, 3주 차에 도메인 개념과 테스트를 연습해 보고, 마지막 4주 차에 배운 모든 것들을 적용해 보는 경험을 하였습니다.

프리코스에서 많은 걸 배웠고 후회 없이 프리코스를 마무리하고자 합니다.