역시 4주 차는 새로운 문제가 나왔습니다.
이번에는 메일 부터 비공개 저장소로 main 브런치에 커밋을 진행하는 방식을 썼는데,
이 내용을 본 후, 깃허브 주소에 들어가 요구 사항을 봤는데 바로 😵💫
정말 요구사항이 많았다! 하지만 동시에 정말 재밌을 거 같았다!
이번 미션도 클래스(객체)분리가 목표이다.
3주 차에 더불어 좀 더 분리하는 연습을 해 보고, 추가적으로 InputView와 OutputView가 주어졌다.
도메인 로직과 UI로직을 분리하는 연습도 해보았다.
도메인 로직에 대하여
도메인 로직을 이해하기 위해 요구사항을 꼼꼼하게 분석하고, 클래스(객체)를 어떻게 구성할지 결정했다. 특히, 이번 미션은 예상 방문 날짜와 주문 메뉴에 따라 혜택을 계산하는 프로그램을 완성하는 것이었기 때문에 복잡한 조건과 예외에 대한 고민이 필요했다.
기능 목록 양부터 정말 살벌하다..
클래스(객체) 분리와 역할, 책임 부여
각 클래스가 어떤 역할과 책임을 가져야 하는지 고민하면서 클래스 설계에 신경을 썼습니다. 초기에 주어진 카테고리와 음식 이름 가격을 함께 저장하는 방식에 대해 고민을 해보았습니다. 제가 내린 결론은, 애피타이저와 메인 같은 카테고리와 음식 이름 및 가격은 변경될 수 있는 부분이라는 생각이 들어, 카테고리와 음식을 분리하는 결정을 내리게 되었습니다. 나중에 카테고리와 음식에 대한 정보가 바뀌어도 Category와 Food만 수정하면 되기 때문에 유연성이 향상된 것을 느꼈습니다.
public enum Category {
APPETIZER,
MAIN,
DESSERT,
DRINK
}
public enum Food {
MUSHROOM_SOUP("양송이수프", 6000),
TAPAS("타파스", 5500),
CAESAR_SALAD("시저샐러드", 8000),
T_BONE_STEAK("티본스테이크", 55000),
BBQ_RIBS("바비큐립", 54000),
SEAFOOD_PASTA("해산물파스타", 35000),
CHRISTMAS_PASTA("크리스마스파스타", 25000),
CHOCOLATE_CAKE("초코케이크", 15000),
ICE_CREAM("아이스크림", 5000),
ZERO_COLA("제로콜라", 3000),
RED_WINE("레드와인", 60000),
CHAMPAGNE("샴페인", 25000);
}
어려움 2가지
Orders가 Order의 일급 컬렉션이고, Order 클래스가 Menu를 참조하고, Menu가 다시 Food와 Category를 참조하는 구조에서, 예외 처리 및 값을 가져오는 부분에서 두 가지 어려움을 겪었습니다.
첫 번째로, Order 클래스에서 음식 이름 및 카테고리를 얻기 위해 getter를 사용하였습니다. 이로 인해 각 객체의 getter를 순차적으로 호출해야 하는 번거로움이 있었습니다. 특히, Food와 Category를 거치는 과정에서 코드가 복잡해지고 가독성이 떨어졌다고 생각합니다. 객체 지향적인 방식으로 객체에게 직접 물어보는 것이 아닌, getter를 통해 간접적으로 값을 얻는 방식은 코드의 가독성과 객체를 제대로 사용하지 않았다고 느껴졌습니다.
두 번째로 Orders 클래스에서 음식 이름이 중복되면 예외가 발생해야 합니다. 이를 위해 처음에 equals와 hashCode 재정의를 생각하였지만, Menu와 Food까지 재정의해야 하는 어려움이 있었습니다. 그래서 저는 다른 방법이 생각나지 않아 음식을 getter로 직접 가져와 비교하였습니다. 이 부분이 정말 아쉽습니다.
private boolean isDuplicateOrderMenu(List<Order> orders) {
Set<String> foodNames = new HashSet<>();
for (Order order : orders) {
String foodName = order.getFoodName();
if (!foodNames.add(foodName)) {
return true;
}
}
return false;
}
처음으로 의존관계를 설정해 주는 클래스를 만들어봤습니다.
이전 코드 리뷰에서 받은 피드백을 적극 활용하여 의존관계 설정을 개선하기 위해 AppConfig 클래스를 도입하는 도전에 나섰습니다. 이를 통해 의존성 주입을 더 효과적으로 관리할 수 있었고, 코드의 유지보수성을 향상할 수 있었습니다.
public class AppConfig {
public PlannerController plannerController() {
return new PlannerController(plannerService());
}
public PlannerService plannerService() {
return new PlannerService(menuBoard());
}
public MenuBoard menuBoard() {
return new MenuBoard();
}
}
UI로직과 도메인 로직 분리 중 고민이 들었던 점.
public static void printGiveawayMenu(TotalOrderAmount totalOrderAmount) {
...
}
공통 피드백에서는 한 클래스에서 도메인 로직과 UI 로직을 같이 두지 말라는 뜻으로 이해했었다. 과연 이렇게 쓰는것은 도메인 로직과 UI로직을 분리한 것일까? 도메인 객체의 getter를 쓰면 결국 그 도메인 안에 값을 알게 된다고 생각했기 때문이고, List나 원시 타입으로 이 정보가 뭔지 모르게 전달해야 하나라는 고민이 들었습니다.
마무리 글,,
이번 4주차 미션 도중에 여러 어려움을 겪었고, 몇몇 아쉬운 부분이 있었습니다. 그러나 이는 동시에 4주 동안 프리코스를 통해 얼마나 많이 성장했는지를 나타내는 좋은 증거라고 생각합니다!! 어려움을 겪었다는 것과 아쉬운 부분이 있다는 것은 새로운 도전과 학습이 있었다는 증거이며, 이를 통해 더 나은 프로그래머로 성장할 수 있었습니다. 프리코스를 통해 많은 것을 얻었고, 정말 값진 경험이었습니다. 이제는 그 경험을 더 나은 코드 작성에 활용해보고자 합니다. 모든 분들 4주간 정말 고생하셨습니다. 감사합니다!!
'대외 활동 > 우아한테크코스 6기 BE' 카테고리의 다른 글
우아한테크코스 6기 3주차 프리코스 회고록 (0) | 2023.11.09 |
---|---|
우아한테크코스 6기 2주차 프리코스 회고록 (0) | 2023.11.02 |
우아한테크코스 6기 1주차 프리코스 회고록 (0) | 2023.10.24 |