ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,36 @@
+package christmas.view;
+
+import camp.nextstep.edu.missionutils.Console;
+import christmas.domain.Menu;
+import christmas.domain.Order;
+import christmas.domain.Reservation;
+import christmas.exception.ValidatorException;
+import christmas.validator.Validator;
+import java.util.Map;
+
+public class InputView {
+
+    public static Reservation createReservation() {
+        try {
+            String input = Console.readLine();
+            int date = Validator.convertDateStringToInt(input);
+
+            return Reservation.from(date);
+        } catch (ValidatorException exception) {
+            OutputView.println(exception.getMessage());
+            return createReservation();
+        }
+    }
+
+    public static Order createOrder() {
+        try {
+            String input = Console.readLine();
+            Validator.isValidOrderFormat(input);
+            Map<Menu, Integer> order = Validator.parseOrder(input);
+            return Order.from(order);
+        } catch (ValidatorException exception) {
+            OutputView.println(exception.getMessage());
+            return createOrder();
+        }
+    }
+}

리뷰: `InputView`에 존재하는 코드 흐름의 중복을 다음과 같이 제거할 수 있습니다!
동작 파라미터화로 변경이 필요한 로직의 부분만 중복되는 흐름 사이에 전달해 주는 방식이에요!

```suggestion
    public static Order createOrder() {
        return getResult(() -> {
            String input = Console.readLine();
            Validator.isValidOrderFormat(input);
            Map<Menu, Integer> order = Validator.parseOrder(input);
            return Order.from(order);
        });
    }
    
    public static <T> T getResult(Supplier<T> supplier){
        try{
            return supplier.get();
        } catch (ValidatorException e){
            OutputView.println(e.getMessage());
            return getResult(supplier);
        }
    }
```
@@ -0,0 +1,36 @@
+package christmas.view;
+
+import camp.nextstep.edu.missionutils.Console;
+import christmas.domain.Menu;
+import christmas.domain.Order;
+import christmas.domain.Reservation;
+import christmas.exception.ValidatorException;
+import christmas.validator.Validator;
+import java.util.Map;
+
+public class InputView {
+
+    public static Reservation createReservation() {
+        try {
+            String input = Console.readLine();
+            int date = Validator.convertDateStringToInt(input);
+
+            return Reservation.from(date);
+        } catch (ValidatorException exception) {
+            OutputView.println(exception.getMessage());
+            return createReservation();
+        }
+    }
+
+    public static Order createOrder() {
+        try {
+            String input = Console.readLine();
+            Validator.isValidOrderFormat(input);
+            Map<Menu, Integer> order = Validator.parseOrder(input);
+            return Order.from(order);
+        } catch (ValidatorException exception) {
+            OutputView.println(exception.getMessage());
+            return createOrder();
+        }
+    }
+}

