ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,54 @@
+package christmas;
+
+import christmas.domain.DecemberDate;
+import christmas.domain.menu.OrderRepository;
+import christmas.domain.Reservation;
+import christmas.view.InputView;
+import christmas.view.OutputView;
+import java.util.function.Supplier;
+
+public class ChristmasController {
+    public static void run() {
+        Reservation reservation = initReservation();
+        printOrderInformation(reservation);
+        printDiscountInformation(reservation);
+    }
+
+    private static Reservation initReservation() {
+        OutputView.printWelcomeMessage();
+        DecemberDate date = initDecemberDate();
+        OrderRepository orderRepository = initOrderRepository();
+        return Reservation.of(date, orderRepository);
+    }
+
+    private static DecemberDate initDecemberDate() {
+        return receiveValidatedValue(() -> new DecemberDate(InputView.readDate()));
+    }
+
+    private static OrderRepository initOrderRepository() {
+        return receiveValidatedValue(() -> OrderRepository.createByString(InputView.readOrders()));
+    }
+
+    private static <T> T receiveValidatedValue(Supplier<T> inputMethod) {
+        try {
+            return inputMethod.get();
+        } catch (IllegalArgumentException exception) {
+            OutputView.printException(exception);
+            return receiveValidatedValue(inputMethod);
+        }
+    }
+
+    private static void printOrderInformation(Reservation reservation) {
+        OutputView.printEventPreMessage(reservation.getDecemberDate());
+        OutputView.printOrderMenus(reservation.getOrderRepository());
+    }
+
+    private static void printDiscountInformation(Reservation reservation) {
+        OutputView.printOriginalPrice(reservation.calculateTotalOriginalMoney());
+        OutputView.printGiftMenu(reservation.calculateGift());
+        OutputView.printDiscountLogs(reservation.getDiscountRepository());
+        OutputView.printTotalDiscountMoney(reservation.calculateTotalDiscountMoney());
+        OutputView.printToTalFinalPrice(reservation.calculateTotalFinalMoney());
+        OutputView.printEventBadge(reservation.calculateEventBadge());
+    }
+}

리뷰: 람다식을 활용하여 반복입력 예외처리를 한 번만 하는 방식도 있군요. 배우고 갑니다. 좋은 방식인것 같습니다.
@@ -0,0 +1,59 @@
+package christmas.domain;
+
+import christmas.domain.discount.DiscountRepository;
+import christmas.domain.discount.GiftDiscount;
+import christmas.domain.menu.Menu;
+import christmas.domain.menu.OrderRepository;
+
+public class Reservation {
+    private final DiscountRepository discountRepository;
+    private final DecemberDate decemberDate;
+    private final OrderRepository orderRepository;
+
+    private Reservation(DecemberDate decemberDate, OrderRepository orderRepository) {
+        this.decemberDate = decemberDate;
+        this.orderRepository = orderRepository;
+        this.discountRepository = DiscountRepository.of(decemberDate, orderRepository);
+    }
+
+    public static Reservation of(DecemberDate decemberDate, OrderRepository menus) {
+        return new Reservation(decemberDate, menus);
+    }
+
+    public Menu calculateGift() {
+        return discountRepository.calculateGift();
+    }
+
+    public Money calculateTotalOriginalMoney() {
+        return orderRepository.calculateTotalPrice();
+    }
+
+    public Money calculateTotalDiscountMoney() {
+        return discountRepository.calculateTotalDiscountMoney();
+    }
+
+    public Money calculateTotalFinalMoney() {
+        Money discountMoney = calculateTotalDiscountMoney();
+        if (discountRepository.hasGiftDiscount()) {
+            discountMoney = discountMoney.minus(GiftDiscount.getGift().getPrice());
+        }
+        return calculateTotalOriginalMoney().minus(discountMoney);
+    }
+
+    public EventBadge calculateEventBadge() {
+        Money totalDiscountMoney = calculateTotalDiscountMoney();
+        return EventBadge.findByTotalDiscountPrice(totalDiscountMoney);
+    }
+
+    public DiscountRepository getDiscountRepository() {
+        return discountRepository;
+    }
+
+    public DecemberDate getDecemberDate() {
+        return decemberDate;
+    }
+
+    public OrderRepository getOrderRepository() {
+        return orderRepository;
+    }
+}

