ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,77 @@
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static org.assertj.core.api.Assertions.*;
+
+public class RacingCarTest {
+
+    List<Car> recordMovingCar = new ArrayList<>();
+
+    @ParameterizedTest
+    @ValueSource(ints = {1, 2, 3, 4, 5})
+    @DisplayName("입력한 횟수 만큼의 '-' 문자열 만들기")
+    public String moving(int randomValueForMove) {
+        String move = "-";
+
+        if (randomValueForMove > 9 || randomValueForMove < 4) {
+            move = "";
+            return move;
+        }
+
+        for (int number=0; number < randomValueForMove; number++) { move = move + "-";}
+
+        return move;
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "1, 2",
+            "5, 7",
+            "3, 5",
+            "2, 7"
+    })
+    @DisplayName("입력한 자동차 대수 및 시도 횟수에 맞게 결과가 출력 되는가")
+    public void randomNumberForMove(int numberOfCarsValue, int numberOfAttemptsValue) {
+        Random random = new Random();
+
+        for (int attempt=0; attempt < numberOfAttemptsValue; attempt++) {
+            for (int eachCar = 0; eachCar < numberOfCarsValue; eachCar++) {
+                int carIndex = eachCar + 1;
+                int randomValueForMove = random.nextInt(numberOfAttemptsValue);
+
+                String move = "-";
+                Car car = new Car();
+                car.setMoving(move);
+                recordMovingCar.add(car);
+
+                String beforeMoving = "";
+
+//                System.out.println("랜덤 값 : " + randomValueForMove);
+
+                if (randomValueForMove > 9 || randomValueForMove < 4) {
+                    beforeMoving = recordMovingCar.get(eachCar).getMoving();
+                    String doNotMove = beforeMoving + moving(randomValueForMove);
+                    car.setMoving(doNotMove);
+                }
+
+                if (randomValueForMove > 0 & randomValueForMove > 3 & randomValueForMove <= 9) {
+                    beforeMoving = recordMovingCar.get(eachCar).getMoving();
+                    String plusMoving = beforeMoving + moving(randomValueForMove);
+                    car.setMoving(plusMoving);
+                }
+
+                recordMovingCar.add(car);
+                recordMovingCar.get(eachCar).setMoving(car.getMoving());
+                System.out.println(recordMovingCar.get(eachCar).getMoving());
+            }
+            System.out.print(System.lineSeparator());
+        }
+    }
+}

리뷰: - 위에 언급했듯 테스트 코드에 도메인 로직을 작성해선 안됩니다. 
- 단위테스트는 assertion으로만 검증해야 합니다.
@@ -0,0 +1,13 @@
+package christmas.model;
+
+import christmas.domain.Badge;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class BadgeEvent {
+    public Badge giveBadge(int orderAmount) {
+        return Arrays.stream(Badge.values()).sorted(Comparator.reverseOrder())
+                .filter(b -> b.getCutLine() <= orderAmount).findFirst().orElse(Badge.NONE);
+    }
+}