리뷰: `View`에서 도메인 클래스 자체가 생성되어 반환되는 것이 `View` 클래스에 너무 많은 책임이 존재하는 것 처럼 보이기도 하는데 이 부분에 대해선 어떻게 생각하시나요?
@@ -0,0 +1,48 @@
+package christmas.view.messages;
+
+public enum PrintMessage {
+    INPUT_INTRODUCE("안녕하세요! 우테코 식당 12월 이벤트 플래너입니다."),
+    INPUT_RESERVATION("12월 중 식당 예상 방문 날짜는 언제인가요? (숫자만 입력해 주세요!)"),
+    INPUT_ORDER("주문하실 메뉴를 메뉴와 개수를 알려 주세요. (e.g. 해산물파스타-2,레드와인-1,초코케이크-1)"),
+
+    OUTPUT_RESULT("12월 26일에 우테코 식당에서 받을 이벤트 혜택 미리 보기!"),
+    OUTPUT_ORDER("<주문 메뉴>"),
+    OUTPUT_TOTAL_BEFORE_DISCOUNT("<할인 전 총주문 금액>"),
+    OUTPUT_GIFT_MENU("<증정 메뉴>"),
+    OUTPUT_BENEFIT("<혜택 내역>"),
+    OUTPUT_TOTAL_BENEFIT("<총혜택 금액>"),
+    OUTPUT_TOTAL_AFTER_DISCOUNT("<할인 후 예상 결제 금액>"),
+    OUTPUT_EVENT_BADGE("<12월 이벤트 배지>"),
+    OUTPUT_PRECAUTIONS("총주문 금액 10,000원 이상부터 이벤트가 적용됩니다.\n"
+            + "음료만 주문 시, 주문할 수 없습니다.\n"
+            + "메뉴는 한 번에 최대 20개까지만 주문할 수 있습니다.\n"
+            + "(e.g. 시저샐러드-1, 티본스테이크-1, 크리스마스파스타-1, 제로콜라-3, 아이스크림-1의 총개수는 7개)\n"),
+    MONEY("원"),
+    COUNT("개"),
+    NONE("없음"),
+    PREVIEW("12월 %d일에 우테코 식당에서 받을 이벤트 혜택 미리 보기!"),
+    CHRISTMAS_DISCOUNT("크리스마스 할인: -"),
+    WEEKDAY_DISCOUNT("평일 할인: -"),
+    WEEKEND_DISCOUNT("주말 할인: -"),
+    SPECIAL_DISCOUNT("특별 할인: -"),
+    SERVICE_DISCOUNT("증정 이벤트: -"),
+    BENEFIT_ALL_DISCOUNT("<총혜택 금액>"),
+    AFTER_BENEFIT_DISCOUNT("<할인 후 예상 결제 금액>"),
+    BADGE_DISCOUNT("<12월 이벤트 배지>"),
+    SERVICE_MENU("샴페인 1개");
+
+
+    private final String message;
+
+    PrintMessage(String message) {
+        this.message = message;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public String getMessage(int day) {
+        return String.format(message, day);
+    }
+}

리뷰: 여러 줄로 구성된 `String`은 `"""`로 감싸줄 수 있는 것으로 알고 있습니다!
@@ -0,0 +1,50 @@
+package christmas.domain;
+
+public enum Calendar {
+    WEEKEND(1, 2, 8, 9, 15, 16, 22, 23, 29, 30),
+    WEEKDAY(3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 31),
+    SPECIAL_DAY(3, 10, 17, 24, 25, 31);
+
+    private final int[] days;
+
+    Calendar(int... days) {
+        this.days = days;
+    }
+
+    public int[] getDays() {
+        return days;
+    }
+
+    public static boolean isWeekday(int date) {
+        for (Calendar calendar : values()) {
+            for (int weekday : calendar.getDays()) {
+                if (weekday == date && calendar == WEEKDAY) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isWeekend(int date) {
+        for (Calendar calendar : values()) {
+            for (int weekend : calendar.getDays()) {
+                if (weekend == date && calendar == WEEKEND) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isSpecialDay(int date) {
+        for (Calendar calendar : values()) {
+            for (int specialDay : calendar.getDays()) {
+                if (specialDay == date && calendar == SPECIAL_DAY) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}

리뷰: 생각하지 못했던 부분인데 감사합니다.
@@ -0,0 +1,50 @@
+package christmas.domain;
+
+public enum Calendar {
+    WEEKEND(1, 2, 8, 9, 15, 16, 22, 23, 29, 30),
+    WEEKDAY(3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 31),
+    SPECIAL_DAY(3, 10, 17, 24, 25, 31);
+
+    private final int[] days;
+
+    Calendar(int... days) {
+        this.days = days;
+    }
+
+    public int[] getDays() {
+        return days;
+    }
+
+    public static boolean isWeekday(int date) {
+        for (Calendar calendar : values()) {
+            for (int weekday : calendar.getDays()) {
+                if (weekday == date && calendar == WEEKDAY) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isWeekend(int date) {
+        for (Calendar calendar : values()) {
+            for (int weekend : calendar.getDays()) {
+                if (weekend == date && calendar == WEEKEND) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isSpecialDay(int date) {
+        for (Calendar calendar : values()) {
+            for (int specialDay : calendar.getDays()) {
+                if (specialDay == date && calendar == SPECIAL_DAY) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}

리뷰: 헉.. 그렇지 않아도 Stream에 대해 계속 공부하고 있는데 복습하며 적용해보도록 하겠습니다. 감사합니다!
@@ -0,0 +1,24 @@
+package christmas.domain;
+
+public enum DiscountType {
+    MIN_EVENT_CONDITION(10000),
+    CHAMPAGNE_CONDITION(120000),
+    CHAMPAGNE(25000),
+    SERVICE_MENU_CONDITION(1),
+    DDAY_CONDITION(25),
+    BASE_AMOUNT(900),
+    DAY_BONUS(100),
+    SPECIALDAY_CONDITION(2023),
+    INIT_COUNT(0),
+    SPECIAL_DISCOUNT(1000);
+
+    private final int type;
+
+    DiscountType(int type) {
+        this.type = type;
+    }
+
+    public int getType() {
+        return type;
+    }
+}

리뷰: 감사합니다!
@@ -0,0 +1,37 @@
+package christmas.domain;
+
+import java.util.Arrays;
+
+public enum Menu {
+    양송이수프(6_000), 타파스(5_500), 시저샐러드(8_000),
+    티본스테이크(55_000), 바비큐립(54_000), 해산물파스타(35_000), 크리스마스파스타(25_000),
+    초코케이크(15_000), 아이스크림(5_000),
+    제로콜라(3_000), 레드와인(60_000), 샴페인(25_000);
+
+    private final int price;
+
+    Menu(int price) {
+        this.price = price;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    public boolean isBeverage() {
+        return this == 제로콜라 || this == 레드와인 || this == 샴페인;
+    }
+
+    public boolean isDessert() {
+        return this == 초코케이크 || this == 아이스크림;
+    }
+
+    public boolean isMain() {
+        return this == 티본스테이크 || this == 바비큐립 || this == 해산물파스타 || this == 크리스마스파스타;
+    }
+
+    public static boolean contains(String itemName) {
+        return Arrays.stream(Menu.values())
+                .anyMatch(menu -> menu.name().equalsIgnoreCase(itemName));
+    }
+}

리뷰: 좀 더 객체지향적으로 설계가 가능한 부분이네요. 감사합니다!
@@ -0,0 +1,36 @@
+package christmas.view;
+
+import camp.nextstep.edu.missionutils.Console;
+import christmas.domain.Menu;
+import christmas.domain.Order;
+import christmas.domain.Reservation;
+import christmas.exception.ValidatorException;
+import christmas.validator.Validator;
+import java.util.Map;
+
+public class InputView {
+
+    public static Reservation createReservation() {
+        try {
+            String input = Console.readLine();
+            int date = Validator.convertDateStringToInt(input);
+
+            return Reservation.from(date);
+        } catch (ValidatorException exception) {
+            OutputView.println(exception.getMessage());
+            return createReservation();
+        }
+    }
+
+    public static Order createOrder() {
+        try {
+            String input = Console.readLine();
+            Validator.isValidOrderFormat(input);
+            Map<Menu, Integer> order = Validator.parseOrder(input);
+            return Order.from(order);
+        } catch (ValidatorException exception) {
+            OutputView.println(exception.getMessage());
+            return createOrder();
+        }
+    }
+}

리뷰: 최근에 공부하며 View는 컨트롤러에서 Model을 받기만 해야 한다는 생각이 들었습니다. 이 당시에는 View에서 Model을 생성해서 반환하는 방법이 저도 맞는건가? 생각을 했었는데 값만 반환해주는 형식으로 수정해봐야겠네요. 감사합니다.
@@ -0,0 +1,36 @@
+package christmas.view;
+
+import camp.nextstep.edu.missionutils.Console;
+import christmas.domain.Menu;
+import christmas.domain.Order;
+import christmas.domain.Reservation;
+import christmas.exception.ValidatorException;
+import christmas.validator.Validator;
+import java.util.Map;
+
+public class InputView {
+
+    public static Reservation createReservation() {
+        try {
+            String input = Console.readLine();
+            int date = Validator.convertDateStringToInt(input);
+
+            return Reservation.from(date);
+        } catch (ValidatorException exception) {
+            OutputView.println(exception.getMessage());
+            return createReservation();
+        }
+    }
+
+    public static Order createOrder() {
+        try {
+            String input = Console.readLine();
+            Validator.isValidOrderFormat(input);
+            Map<Menu, Integer> order = Validator.parseOrder(input);
+            return Order.from(order);
+        } catch (ValidatorException exception) {
+            OutputView.println(exception.getMessage());
+            return createOrder();
+        }
+    }
+}

리뷰: 헉 이런식으로 코드를 작성할 수 있군요. 알려주셔서 감사합니다. 좀 더 공부해서 적용해보도록 하겠습니다!
@@ -0,0 +1,48 @@
+package christmas.view.messages;
+
+public enum PrintMessage {
+    INPUT_INTRODUCE("안녕하세요! 우테코 식당 12월 이벤트 플래너입니다."),
+    INPUT_RESERVATION("12월 중 식당 예상 방문 날짜는 언제인가요? (숫자만 입력해 주세요!)"),
+    INPUT_ORDER("주문하실 메뉴를 메뉴와 개수를 알려 주세요. (e.g. 해산물파스타-2,레드와인-1,초코케이크-1)"),
+
+    OUTPUT_RESULT("12월 26일에 우테코 식당에서 받을 이벤트 혜택 미리 보기!"),
+    OUTPUT_ORDER("<주문 메뉴>"),
+    OUTPUT_TOTAL_BEFORE_DISCOUNT("<할인 전 총주문 금액>"),
+    OUTPUT_GIFT_MENU("<증정 메뉴>"),
+    OUTPUT_BENEFIT("<혜택 내역>"),
+    OUTPUT_TOTAL_BENEFIT("<총혜택 금액>"),
+    OUTPUT_TOTAL_AFTER_DISCOUNT("<할인 후 예상 결제 금액>"),
+    OUTPUT_EVENT_BADGE("<12월 이벤트 배지>"),
+    OUTPUT_PRECAUTIONS("총주문 금액 10,000원 이상부터 이벤트가 적용됩니다.\n"
+            + "음료만 주문 시, 주문할 수 없습니다.\n"
+            + "메뉴는 한 번에 최대 20개까지만 주문할 수 있습니다.\n"
+            + "(e.g. 시저샐러드-1, 티본스테이크-1, 크리스마스파스타-1, 제로콜라-3, 아이스크림-1의 총개수는 7개)\n"),
+    MONEY("원"),
+    COUNT("개"),
+    NONE("없음"),
+    PREVIEW("12월 %d일에 우테코 식당에서 받을 이벤트 혜택 미리 보기!"),
+    CHRISTMAS_DISCOUNT("크리스마스 할인: -"),
+    WEEKDAY_DISCOUNT("평일 할인: -"),
+    WEEKEND_DISCOUNT("주말 할인: -"),
+    SPECIAL_DISCOUNT("특별 할인: -"),
+    SERVICE_DISCOUNT("증정 이벤트: -"),
+    BENEFIT_ALL_DISCOUNT("<총혜택 금액>"),
+    AFTER_BENEFIT_DISCOUNT("<할인 후 예상 결제 금액>"),
+    BADGE_DISCOUNT("<12월 이벤트 배지>"),
+    SERVICE_MENU("샴페인 1개");
+
+
+    private final String message;
+
+    PrintMessage(String message) {
+        this.message = message;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public String getMessage(int day) {
+        return String.format(message, day);
+    }
+}

리뷰: 앗! 까먹고 있었네요. 감사합니다!
@@ -0,0 +1,15 @@
+package christmas.controller;
+
+import christmas.domain.Order;
+import christmas.domain.Reservation;
+import christmas.domain.Result;
+
+public class EventPlannerController {
+    public static void run() {
+        Reservation reservation = ReservationController.inputReservation();
+        Order order = OrderController.inputOrder();
+        Result result = ResultController.createResult(order, reservation);
+        ResultController.printResult(result);
+
+    }
+}

리뷰: 어떤 이유로 static 메서드를 사용하셨을까요?
static메서드를 사용하면 편리할 수 있는데 다른 사이드 이펙트가 없을까요?
@@ -0,0 +1,20 @@
+package christmas.controller;
+
+import christmas.domain.Order;
+import christmas.domain.Reservation;
+import christmas.domain.Result;
+import christmas.view.OutputView;
+
+public class ResultController {
+
+    public static Result createResult(Order order, Reservation reservation) {
+        OutputView.printIntroduce(reservation.getDate());
+        OutputView.printOrder(order);
+        System.out.println();
+        return Result.from(order.getOrderedItems(), reservation.getDate());
+    }
+
+    public static void printResult(Result result) {
+        OutputView.printAllEvents(result);
+    }
+}

리뷰: 여러 컨트롤러 클래스를 분리하신 이유가 무엇인가요?
@@ -0,0 +1,50 @@
+package christmas.domain;
+
+public enum Calendar {
+    WEEKEND(1, 2, 8, 9, 15, 16, 22, 23, 29, 30),
+    WEEKDAY(3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 31),
+    SPECIAL_DAY(3, 10, 17, 24, 25, 31);
+
+    private final int[] days;
+
+    Calendar(int... days) {
+        this.days = days;
+    }
+
+    public int[] getDays() {
+        return days;
+    }
+
+    public static boolean isWeekday(int date) {
+        for (Calendar calendar : values()) {
+            for (int weekday : calendar.getDays()) {
+                if (weekday == date && calendar == WEEKDAY) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isWeekend(int date) {
+        for (Calendar calendar : values()) {
+            for (int weekend : calendar.getDays()) {
+                if (weekend == date && calendar == WEEKEND) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isSpecialDay(int date) {
+        for (Calendar calendar : values()) {
+            for (int specialDay : calendar.getDays()) {
+                if (specialDay == date && calendar == SPECIAL_DAY) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}

리뷰: calendar라는 enum이 2023년 12월의 날짜만 있으니 조금 어색한 것 같아요 클래스 명을 좀 더 명확하게 하면 좋을 것 같아요
@@ -0,0 +1,29 @@
+package christmas.domain;
+
+public enum EventBadge {
+    SANTA(20000, "산타"),
+    TREE(10000, "트리"),
+    STAR(5000, "별"),
+    NONE(0, "없음");
+
+    private final int threshold;
+    private final String description;
+
+    EventBadge(int threshold, String description) {
+        this.threshold = threshold;
+        this.description = description;
+    }
+
+    public static EventBadge getBadge(int totalAfterBenefit) {
+        for (EventBadge badge : values()) {
+            if (totalAfterBenefit >= badge.threshold) {
+                return badge;
+            }
+        }
+        return EventBadge.NONE;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

리뷰: 이것도 스트림으로 해결할 수 있겠네요
휴대폰으로 하는 것이라 코드치기가 불편해서 스트림, filter, findAny, orElseGet 을 사용하면 될 것 같아요!
@@ -0,0 +1,37 @@
+package christmas.domain;
+
+import java.util.Arrays;
+
+public enum Menu {
+    양송이수프(6_000), 타파스(5_500), 시저샐러드(8_000),
+    티본스테이크(55_000), 바비큐립(54_000), 해산물파스타(35_000), 크리스마스파스타(25_000),
+    초코케이크(15_000), 아이스크림(5_000),
+    제로콜라(3_000), 레드와인(60_000), 샴페인(25_000);
+
+    private final int price;
+
+    Menu(int price) {
+        this.price = price;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    public boolean isBeverage() {
+        return this == 제로콜라 || this == 레드와인 || this == 샴페인;
+    }
+
+    public boolean isDessert() {
+        return this == 초코케이크 || this == 아이스크림;
+    }
+
+    public boolean isMain() {
+        return this == 티본스테이크 || this == 바비큐립 || this == 해산물파스타 || this == 크리스마스파스타;
+    }
+
+    public static boolean contains(String itemName) {
+        return Arrays.stream(Menu.values())
+                .anyMatch(menu -> menu.name().equalsIgnoreCase(itemName));
+    }
+}

리뷰: 여기만 변수명을 한글로 하신 이유가 있나요? 저는 한글 변수가 가독성이 좋다고 생각하지만 자동완성에서 불편하더라고요 
그리고 아래에 is~~~ 메서드가 많은데 메뉴에 가격과 타입도 같이 가지고 있다면 좀 더 깔끔하게 코드를 작성할 수 있을 것 같네요
@@ -0,0 +1,25 @@
+package christmas.domain;
+
+import christmas.validator.Validator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Order {
+
+    private Map<Menu, Integer> orderedItems;
+
+    private Order(Map<Menu, Integer> orderedItems ) {
+        this.orderedItems = orderedItems;
+    }
+
+    public static Order from(Map<Menu, Integer> orderMap) {
+//        Map<Menu, Integer> orderMap = parseOrder(order);
+        return new Order(orderMap);
+    }
+
+    public Map<Menu, Integer> getOrderedItems() {
+        return orderedItems;
+    }
+}

리뷰: 왜 같은 메서드가 두개일까요?
@@ -0,0 +1,20 @@
+package christmas.domain;
+
+import christmas.validator.Validator;
+
+public class Reservation {
+    private final int date;
+
+    private Reservation(int date) {
+        Validator.isInRange(date);
+        this.date = date;
+    }
+
+    public static Reservation from(int date) {
+        return new Reservation(date);
+    }
+
+    public int getDate() {
+        return date;
+    }
+}

리뷰: 여기도 그렇네요 어떤 이유로 생성자를 private으로 막아두시고 static 메서드를 사용하셨을까요
@@ -0,0 +1,87 @@
+package christmas.domain;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class CalendarTest {
+
+    @DisplayName("평일에 해당하는 날짜를 입력했을 때 검증")
+    @Test
+    public void testIsWeekday() {
+        // Given
+        int weekday = 5;
+
+        // When
+        boolean result = Calendar.isWeekday(weekday);
+
+        // Then
+        assertTrue(result, "평일이 맞음");
+    }
+
+    @DisplayName("평일에 해당하지 않는 날짜를 입력했을 때 검증")
+    @Test
+    public void testIsNotWeekday() {
+        // Given
+        int weekday = 9;
+
+        // When
+        boolean result = Calendar.isWeekday(weekday);
+
+        // Then
+        assertFalse(result, "평일이 아님");
+    }
+
+    @DisplayName("주말에 해당하는 날짜를 입력했을 때 검증")
+    @Test
+    public void testIsWeekend() {
+        // Given
+        int weekend = 9;
+
+        // When
+        boolean result = Calendar.isWeekend(weekend);
+
+        // Then
+        assertTrue(result, "주말이 맞음");
+    }
+
+    @DisplayName("주말에 해당하지 않는 날짜를 입력했을 때 검증")
+    @Test
+    public void testIsNotWeekend() {
+        // Given
+        int weekend = 3;
+
+        // When
+        boolean result = Calendar.isWeekend(weekend);
+
+        // Then
+        assertFalse(result, "주말이 아님");
+    }
+
+    @DisplayName("특별한 날에 해당하는 날짜를 입력했을 때 검증")
+    @Test
+    public void testIsSpecialDay() {
+        // Given
+        int specialDay = 25;
+
+        // When
+        boolean result = Calendar.isSpecialDay(specialDay);
+
+        // Then
+        assertTrue(result, "특별한 날");
+    }
+
+    @DisplayName("특별한 날에 해당하지 않는 날짜를 입력했을 때 검증")
+    @Test
+    public void testIsNotSpecialDay() {
+        // Given
+        int specialDay = 19;
+
+        // When
+        boolean result = Calendar.isSpecialDay(specialDay);
+
+        // Then
+        assertFalse(result, "특별한 날");
+    }
+}
\ No newline at end of file

리뷰: assertJ 라이브러리를 사용하시는 것을 추천드립니다
@@ -0,0 +1,88 @@
+package christmas.domain;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+class MenuTest {
+
+    @DisplayName("양송이 수프 가격 동일한지 검증")
+    @Test
+    public void testGetPrice() {
+        // Given
+        Menu menu = Menu.양송이수프;
+
+        // When
+        int price = menu.getPrice();
+
+        // Then
+        assertEquals(6_000, price, "양송이수프의 가격이 같음");
+    }
+
+    @DisplayName("음료인지 검증")
+    @Test
+    public void testIsBeverage() {
+        // Given
+        Menu cola = Menu.제로콜라;
+        Menu wine = Menu.레드와인;
+        Menu champagne = Menu.샴페인;
+        Menu pasta = Menu.크리스마스파스타;
+
+        // Then
+        assertTrue(cola.isBeverage(), "제로콜라는 음료수");
+        assertTrue(wine.isBeverage(), "레드와인은 음료수");
+        assertTrue(champagne.isBeverage(), "샴페인은 음료수");
+        assertFalse(pasta.isBeverage(), "크리스마스파스타는 음료수가 아님");
+    }
+
+    @DisplayName("디저트인지 검증")
+    @Test
+    public void testIsDessert() {
+        // Given
+        Menu cake = Menu.초코케이크;
+        Menu iceCream = Menu.아이스크림;
+        Menu pasta = Menu.크리스마스파스타;
+
+        // Then
+        assertTrue(cake.isDessert(), "초코케이크는 디저트");
+        assertTrue(iceCream.isDessert(), "아이스크림은 디저트");
+        assertFalse(pasta.isDessert(), "크리스마스파스타는 디저트가 아님");
+    }
+
+    @DisplayName("메인요리인지 검증")
+    @Test
+    public void testIsMain() {
+        // Given
+        Menu steak = Menu.티본스테이크;
+        Menu ribs = Menu.바비큐립;
+        Menu pasta = Menu.크리스마스파스타;
+        Menu soup = Menu.양송이수프;
+
+        // Then
+        assertTrue(steak.isMain(), "티본스테이크는 메인요리");
+        assertTrue(ribs.isMain(), "바비큐립은 메인요리");
+        assertTrue(pasta.isMain(), "크리스마스파스타는 메인요리");
+        assertFalse(soup.isMain(), "양송이수프는 메인요리가 아님");
+    }
+
+    @DisplayName("주문 메뉴가 메뉴에 포함되어 있는지 검증")
+    @Test
+    public void testContains_ValidItem() {
+        // Given
+        String itemName = "아이스크림";
+
+        // Then
+        assertTrue(Menu.contains(itemName), "메뉴에 아이스크림이 있어야 함");
+    }
+
+    @DisplayName("주문 메뉴가 메뉴에 포함되어 있지 않은지 검증")
+    @Test
+    public void testContains_InvalidItem() {
+        // Given
+        String itemName = "피자";
+
+        // Then
+        assertFalse(Menu.contains(itemName), "메뉴에 피자가 없어야 함");
+    }
+}
\ No newline at end of file

리뷰: softAssertion이나 assertAll에 대해 알아보시면 좋을 것 같아요
@@ -0,0 +1,15 @@
+package christmas.controller;
+
+import christmas.domain.Order;
+import christmas.domain.Reservation;
+import christmas.domain.Result;
+
+public class EventPlannerController {
+    public static void run() {
+        Reservation reservation = ReservationController.inputReservation();
+        Order order = OrderController.inputOrder();
+        Result result = ResultController.createResult(order, reservation);
+        ResultController.printResult(result);
+
+    }
+}

리뷰: static 메서드만 있는 클래스라면 인스턴스륾 만들 필요가 없을텐데요, 이를 어떻게 방지할 수 있을까요?