리뷰: 제가 알기로는 Repositoy는 주로 데이터 베이스 연결과 관련한 객체로 많이 사용하는 것으로 알고있습니다. 외부의 시스템과 연결하는 재사용되는 로직을 주로 처리하는 역할을 합니다.
@@ -0,0 +1,59 @@
+package christmas.domain;
+
+import christmas.domain.discount.DiscountRepository;
+import christmas.domain.discount.GiftDiscount;
+import christmas.domain.menu.Menu;
+import christmas.domain.menu.OrderRepository;
+
+public class Reservation {
+    private final DiscountRepository discountRepository;
+    private final DecemberDate decemberDate;
+    private final OrderRepository orderRepository;
+
+    private Reservation(DecemberDate decemberDate, OrderRepository orderRepository) {
+        this.decemberDate = decemberDate;
+        this.orderRepository = orderRepository;
+        this.discountRepository = DiscountRepository.of(decemberDate, orderRepository);
+    }
+
+    public static Reservation of(DecemberDate decemberDate, OrderRepository menus) {
+        return new Reservation(decemberDate, menus);
+    }
+
+    public Menu calculateGift() {
+        return discountRepository.calculateGift();
+    }
+
+    public Money calculateTotalOriginalMoney() {
+        return orderRepository.calculateTotalPrice();
+    }
+
+    public Money calculateTotalDiscountMoney() {
+        return discountRepository.calculateTotalDiscountMoney();
+    }
+
+    public Money calculateTotalFinalMoney() {
+        Money discountMoney = calculateTotalDiscountMoney();
+        if (discountRepository.hasGiftDiscount()) {
+            discountMoney = discountMoney.minus(GiftDiscount.getGift().getPrice());
+        }
+        return calculateTotalOriginalMoney().minus(discountMoney);
+    }
+
+    public EventBadge calculateEventBadge() {
+        Money totalDiscountMoney = calculateTotalDiscountMoney();
+        return EventBadge.findByTotalDiscountPrice(totalDiscountMoney);
+    }
+
+    public DiscountRepository getDiscountRepository() {
+        return discountRepository;
+    }
+
+    public DecemberDate getDecemberDate() {
+        return decemberDate;
+    }
+
+    public OrderRepository getOrderRepository() {
+        return orderRepository;
+    }
+}

리뷰: 정적 팩토리 메서드를 사용하셨는데 혹시 이 메서드의 장점이 어떤 점인지 알 수 있을까요? (궁금증 입니다.)
@@ -0,0 +1,29 @@
+package christmas.domain.discount;
+
+import christmas.domain.DecemberDate;
+import christmas.domain.Money;
+import java.util.List;
+
+public class SpecialDiscount {
+    public static final String NAME = "특별 할인";
+    private static final int DISCOUNT_AMOUNT = 1000;
+    private static final List<DecemberDate> specialDates = List.of(
+        new DecemberDate(3),
+        new DecemberDate(10),
+        new DecemberDate(17),
+        new DecemberDate(24),
+        new DecemberDate(25),
+        new DecemberDate(31)
+    );
+
+    public static Money calculateDiscountAmount(DecemberDate date) {
+        if (isSpecialDate(date)) {
+            return new Money(DISCOUNT_AMOUNT);
+        }
+        return new Money(0);
+    }
+
+    private static boolean isSpecialDate(DecemberDate date) {
+        return specialDates.contains(date);
+    }
+}

리뷰: 7로 나누어서 3이 되는 경우로 표현하면 코드의 길이를 줄일 수 있을것 같습니다. 각 나머지 값이 하나의 요일에 대응되므로, 나머지 값을 각각의 요일과 대응시키는 방법도 효과적일 것 같아요!
@@ -0,0 +1,23 @@
+package christmas.constant;
+
+public class Number {
+    public static final int ZERO = 0;
+    public static final int ONE = 1;
+    public static final int TWO = 2;
+    public static final int THREE = 3;
+    public static final int SEVEN = 7;
+    public static final int TWENTY = 20;
+    public static final int HUNDRED = 100;
+    public static final int THOUSAND = 1000;
+    public static final int TEN_THOUSAND = 10000;
+    public static final int MIN_DATE = 1;
+    public static final int MAX_DATE = 31;
+    public static final int CHRISTMAS = 25;
+    public static final int YEAR = 2023;
+    public static final int FREE_GIFT = 120000;
+    public static final int STAR = 5000;
+    public static final int TREE = 10000;
+    public static final int SANTA = 20000;
+
+
+}