리뷰: 도메인과 모델의 차이가 무엇인가요?
@@ -0,0 +1,25 @@
+package christmas.domain;
+
+public enum Badge {
+    NONE("없음", 0),
+    STAR("별", 5000),
+    TREE("트리", 10000),
+    SANTA("산타", 20000);
+
+
+    private String name;
+    private int cutLine;
+
+    Badge(String name, int cutLine) {
+        this.name = name;
+        this.cutLine = cutLine;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getCutLine() {
+        return cutLine;
+    }
+}

리뷰: enum의 이 변수들은 재할당 될 일이 없으니 private final하게 작성해주시면 좋을 것 같아요
@@ -0,0 +1,13 @@
+package christmas.model;
+
+import christmas.domain.Badge;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class BadgeEvent {
+    public Badge giveBadge(int orderAmount) {
+        return Arrays.stream(Badge.values()).sorted(Comparator.reverseOrder())
+                .filter(b -> b.getCutLine() <= orderAmount).findFirst().orElse(Badge.NONE);
+    }
+}

리뷰: 1. 스트림은 한 줄에 한 개씩 해서 늘여써 주시면 보기 편할 것 같습니다
2. 커트라인을 물어본 다음 직접 로직을 계산하는게 아니라, 커트라인을 넘냐고 시키면 어떨까요?
3. 람다의 b라는 변수명을 조금 더 파악하기 쉬운 이름을 적어주시면 좋을 것 같아요
4. 이 코드는 Badge의 순서가 바뀌게 되면 오류가 납니다. 커트라인을 기준으로 reverseOrder로 정렬해야 할 것 같아요
```suggestion
    public Badge giveBadge(int orderAmount) {
        return Arrays.stream(Badge.values())
                .filter(badge -> badge.isOverCutLine(orderAmount))
                .max(Comparator.comparingInt(Badge::getCutLine))
                .orElse(Badge.NONE);
    }
```
@@ -0,0 +1,62 @@
+package christmas.domain;
+
+import java.util.Arrays;
+
+public enum Menu {
+
+    STAKE("티본스테이크", 55000, "main"),
+    LEAF("바비큐립", 54000, "main"),
+    PASTA("해산물파스타", 35000, "main"),
+    CHRISMASPASTA("크리스마스파스타", 25000, "main"),
+
+    COKE("제로콜라", 3000, "drink"),
+    WINE("레드와인", 60000, "drink"),
+    CHAMPAGNE("샴페인", 25000, "drink"),
+
+    CAKE("초코케이크", 15000, "desert"),
+    ICECREAM("아이스크림", 5000, "desert"),
+
+    SOUP("양송이수프", 6000, "appetizer"),
+    TAPAS("타파스", 5500, "appetizer"),
+    SALAD("시저샐러드", 8000, "appetizer"),
+
+    NONE("없음", 0, "none");
+
+    private String name;
+    private int price;
+    private String type;
+
+    public String getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    Menu(String name, int price, String type) {
+        this.name = name;
+        this.price = price;
+        this.type = type;
+    }
+
+    public static Menu getMenuWithName(String menuName) {
+        return Arrays.stream(Menu.values())
+                .filter(menu -> menu.getName().equals(menuName)).findAny().get();
+    }
+
+    public static int getPriceWithName(String name) {
+        return Arrays.stream(Menu.values()).filter(Menu -> Menu.name.equals(name)).findAny()
+                .orElse(NONE).getPrice();
+    }
+
+    // Drink만 포함된 메뉴가 아니면 True
+    public static boolean isOnlyDrinkMenu(String name) {
+        return Arrays.stream(Menu.values()).filter(n -> n.getName().equals(name))
+                .allMatch(n -> n.getType().equals("drink"));
+    }
+}

리뷰: 1. 없는 메뉴 이름이 들어오면 터질 수 있으니, get보단 orElseThrow와 같은 식으로 구현하면 좋을 것 같아요
2. 있을 수도, 없을 수도 있으니 get보단 `findMenuByName` 같은 이름도 좋을 것 같네요
@@ -0,0 +1,30 @@
+package christmas.domain;
+
+import java.util.Map;
+
+public class Order {
+
+    private int orderDate;
+    private Map<Menu, Integer> orderMenu;
+
+    public Order(int orderDate, Map<Menu, Integer> orderMenu) {
+        this.orderDate = orderDate;
+        this.orderMenu = orderMenu;
+    }
+
+    public int getOrderDate() {
+        return orderDate;
+    }
+
+    public Map<Menu, Integer> getOrderMenu() {
+        return orderMenu;
+    }
+
+    public int orderAmount() {
+        int result = 0;
+        for (Menu menu : orderMenu.keySet()) {
+            result += Menu.getPriceWithName(menu.getName()) * orderMenu.get(menu);
+        }
+        return result;
+    }
+}

리뷰: ```suggestion
            result += menu.getPrice() * orderMenu.get(menu);
```
그냥 menu.getPrice를 써도 될 것 같아요 😄
@@ -0,0 +1,62 @@
+package christmas.domain;
+
+import java.util.Arrays;
+
+public enum Menu {
+
+    STAKE("티본스테이크", 55000, "main"),
+    LEAF("바비큐립", 54000, "main"),
+    PASTA("해산물파스타", 35000, "main"),
+    CHRISMASPASTA("크리스마스파스타", 25000, "main"),
+
+    COKE("제로콜라", 3000, "drink"),
+    WINE("레드와인", 60000, "drink"),
+    CHAMPAGNE("샴페인", 25000, "drink"),
+
+    CAKE("초코케이크", 15000, "desert"),
+    ICECREAM("아이스크림", 5000, "desert"),
+
+    SOUP("양송이수프", 6000, "appetizer"),
+    TAPAS("타파스", 5500, "appetizer"),
+    SALAD("시저샐러드", 8000, "appetizer"),
+
+    NONE("없음", 0, "none");
+
+    private String name;
+    private int price;
+    private String type;
+
+    public String getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    Menu(String name, int price, String type) {
+        this.name = name;
+        this.price = price;
+        this.type = type;
+    }
+
+    public static Menu getMenuWithName(String menuName) {
+        return Arrays.stream(Menu.values())
+                .filter(menu -> menu.getName().equals(menuName)).findAny().get();
+    }
+
+    public static int getPriceWithName(String name) {
+        return Arrays.stream(Menu.values()).filter(Menu -> Menu.name.equals(name)).findAny()
+                .orElse(NONE).getPrice();
+    }
+
+    // Drink만 포함된 메뉴가 아니면 True
+    public static boolean isOnlyDrinkMenu(String name) {
+        return Arrays.stream(Menu.values()).filter(n -> n.getName().equals(name))
+                .allMatch(n -> n.getType().equals("drink"));
+    }
+}

리뷰: ```suggestion
    STAKE("티본스테이크", 55000, Category.MAIN),
```
카테고리의 오타 방지나 변경의 유연함을 위해 카테고리를 enum으로 만들거나, 상수들을 변수로 빼줬어도 좋을 것 같아요
@@ -0,0 +1,62 @@
+package christmas.domain;
+
+import java.util.Arrays;
+
+public enum Menu {
+
+    STAKE("티본스테이크", 55000, "main"),
+    LEAF("바비큐립", 54000, "main"),
+    PASTA("해산물파스타", 35000, "main"),
+    CHRISMASPASTA("크리스마스파스타", 25000, "main"),
+
+    COKE("제로콜라", 3000, "drink"),
+    WINE("레드와인", 60000, "drink"),
+    CHAMPAGNE("샴페인", 25000, "drink"),
+
+    CAKE("초코케이크", 15000, "desert"),
+    ICECREAM("아이스크림", 5000, "desert"),
+
+    SOUP("양송이수프", 6000, "appetizer"),
+    TAPAS("타파스", 5500, "appetizer"),
+    SALAD("시저샐러드", 8000, "appetizer"),
+
+    NONE("없음", 0, "none");
+
+    private String name;
+    private int price;
+    private String type;
+
+    public String getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    Menu(String name, int price, String type) {
+        this.name = name;
+        this.price = price;
+        this.type = type;
+    }
+
+    public static Menu getMenuWithName(String menuName) {
+        return Arrays.stream(Menu.values())
+                .filter(menu -> menu.getName().equals(menuName)).findAny().get();
+    }
+
+    public static int getPriceWithName(String name) {
+        return Arrays.stream(Menu.values()).filter(Menu -> Menu.name.equals(name)).findAny()
+                .orElse(NONE).getPrice();
+    }
+
+    // Drink만 포함된 메뉴가 아니면 True
+    public static boolean isOnlyDrinkMenu(String name) {
+        return Arrays.stream(Menu.values()).filter(n -> n.getName().equals(name))
+                .allMatch(n -> n.getType().equals("drink"));
+    }
+}

리뷰: 1. 람다식의 변수는 camelCase로 적어주시면 좋을 것 같아요
2. `getMenuWithName`의 로직과 중복이지 않나요? 메소드로 추출할 수 있을 것 같아요
@@ -0,0 +1,62 @@
+package christmas.domain;
+
+import java.util.Arrays;
+
+public enum Menu {
+
+    STAKE("티본스테이크", 55000, "main"),
+    LEAF("바비큐립", 54000, "main"),
+    PASTA("해산물파스타", 35000, "main"),
+    CHRISMASPASTA("크리스마스파스타", 25000, "main"),
+
+    COKE("제로콜라", 3000, "drink"),
+    WINE("레드와인", 60000, "drink"),
+    CHAMPAGNE("샴페인", 25000, "drink"),
+
+    CAKE("초코케이크", 15000, "desert"),
+    ICECREAM("아이스크림", 5000, "desert"),
+
+    SOUP("양송이수프", 6000, "appetizer"),
+    TAPAS("타파스", 5500, "appetizer"),
+    SALAD("시저샐러드", 8000, "appetizer"),
+
+    NONE("없음", 0, "none");
+
+    private String name;
+    private int price;
+    private String type;
+
+    public String getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    Menu(String name, int price, String type) {
+        this.name = name;
+        this.price = price;
+        this.type = type;
+    }
+
+    public static Menu getMenuWithName(String menuName) {
+        return Arrays.stream(Menu.values())
+                .filter(menu -> menu.getName().equals(menuName)).findAny().get();
+    }
+
+    public static int getPriceWithName(String name) {
+        return Arrays.stream(Menu.values()).filter(Menu -> Menu.name.equals(name)).findAny()
+                .orElse(NONE).getPrice();
+    }
+
+    // Drink만 포함된 메뉴가 아니면 True
+    public static boolean isOnlyDrinkMenu(String name) {
+        return Arrays.stream(Menu.values()).filter(n -> n.getName().equals(name))
+                .allMatch(n -> n.getType().equals("drink"));
+    }
+}

리뷰: 이건 이 클래스의 메뉴들 중, name과 같은 이름의 메뉴가 drink인지에 대한 로직인 것 같아요.
다시 말해, name으로 들어온 애가 drink인지를 판단하는 로직인데요. 주석으로 작성하신 설명과 조금 다른 것 같아요

`isDrinkMenu`가 어울리지 않을까요?
@@ -0,0 +1,62 @@
+package christmas.domain;
+
+import java.util.Arrays;
+
+public enum Menu {
+
+    STAKE("티본스테이크", 55000, "main"),
+    LEAF("바비큐립", 54000, "main"),
+    PASTA("해산물파스타", 35000, "main"),
+    CHRISMASPASTA("크리스마스파스타", 25000, "main"),
+
+    COKE("제로콜라", 3000, "drink"),
+    WINE("레드와인", 60000, "drink"),
+    CHAMPAGNE("샴페인", 25000, "drink"),
+
+    CAKE("초코케이크", 15000, "desert"),
+    ICECREAM("아이스크림", 5000, "desert"),
+
+    SOUP("양송이수프", 6000, "appetizer"),
+    TAPAS("타파스", 5500, "appetizer"),
+    SALAD("시저샐러드", 8000, "appetizer"),
+
+    NONE("없음", 0, "none");
+
+    private String name;
+    private int price;
+    private String type;
+
+    public String getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getPrice() {
+        return price;
+    }
+
+    Menu(String name, int price, String type) {
+        this.name = name;
+        this.price = price;
+        this.type = type;
+    }
+
+    public static Menu getMenuWithName(String menuName) {
+        return Arrays.stream(Menu.values())
+                .filter(menu -> menu.getName().equals(menuName)).findAny().get();
+    }
+
+    public static int getPriceWithName(String name) {
+        return Arrays.stream(Menu.values()).filter(Menu -> Menu.name.equals(name)).findAny()
+                .orElse(NONE).getPrice();
+    }
+
+    // Drink만 포함된 메뉴가 아니면 True
+    public static boolean isOnlyDrinkMenu(String name) {
+        return Arrays.stream(Menu.values()).filter(n -> n.getName().equals(name))
+                .allMatch(n -> n.getType().equals("drink"));
+    }
+}

리뷰: 람다 식의 변수명을 조금더 자세히 적어주시면 좋겠습니다
@@ -0,0 +1,32 @@
+package christmas.model;
+
+import christmas.domain.Menu;
+
+import java.util.Map;
+
+public class Condition {
+
+    private final static int CONDITION = 10000;
+    private final static int ORDERCOUNTCONDITION = 20;
+
+    public boolean checkEventConditionAmount(int orderAmount) {
+        if (orderAmount >= CONDITION) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean checkEventConditionMenu(Map<Menu, Integer> orderMenu) {
+        if (orderMenu.keySet().stream().allMatch(menu -> Menu.isOnlyDrinkMenu(menu.getName()))) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean checkEventConditionMenuCount(Map<Menu, Integer> orderMenu) {
+        if (orderMenu.values().stream().mapToInt(Integer::intValue).sum() > ORDERCOUNTCONDITION) {
+            return false;
+        }
+        return true;
+    }
+}

리뷰: `return orderAmount >= CONDITION;` 과 같이 줄여도 좋을 것 같아요
@@ -0,0 +1,32 @@
+package christmas.model;
+
+import christmas.domain.Menu;
+
+import java.util.Map;
+
+public class Condition {
+
+    private final static int CONDITION = 10000;
+    private final static int ORDERCOUNTCONDITION = 20;
+
+    public boolean checkEventConditionAmount(int orderAmount) {
+        if (orderAmount >= CONDITION) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean checkEventConditionMenu(Map<Menu, Integer> orderMenu) {
+        if (orderMenu.keySet().stream().allMatch(menu -> Menu.isOnlyDrinkMenu(menu.getName()))) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean checkEventConditionMenuCount(Map<Menu, Integer> orderMenu) {
+        if (orderMenu.values().stream().mapToInt(Integer::intValue).sum() > ORDERCOUNTCONDITION) {
+            return false;
+        }
+        return true;
+    }
+}

리뷰: 컨디션은 조건이란 뜻인데, int 변수인지라 조건이랑은 안 맞는 것 같아요.
MAX_ORDER_COUNT 같은 이름은 어떨까요
@@ -0,0 +1,32 @@
+package christmas.model;
+
+import christmas.domain.Menu;
+
+import java.util.Map;
+
+public class Condition {
+
+    private final static int CONDITION = 10000;
+    private final static int ORDERCOUNTCONDITION = 20;
+
+    public boolean checkEventConditionAmount(int orderAmount) {
+        if (orderAmount >= CONDITION) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean checkEventConditionMenu(Map<Menu, Integer> orderMenu) {
+        if (orderMenu.keySet().stream().allMatch(menu -> Menu.isOnlyDrinkMenu(menu.getName()))) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean checkEventConditionMenuCount(Map<Menu, Integer> orderMenu) {
+        if (orderMenu.values().stream().mapToInt(Integer::intValue).sum() > ORDERCOUNTCONDITION) {
+            return false;
+        }
+        return true;
+    }
+}

리뷰: menu의 배열을 돌면서 모두 drink인지 판단하는 로직입니다.
allMatch에서, 갖고 있는 menu한테 drink 메뉴인지 물어보면 되는데요.
굳이 이름을 꺼내서, Menu의 static 함수한테 물어볼 필요가 없다고 생각합니다.
```java
return !orderMenu.keySet()
        .stream()
        .allMatch(Menu::isDrink);
```
@@ -0,0 +1,52 @@
+package christmas.model;
+
+import camp.nextstep.edu.missionutils.Console;
+import christmas.domain.Menu;
+import christmas.validate.Validate;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Input {
+
+    private static final String delimeterComma = "(,)";
+    private static final String delimeterDash = "(-)";
+
+    public int inputOrderDate() {
+        String input = Console.readLine();
+        try {
+            Validate.integerTypeValidate(input);
+            int date = Integer.parseInt(input);
+            Validate.visitDateValidate(date);
+        } catch (IllegalArgumentException e) {
+            inputOrderDate();
+        }
+        return Integer.parseInt(input);
+    }
+
+    public Map<Menu, Integer> inputOrderMenu() {
+        String input = Console.readLine();
+        try {
+            Validate.menuFormatValidate(input);
+            Validate.isOnlyDrinkValidate(input);
+            Validate.menuDuplicationValidate(input);
+            Validate.menuValidate(input);
+            Validate.menuOrderNumberValidate(input);
+        } catch (IllegalArgumentException e) {
+            inputOrderMenu();
+        }
+        return createOrder(input);
+    }
+
+    private Map<Menu, Integer> createOrder(String input) {
+        Map<Menu, Integer> result = new LinkedHashMap<>();
+        List<String[]> pair = Arrays.stream(input.trim().split(delimeterComma))
+                .map(s -> s.split(delimeterDash)).toList();
+        for (String[] strings : pair) {
+            result.put(Menu.getMenuWithName(strings[0]), Integer.parseInt(strings[1]));
+        }
+        return result;
+    }
+}

리뷰: Input 그 자체가 아니라 Input을 받는 클래스이기 때문에, 더 의미가 드러나는 이름이면 좋을 것 같아요
@@ -0,0 +1,52 @@
+package christmas.model;
+
+import camp.nextstep.edu.missionutils.Console;
+import christmas.domain.Menu;
+import christmas.validate.Validate;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Input {
+
+    private static final String delimeterComma = "(,)";
+    private static final String delimeterDash = "(-)";
+
+    public int inputOrderDate() {
+        String input = Console.readLine();
+        try {
+            Validate.integerTypeValidate(input);
+            int date = Integer.parseInt(input);
+            Validate.visitDateValidate(date);
+        } catch (IllegalArgumentException e) {
+            inputOrderDate();
+        }
+        return Integer.parseInt(input);
+    }
+
+    public Map<Menu, Integer> inputOrderMenu() {
+        String input = Console.readLine();
+        try {
+            Validate.menuFormatValidate(input);
+            Validate.isOnlyDrinkValidate(input);
+            Validate.menuDuplicationValidate(input);
+            Validate.menuValidate(input);
+            Validate.menuOrderNumberValidate(input);
+        } catch (IllegalArgumentException e) {
+            inputOrderMenu();
+        }
+        return createOrder(input);
+    }
+
+    private Map<Menu, Integer> createOrder(String input) {
+        Map<Menu, Integer> result = new LinkedHashMap<>();
+        List<String[]> pair = Arrays.stream(input.trim().split(delimeterComma))
+                .map(s -> s.split(delimeterDash)).toList();
+        for (String[] strings : pair) {
+            result.put(Menu.getMenuWithName(strings[0]), Integer.parseInt(strings[1]));
+        }
+        return result;
+    }
+}

리뷰: 링크드 해시맵으로 작성하신 이유가 있을까요?
@@ -0,0 +1,59 @@
+package christmas.domain.order;
+
+import christmas.domain.menu.Menu;
+import christmas.error.ErrorMessage;
+import java.util.Objects;
+
+public class OrderMenu {
+
+    private static final int MIN_QUANTITY = 1;
+    private static final int MAX_QUANTITY = 20;
+
+    private final Menu menu;
+    private final int quantity;
+
+    public OrderMenu(Menu menu, int quantity) {
+        this.menu = menu;
+        if (quantity < MIN_QUANTITY || quantity > MAX_QUANTITY) {
+            throw new IllegalArgumentException(ErrorMessage.INVALID_ORDER.getMessage());
+        }
+        this.quantity = quantity;
+    }
+
+    public boolean isMenuMain() {
+        return menu.isMain();
+    }
+
+    public boolean isMenuDessert() {
+        return menu.isDessert();
+    }
+
+    public int calculatePrice() {
+        return menu.getPrice() * quantity;
+    }
+
+    public boolean isNotBeverage() {
+        return menu.isNotBeverage();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        OrderMenu orderMenu = (OrderMenu) o;
+        return menu == orderMenu.menu;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(menu);
+    }
+
+    public Menu getMenu() {
+        return menu;
+    }
+
+    public int getQuantity() {
+        return quantity;
+    }
+}

리뷰: OrderMenus에서 예외 처리 하신 거 같은데 여기서는 왜 하셨는지 의견이 궁금해요!
@@ -0,0 +1,28 @@
+package christmas.domain.event;
+
+import java.util.function.Predicate;
+
+public enum EventBadge {
+
+    SANTA("산타", (amount) -> amount >= 20_000),
+    TREE("트리", (amount) -> amount >= 10_000 && amount < 20_000),
+    STAR("별", (amount) -> amount >= 5_000 && amount < 10_000),
+    MISS("없음", (amount) -> amount < 5_000);
+
+    private final String name;
+    private final Predicate<Integer> totalBenefitAmountMatcher;
+
+    EventBadge(String name, Predicate<Integer> totalBenefitAmountMatcher) {
+        this.name = name;
+        this.totalBenefitAmountMatcher = totalBenefitAmountMatcher;
+    }
+
+    public boolean matchesTotalBenefitAmount(int totalBenefitAmount) {
+        return totalBenefitAmountMatcher.test(totalBenefitAmount);
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}

리뷰: 이걸 사용하는거랑 따로 메서드를 만들어서 사용하는것 중에 Predicate를 선택하신 이유가 궁금해요