우아한테크코스 6기[BE] 4주차 회고

2023. 11. 15. 21:02JAVA

 

벌써 마지막 주차 미션제출이라니 시간이 정말 빠르게 흐른 것 같습니다. 4주차 미션을 진행하며 고민했던 내용들을 정리해보았습니다. 

 

<확장성을 고려한 클래스 분리>

 

이번 미션에서는 크게 3가지 확장성을 고려하면서 기능을 구현했습니다.

 

먼저는 "플래너 적용 날짜에 대한 확장성"입니다. 제공된 이메일 내용을 보면 23년 12월을 목표로 삼고 있습니다. 이와 더불어 24년도 1월에 대한 이야기도 담겨 있었습니다. 따라서 플래너가 24년에도 사용될 수 있다고 생각했습니다. 따라서 2023년과 12월을 'PlannerConfig' 클래스에서 상수로 작성했습니다. 

 

두 번째는 '적용되는 이벤트의 변경'입니다. 제공된 이메일에서는 5개의 이벤트를 담고 있었습니다. 하지만 프로그램을 진행하며 취소하거나 추가하고 싶은 이벤트가 생길 수 있다고 판단했습니다. 또한 달마다 진행되는 이벤트들이 달라질 것이라 생각했습니다. 따라서 'EventManager'를 이용해 진행할 이벤트들을 사전에 선택할 수 있도록 코드를 작성했습니다. 'EventManage'는 'PlannerConfig' 클래스에서 생성되며 진행되는 이벤트들을 Builder 패턴을 활용해 선택할 수 있도록 작성했습니다.

 

마지막으로 '이벤트의 종류'입니다. 이벤트는 크게 할인 이벤트와 증정 이벤트로 나누어져 있었습니다. 따라서 Event를 상속하는 DiscountEvent와 GiftEvent 클래스들을 작성했습니다. 하지만 추후에 할인과 증정을 동시에 제공하는 이벤트가 생길 경우 DiscountAndGiftEvent라는 새로운 클래스가 추가되어야 한다는 생각이 들었습니다. 즉 Event에서 종류를 분류하기 보다는 이벤트 적용 결과인 Benefit들만 종류에 맞게 분리하여 제공하는 것이 확장성에 유리하다는 것을 깨달았습니다. 따라서 Benefit의 서브 클래스 DiscountBenefit과 GiftBenefit를 구현해 Event 종류에 따른 확장성을 보장하고자 했습니다. 

 

 

<피드백 적용>

 

- "객체는 객체스럽게 사용한다"

3주차 공통 피드백에 쓰여 있는 "객체는 객체스럽게 사용한다"는 말을 최대한 적용하고자 했습니다. 객체를 객체스럽게 사용하기 위해서는 객체와 관련한 로직은 객체 내부에서 수행되어야 한다고 이해했습니다. 따라서 리팩토링 과정에서 불필요한 getter를 지양하며 객체지향설계를 따르고자 했습니다. 예를 들어 Reservation 클래스안에 LocalDate타입의 date가 인스턴스 변수로 있었습니다. 처음에는 LocalDate 자체가 java 안에 존재하는 클래스이기 때문에 date와 관련한 메서드를 reservation안에서 작성할 필요가 없다고 생각했습니다. 하지만 피드백을 다시 살펴보며 고민해 보니, 'date가 주말인지' 혹은 'date가 이벤트 기간에 포함되는 지'와 같은 메서드들을 Reservation에서 관리하는 것이 맞다는 것을 알 수 있었습니다. 따라서 리팩토링 과정을 통해 객체지향 설계를 위한 수정을 진행하였습니다.

 

- "단위 테스트하기 어려운 코드를 단위 테스트하기"

2주차, 3주차 미션에 까다로운 단위 테스트들이 존재하였기에 3주차 공통 피드백인 "단위 테스트하기 어려운 코드를 단위 테스트하기" 를 인상깊에 읽었습니다. 4주차에서는 EventManagerTest에서의 "해당하는 이벤트들을 적용시켜 EventResult를 반환한다."의 단위테스트가 까다롭다고 느껴졌습니다. Event의 적용 여부와 benefit을 어떻게 효율적으로 제공할 수 있을 지에 대해 고민했습니다. 3주차의 또다른 피드백이었던 "테스트를 위한 편의 메서드를 구현 코드에 구현하지 마라."를 지키며 테스트를 작성하기 위해, 적용 여부와 benefit을 외부에서 주입받는 "StubEvent"를 만들었습니다. StubEvent를 사용하며 적용 여부와 혜택들을 편리하게 관리할 수 있었고 까다로운 단위테스트였지만 비교적 쉽게 작성할 수 있었습니다. 

 

- "연관성이 있는 상수는 static final 대신 enum을 활용한다"

3주차 공통 피드백에서 enum의 활용에 대한 이야기를 있었습니다. 4주차 미션에서 Menu구현에 있어 enum을 사용했습니다. Menu안에는 음식 종류를 나타내는 타입이 필요했고 처음에는 static final을 떠올렸습니다. 하지만 이를 상수로 만들기 보다는 enum으로 작성하는 것이 좋겠다는 생각이 들었고 MenuType이라는 enum을 하나 더 만들어 enum을 활용해 구분하도록 코드를 작성했습니다. 

 

 

<구체적인 Test 작성>

4주차에서는 입력과 관련해 Error메세지가 지정되어 있었습니다. 따라서 '예약 날짜 예외'와 '주문 예외'로 예외 클래스를 분리하였고 예외마다 사전에 지정된 ErrorMessage를 가지도록 작성했습니다. 테스트를 작성할 때에는 'assertThatThrownBy'를 이용해 예외를 확인하고 'isInstanceOf'와 'hasMessage'를 통해 예외 클래스과 에러메세지를 확인하도록 작성했습니다. 이러한 방식의 테스트는 원하는 예외 클래스와 메세지를 확인할 수 있었지만, 테스트에서 제기한 예외 상황인지에 대한 확인이 불가했습니다. 실제로 주문 메뉴 중복과 관련한 테스트를 작성했고 테스트는 통과했지만, 발생한 예외가 중복이 아닌 타입변환에서 발생한 예외였습니다. 확인해보니 중복 예외 기능은 구현하지 못한 상황이었습니다.

 

이러한 문제를 해결하기 위해 2가지 방법을 생각했습니다. 먼저는 예외 클래스를 늘려 isInstanceOf에서 예외 상황을 구분하는 것입니다. 하지만  예외 클래스가 예외 상황마다 추가된다면, 클래스의 개수가 너무 많아진다고 생각하였고 불필요한 예외 클래스는 오히려 유지보수에 방해가 될 것이라 생각했습니다. 따라서 선택된 2번재 방법은 Exception내부의 errorMessage를 세부 예외 내용으로 작성하고, 출력을 위한 매서드를 추가로 작성하는 방법이었습니다. 따라서 ReservationDateException과 OrderException에 getOutputMessage()라는 메서드를 추가하여 출력을 위한 메서드를 따로 작성했습니다. 이러한 방법을 이용해 구체적인 테스트를 작성할 수 있었고 보다 정확하게 미션을 수행할 수 있었습니다.

 

'JAVA' 카테고리의 다른 글

우아한테크코스 6기[BE] 3주차 피드백  (1) 2023.11.09
팩토리 패턴  (0) 2023.11.05
우아한테크코스 2주차[BE] 피드백  (0) 2023.11.03
우아한테크코스 6기[BE] 2주차 회고  (0) 2023.11.03
정적 팩토리 메서드  (0) 2023.10.31