리뷰: 혹시 해당 클래스를 만드신 이유는 뭘까요?

`연관성이 있는 상수는 static final 대신 enum을 활용한다`
해당 문구 때문이라면, 상수끼리 연관성도 낮고, Enum도 아니군요...
3을 THREE라고 네이밍하는 것도 다소 아쉽습니다. 맥락상 어떤 역할을 하는지 보여주는 것이 더 좋겠네요
@@ -0,0 +1,6 @@
+package christmas.constant.message;
+
+public class InputMessage {
+    public static final String DATE = "12월 중 식당 예상 방문 날짜는 언제인가요? (숫자만 입력해 주세요!)";
+    public static final String ORDER = "주문하실 메뉴를 메뉴와 개수를 알려 주세요. (e.g. 해산물파스타-2,레드와인-1,초코케이크-1)";
+}

리뷰: 제 생각엔 메세지들은 굳이 상수화 시키지 않아도
하나의 메서드에만 쓰이고, 메세지를 읽었을 때 어떤 용도인지 충분히 알 수 있다고 생각해서
지금과 같은 경우엔 굳이 상수화 시키지 않는 편인데
승철님은 어떻게 생각하시나요?

(OutputMessage도 마찬가지입니다 ㅎㅎ)
@@ -0,0 +1,87 @@
+package christmas.controller;
+
+import christmas.domain.*;
+import christmas.domain.calculator.PriceCalculator;
+import christmas.view.*;
+
+public class EventController {
+    public void event() {
+        printStart();
+        Date date = getDate();
+        Order order = getOrder();
+        printPreview(date);
+        printOrder(order);
+        Price price = getBeforeDiscount(order);
+        printBeforeDiscount(price);
+        Event event = applyEvent(date, order, price);
+        printGift(event);
+        printEvent(event);
+        printAllBenefit(event);
+        printAfterDiscount(event, price);
+        printEventBadge(event);
+    }
+
+    public void printStart() {
+        OutputHelloView outputHello = new OutputHelloView();
+        outputHello.outputHello();
+    }
+
+    public Date getDate() {
+        InputDateView inputDateView = new InputDateView();
+        return inputDateView.inputDate();
+    }
+
+    public Order getOrder() {
+        InputOrderView inputOrderView = new InputOrderView();
+        return inputOrderView.inputOrder();
+    }
+
+    public void printPreview(Date date) {
+        OutputPreviewView outputPreviewView = new OutputPreviewView();
+        outputPreviewView.outputPreview(date);
+    }
+
+    public void printOrder(Order order) {
+        OutputOrderView outputOrderView = new OutputOrderView();
+        outputOrderView.outputOrder(order);
+    }
+
+    public Price getBeforeDiscount(Order order) {
+        PriceCalculator priceCalculator = new PriceCalculator();
+        return priceCalculator.calculatePrice(order);
+    }
+
+    public void printBeforeDiscount(Price price) {
+        OutputBeforeDiscountView outputBeforeDiscountView = new OutputBeforeDiscountView();
+        outputBeforeDiscountView.outputBeforeDiscount(price);
+    }
+
+    public Event applyEvent(Date date, Order order, Price price) {
+        return new Event(date, order, price);
+    }
+
+    public void printGift(Event event) {
+        OutputGiftView outputGiftView = new OutputGiftView();
+        outputGiftView.outputGift(event);
+    }
+
+    public void printEvent(Event event) {
+        OutputEventView outputEventView = new OutputEventView();
+        outputEventView.outputEvent(event);
+    }
+
+    public void printAllBenefit(Event event) {
+        OutputAllBenefitView outputAllBenefitView = new OutputAllBenefitView();
+        outputAllBenefitView.outputAllBenefit(event);
+    }
+
+    public void printAfterDiscount(Event event, Price price) {
+        OutputAfterDiscountView outputAfterDiscountView = new OutputAfterDiscountView();
+        outputAfterDiscountView.outputAfterDiscount(event, price);
+    }
+
+    public void printEventBadge(Event event) {
+        OutputEventBadgeView outputEventBadgeView = new OutputEventBadgeView();
+        outputEventBadgeView.outputEventBadge(event);
+    }
+}

리뷰: View 클래스를 굉장히 잘게 나누어주셨네요
안에 메서드들이 하나밖에 없는 경우도 있던데 이렇게 잘게 나눠주신 이유가 뭘까요?
@@ -0,0 +1,87 @@
+package christmas.controller;
+
+import christmas.domain.*;
+import christmas.domain.calculator.PriceCalculator;
+import christmas.view.*;
+
+public class EventController {
+    public void event() {
+        printStart();
+        Date date = getDate();
+        Order order = getOrder();
+        printPreview(date);
+        printOrder(order);
+        Price price = getBeforeDiscount(order);
+        printBeforeDiscount(price);
+        Event event = applyEvent(date, order, price);
+        printGift(event);
+        printEvent(event);
+        printAllBenefit(event);
+        printAfterDiscount(event, price);
+        printEventBadge(event);
+    }
+
+    public void printStart() {
+        OutputHelloView outputHello = new OutputHelloView();
+        outputHello.outputHello();
+    }
+
+    public Date getDate() {
+        InputDateView inputDateView = new InputDateView();
+        return inputDateView.inputDate();
+    }
+
+    public Order getOrder() {
+        InputOrderView inputOrderView = new InputOrderView();
+        return inputOrderView.inputOrder();
+    }
+
+    public void printPreview(Date date) {
+        OutputPreviewView outputPreviewView = new OutputPreviewView();
+        outputPreviewView.outputPreview(date);
+    }
+
+    public void printOrder(Order order) {
+        OutputOrderView outputOrderView = new OutputOrderView();
+        outputOrderView.outputOrder(order);
+    }
+
+    public Price getBeforeDiscount(Order order) {
+        PriceCalculator priceCalculator = new PriceCalculator();
+        return priceCalculator.calculatePrice(order);
+    }
+
+    public void printBeforeDiscount(Price price) {
+        OutputBeforeDiscountView outputBeforeDiscountView = new OutputBeforeDiscountView();
+        outputBeforeDiscountView.outputBeforeDiscount(price);
+    }
+
+    public Event applyEvent(Date date, Order order, Price price) {
+        return new Event(date, order, price);
+    }
+
+    public void printGift(Event event) {
+        OutputGiftView outputGiftView = new OutputGiftView();
+        outputGiftView.outputGift(event);
+    }
+
+    public void printEvent(Event event) {
+        OutputEventView outputEventView = new OutputEventView();
+        outputEventView.outputEvent(event);
+    }
+
+    public void printAllBenefit(Event event) {
+        OutputAllBenefitView outputAllBenefitView = new OutputAllBenefitView();
+        outputAllBenefitView.outputAllBenefit(event);
+    }
+
+    public void printAfterDiscount(Event event, Price price) {
+        OutputAfterDiscountView outputAfterDiscountView = new OutputAfterDiscountView();
+        outputAfterDiscountView.outputAfterDiscount(event, price);
+    }
+
+    public void printEventBadge(Event event) {
+        OutputEventBadgeView outputEventBadgeView = new OutputEventBadgeView();
+        outputEventBadgeView.outputEventBadge(event);
+    }
+}

리뷰: MVC 패턴을 적용하는 이유는 뭘까요?
현재 코드상에서 View가 model의 객체를 생성해주고 있는데
정말 MVC 패턴이 잘 적용된 건 맞을까요?
@@ -0,0 +1,17 @@
+package christmas.domain;
+
+import static christmas.constant.Number.MAX_DATE;
+import static christmas.constant.Number.MIN_DATE;
+import static christmas.constant.message.ErrorMessage.INVALID_DATE;
+
+public record Date(int date) {
+    public Date {
+        validate(date);
+    }
+
+    private void validate(int date) {
+        if (date < MIN_DATE || date > MAX_DATE) {
+            throw new IllegalArgumentException(INVALID_DATE);
+        }
+    }
+}

리뷰: 무엇을 검증하는지 좀 더 명확하게 나타내는 네이밍이 좋겠군요
@@ -0,0 +1,87 @@
+package christmas.controller;
+
+import christmas.domain.*;
+import christmas.domain.calculator.PriceCalculator;
+import christmas.view.*;
+
+public class EventController {
+    public void event() {
+        printStart();
+        Date date = getDate();
+        Order order = getOrder();
+        printPreview(date);
+        printOrder(order);
+        Price price = getBeforeDiscount(order);
+        printBeforeDiscount(price);
+        Event event = applyEvent(date, order, price);
+        printGift(event);
+        printEvent(event);
+        printAllBenefit(event);
+        printAfterDiscount(event, price);
+        printEventBadge(event);
+    }
+
+    public void printStart() {
+        OutputHelloView outputHello = new OutputHelloView();
+        outputHello.outputHello();
+    }
+
+    public Date getDate() {
+        InputDateView inputDateView = new InputDateView();
+        return inputDateView.inputDate();
+    }
+
+    public Order getOrder() {
+        InputOrderView inputOrderView = new InputOrderView();
+        return inputOrderView.inputOrder();
+    }
+
+    public void printPreview(Date date) {
+        OutputPreviewView outputPreviewView = new OutputPreviewView();
+        outputPreviewView.outputPreview(date);
+    }
+
+    public void printOrder(Order order) {
+        OutputOrderView outputOrderView = new OutputOrderView();
+        outputOrderView.outputOrder(order);
+    }
+
+    public Price getBeforeDiscount(Order order) {
+        PriceCalculator priceCalculator = new PriceCalculator();
+        return priceCalculator.calculatePrice(order);
+    }
+
+    public void printBeforeDiscount(Price price) {
+        OutputBeforeDiscountView outputBeforeDiscountView = new OutputBeforeDiscountView();
+        outputBeforeDiscountView.outputBeforeDiscount(price);
+    }
+
+    public Event applyEvent(Date date, Order order, Price price) {
+        return new Event(date, order, price);
+    }
+
+    public void printGift(Event event) {
+        OutputGiftView outputGiftView = new OutputGiftView();
+        outputGiftView.outputGift(event);
+    }
+
+    public void printEvent(Event event) {
+        OutputEventView outputEventView = new OutputEventView();
+        outputEventView.outputEvent(event);
+    }
+
+    public void printAllBenefit(Event event) {
+        OutputAllBenefitView outputAllBenefitView = new OutputAllBenefitView();
+        outputAllBenefitView.outputAllBenefit(event);
+    }
+
+    public void printAfterDiscount(Event event, Price price) {
+        OutputAfterDiscountView outputAfterDiscountView = new OutputAfterDiscountView();
+        outputAfterDiscountView.outputAfterDiscount(event, price);
+    }
+
+    public void printEventBadge(Event event) {
+        OutputEventBadgeView outputEventBadgeView = new OutputEventBadgeView();
+        outputEventBadgeView.outputEventBadge(event);
+    }
+}

리뷰: 추가적으로, 모든 View 관련 객체들에 인스턴스 변수가 없어서
유틸성 클래스로 만들어도 됐을 것 같은데 지금처럼 매 클래스마다 객체를 생성해주시는 이유는 뭘까요?
@@ -0,0 +1,91 @@
+package christmas.domain;
+
+import christmas.domain.menu.Dessert;
+import christmas.domain.menu.Drink;
+import christmas.domain.menu.Entree;
+import christmas.domain.menu.Menu;
+
+import java.util.Map;
+
+import static christmas.constant.Number.*;
+import static christmas.constant.message.OutputMessage.*;
+
+public record Event(Date date, Order order, Price price) {
+    public int d_Day() {
+        if (price.price() < TEN_THOUSAND || date.date() > CHRISTMAS) {
+            return ZERO;
+        }
+        return THOUSAND + (date.date() - MIN_DATE) * HUNDRED;
+    }
+
+    public int weekday() {
+        if (price.price() < TEN_THOUSAND || (date.date() % SEVEN == ONE || date.date() % SEVEN == TWO)) {
+            return ZERO;
+        }
+        int count = ZERO;
+        for (Map.Entry<Menu, Integer> entry : order.order().entrySet()) {
+            Menu menu = entry.getKey();
+            Integer i = entry.getValue();
+            try {
+                Dessert.valueOf(menu.name());
+            } catch (IllegalArgumentException e) {
+                continue;
+            }
+            count += i;
+        }
+        return YEAR * count;
+    }
+
+    public int weekend() {
+        if (price.price() < TEN_THOUSAND || (date.date() % SEVEN != ONE && date.date() % SEVEN != TWO)) {
+            return ZERO;
+        }
+        int count = ZERO;
+        for (Map.Entry<Menu, Integer> entry : order.order().entrySet()) {
+            Menu menu = entry.getKey();
+            Integer i = entry.getValue();
+            try {
+                Entree.valueOf(menu.name());
+            } catch (IllegalArgumentException e) {
+                continue;
+            }
+            count += i;
+        }
+        return YEAR * count;
+    }
+
+    public int special() {
+        if (price.price() < TEN_THOUSAND || (date.date() % SEVEN != THREE && date.date() != CHRISTMAS)) {
+            return ZERO;
+        }
+        return THOUSAND;
+    }
+
+    public int freeGift() {
+        if (price.price() > FREE_GIFT) {
+            return Drink.샴페인.getPrice();
+        }
+        return ZERO;
+    }
+
+    public String badge() {
+        if (allBenefit() >= SANTA) {
+            return SANTA_BADGE;
+        }
+        if (allBenefit() >= TREE) {
+            return TREE_BADGE;
+        }
+        if (allBenefit() >= STAR) {
+            return STAR_BADGE;
+        }
+        return NOTHING;
+    }
+
+    public int allBenefit() {
+        return d_Day() + weekday() + weekend() + special() + freeGift();
+    }
+
+    public int afterDiscount() {
+        return d_Day() + weekday() + weekend() + special();
+    }
+}

리뷰: 자바 컨벤션 상 메서드는 동사형으로 작성하는 걸 권장드립니다
@@ -0,0 +1,91 @@
+package christmas.domain;
+
+import christmas.domain.menu.Dessert;
+import christmas.domain.menu.Drink;
+import christmas.domain.menu.Entree;
+import christmas.domain.menu.Menu;
+
+import java.util.Map;
+
+import static christmas.constant.Number.*;
+import static christmas.constant.message.OutputMessage.*;
+
+public record Event(Date date, Order order, Price price) {
+    public int d_Day() {
+        if (price.price() < TEN_THOUSAND || date.date() > CHRISTMAS) {
+            return ZERO;
+        }
+        return THOUSAND + (date.date() - MIN_DATE) * HUNDRED;
+    }
+
+    public int weekday() {
+        if (price.price() < TEN_THOUSAND || (date.date() % SEVEN == ONE || date.date() % SEVEN == TWO)) {
+            return ZERO;
+        }
+        int count = ZERO;
+        for (Map.Entry<Menu, Integer> entry : order.order().entrySet()) {
+            Menu menu = entry.getKey();
+            Integer i = entry.getValue();
+            try {
+                Dessert.valueOf(menu.name());
+            } catch (IllegalArgumentException e) {
+                continue;
+            }
+            count += i;
+        }
+        return YEAR * count;
+    }
+
+    public int weekend() {
+        if (price.price() < TEN_THOUSAND || (date.date() % SEVEN != ONE && date.date() % SEVEN != TWO)) {
+            return ZERO;
+        }
+        int count = ZERO;
+        for (Map.Entry<Menu, Integer> entry : order.order().entrySet()) {
+            Menu menu = entry.getKey();
+            Integer i = entry.getValue();
+            try {
+                Entree.valueOf(menu.name());
+            } catch (IllegalArgumentException e) {
+                continue;
+            }
+            count += i;
+        }
+        return YEAR * count;
+    }
+
+    public int special() {
+        if (price.price() < TEN_THOUSAND || (date.date() % SEVEN != THREE && date.date() != CHRISTMAS)) {
+            return ZERO;
+        }
+        return THOUSAND;
+    }
+
+    public int freeGift() {
+        if (price.price() > FREE_GIFT) {
+            return Drink.샴페인.getPrice();
+        }
+        return ZERO;
+    }
+
+    public String badge() {
+        if (allBenefit() >= SANTA) {
+            return SANTA_BADGE;
+        }
+        if (allBenefit() >= TREE) {
+            return TREE_BADGE;
+        }
+        if (allBenefit() >= STAR) {
+            return STAR_BADGE;
+        }
+        return NOTHING;
+    }
+
+    public int allBenefit() {
+        return d_Day() + weekday() + weekend() + special() + freeGift();
+    }
+
+    public int afterDiscount() {
+        return d_Day() + weekday() + weekend() + special();
+    }
+}

리뷰: 해당 클래스에서 너무 많은 걸 하고 있네요
할인율을 계산하고, 증점품을 줄지 결정하고, 배지를 줄지 결정하고...
Event라는 네이밍만 들었을 때, 저 모든 일을 하는 것을 예측하기 쉽지 않을것같습니다.
객체지향 설계의 5가지 원칙(SOLID) 중 [단일 책임의 원칙(SRP, Single Responsibility Principle)](https://mangkyu.tistory.com/194)에 대해 알아볼까요?