ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,58 @@
+package store.view;
+
+import static store.global.InputConstant.BUY_PRODUCT_MESSAGE;
+import static store.global.InputConstant.ENDING_MESSAGE;
+import static store.global.InputConstant.MEMBERSHIP_MESSAGE;
+import static store.global.InputConstant.NOTICE_FOR_FREE_STOCK;
+import static store.global.InputConstant.NOTICE_FOR_FREE_STOCK_MESSAGE;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+public class InputView {
+
+    private InputView() {
+
+    }
+
+    public static List<String> getLines(BufferedReader br) throws IOException {
+        List<String> lines = new ArrayList<>();
+        String line;
+        while ((line = getLine(br)) != null) {
+            lines.add(line);
+        }
+        return lines;
+    }
+
+    public static String getLine(BufferedReader br) throws IOException {
+        return br.readLine();
+    }
+
+    public static String getBuyProductMessage(Scanner sc) {
+        System.out.println(BUY_PRODUCT_MESSAGE);
+        return sc.nextLine();
+    }
+
+    public static String getMembershipMessage(Scanner sc) {
+        System.out.println(MEMBERSHIP_MESSAGE);
+        return sc.nextLine();
+    }
+
+    public static String getEndingMessage(Scanner sc) {
+        System.out.println(ENDING_MESSAGE);
+        return sc.nextLine();
+    }
+
+    public static String getMoreFreeStock(Scanner sc, String name, int freeStock) {
+        System.out.printf(NOTICE_FOR_FREE_STOCK_MESSAGE, name, freeStock);
+        return sc.nextLine();
+    }
+
+    public static String getAgreeBuyWithNoPromotion(Scanner sc, String name, int stock) {
+        System.out.printf(NOTICE_FOR_FREE_STOCK, name, stock);
+        return sc.nextLine();
+    }
+}

리뷰: 제가 입출력을 제일 마지막에 구현해서 정신없이 뺐네요 ㅜㅜㅜ 감사합니다 !!
@@ -0,0 +1,38 @@
+package store.domain.promotion;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+public class Promotion {
+
+    private final String name;
+    private final Range range;
+    private final BuyGet buyGet;
+
+    public Promotion(String name, BuyGet buyGet, Range range) {
+        this.buyGet = buyGet;
+        this.name = name;
+        this.range = range;
+    }
+
+    public boolean checkDate(LocalDateTime now) {
+        LocalDate date = now.toLocalDate();
+        return range.isValidRange(date);
+    }
+
+    public int calculateFreeStock(int stock) {
+        return buyGet.calculateGetStock(stock);
+    }
+
+    public int getTotalBuyStock(int totalStock, int currentStock) {
+        return buyGet.calculateBuyStock(totalStock, currentStock);
+    }
+
+    public int getBuyStock() {
+        return buyGet.getBuyStock();
+    }
+
+    public String getName() {
+        return name;
+    }
+}

리뷰: 수정이 잦은 필드가 이고, 필드를 메서드마다 계속 전달하는 방식이 비효율적이라고 느껴서  필드를 관리하는 클래스를 따로 만들어 필드의 수정과 관리를 클래스 내부에서 처리하게 하고 인자로 전달 안해도 되게 했어요 !
@@ -0,0 +1,70 @@
+package store.controller.product;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static store.domain.Store.addFreeProduct;
+
+import camp.nextstep.edu.missionutils.DateTimes;
+import java.util.List;
+import store.domain.Item;
+import store.domain.Stock;
+import store.domain.Store;
+
+public class PromotionItemController {
+
+    public Item processPromotionItem(Stock stock, Item promotionalItem, List<Item> purchasedItems, Store store) {
+        Stock stockFreeItem = new Stock(0);
+        Stock stockForPay = new Stock(0);
+        Item purchasedItem = null;
+        if (promotionalItem == null) {
+            return null;
+        }
+        if (promotionalItem.checkDate(DateTimes.now())) {
+            Item item = store.buyPromoItemNoDiscount(stock, promotionalItem, purchasedItems);
+            if (item != null) {
+                return item;
+            }
+            purchasedItem = processPromotionItems(stock, promotionalItem, purchasedItems, stockFreeItem, stockForPay);
+        }
+
+        return purchasedItem;
+    }
+
+    public static int processRemainingPromotionStock(Item promotionalItem, Stock remainStock) {
+        return Math.min(promotionalItem.getStockCount(), remainStock.getStock());
+    }
+
+    private Item processPromotionItems(Stock stock, Item promotionalItem, List<Item> purchasedItems, Stock stockFreeItem,
+                                       Stock stockForPay) {
+        Item purchasedItem;
+        promotionProcess(stock, promotionalItem, stockFreeItem, stockForPay);
+        purchasedItem = new Item(promotionalItem, stockForPay, FALSE);
+        addFreeProduct(stockFreeItem, promotionalItem, purchasedItems, TRUE);
+        return purchasedItem;
+    }
+
+    private static void promotionProcess(Stock stock, Item promotionalItem, Stock stockFreeItem, Stock stockForPay) {
+        int stockForPromotionItem = promotionalItem.getTotalBuyStock(stock.getStock(), promotionalItem.getStockCount());
+        int freeStock = promotionalItem.calculateFreeStock(stockForPromotionItem);
+
+        updatePromotionItems(promotionalItem, stockFreeItem, stockForPay, freeStock, stockForPromotionItem);
+
+        stock.minus(stockForPromotionItem + freeStock);
+        int remainingStock = updateRemainItem(stock, promotionalItem, stockForPay);
+        stock.minus(remainingStock);
+    }
+
+    private static int updateRemainItem(Stock stock, Item promotionalItem, Stock stockForPay) {
+        int remainingStock = processRemainingPromotionStock(promotionalItem, stock);
+        promotionalItem.updateStock(remainingStock);
+        stockForPay.plus(remainingStock);
+        return remainingStock;
+    }
+
+    private static void updatePromotionItems(Item promotionalItem, Stock stockFreeItem, Stock stockForPay, int freeStock,
+                                             int stockForPromotionItem) {
+        stockFreeItem.plus(freeStock);
+        stockForPay.plus(stockForPromotionItem);
+        promotionalItem.updateStock(stockForPromotionItem + freeStock);
+    }
+}

리뷰: 항상 세세히 봐주셔서 감사합니다..ㅎㅎ 
체크을 못했네요.. ㅠㅠㅠ
@@ -0,0 +1,62 @@
+package store.domain;
+
+import static store.global.ErrorMessages.INVALID_STATE_ERROR;
+
+import java.util.Objects;
+
+public class Stock {
+
+    private int stock;
+
+    public Stock(int stock) {
+        validate(stock);
+        this.stock = stock;
+    }
+
+    public int getStock() {
+        return stock;
+    }
+
+    public boolean compare(int stock) {
+        return this.stock >= stock;
+    }
+
+    public void minus(int stock) {
+        updateValidate(stock);
+        this.stock -= stock;
+    }
+
+    public void plus(int stock) {
+        this.stock += stock;
+    }
+
+    private void validate(int stock) {
+        if (stock < 0) {
+            throw new IllegalStateException(INVALID_STATE_ERROR.getMessage());
+        }
+    }
+
+    private void updateValidate(int stock) {
+        if (stock > this.stock) {
+            throw new IllegalStateException(INVALID_STATE_ERROR.getMessage());
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        Stock stock1 = (Stock) o;
+        return stock == stock1.stock;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(stock);
+    }
+}
+

리뷰: 테스트를 위해 Override한건데 냅둬야할지 테스트를 고쳤어야할지 고민하다가 남겨뒀습니다  !
@@ -0,0 +1,12 @@
+package store.common;
+
+public class ConsoleMessages {
+    public static final String WELCOME_MESSAGE = "안녕하세요. W편의점입니다.";
+    public static final String PRODUCT_LIST_HEADER = "현재 보유하고 있는 상품입니다.";
+    public static final String PURCHASE_ITEMS_PROMPT = "구매하실 상품명과 수량을 입력해 주세요. (예: [사이다-2],[감자칩-1])";
+    public static final String ADDITIONAL_PROMO_PROMPT = "현재 %s은(는) %d개를 무료로 더 받을 수 있습니다. 추가하시겠습니까? (Y/N)";
+    public static final String FULL_PRICE_PURCHASE_PROMPT = "현재 %s %d개는 프로모션 할인이 적용되지 않습니다. 그래도 구매하시겠습니까? (Y/N)";
+    public static final String MEMBERSHIP_DISCOUNT_PROMPT = "멤버십 할인을 받으시겠습니까? (Y/N)";
+    public static final String ADDITIONAL_PURCHASE_PROMPT = "감사합니다. 구매하고 싶은 다른 상품이 있나요? (Y/N)";
+    public static final String LINE_SEPARATOR = System.lineSeparator();
+}

리뷰: enum이 아닌 class로 관리하신 이유가 궁금해요!
@@ -0,0 +1,90 @@
+package store.controller;
+
+import java.util.List;
+import store.domain.Cart;
+import store.domain.Membership;
+import store.domain.ParsedItem;
+import store.domain.Receipt;
+import store.io.input.StoreInput;
+import store.io.output.StoreOutput;
+import store.service.ConvenienceStoreService;
+
+public class ConvenienceStoreController {
+    private final StoreInput storeInput;
+    private final StoreOutput storeOutput;
+    private final ConvenienceStoreService convenienceStoreService;
+
+    public ConvenienceStoreController(StoreInput storeInput, StoreOutput storeOutput,
+                                      ConvenienceStoreService convenienceStoreService) {
+        this.storeInput = storeInput;
+        this.storeOutput = storeOutput;
+        this.convenienceStoreService = convenienceStoreService;
+    }
+
+    public void start() {
+        boolean continueShopping;
+        try {
+            do {
+                executeShoppingCycle();
+                continueShopping = getValidAdditionalPurchaseResponse();
+            } while (continueShopping);
+        } finally {
+            storeOutput.close();
+        }
+    }
+
+    private void executeShoppingCycle() {
+        convenienceStoreService.printInventoryProductList(storeOutput);
+
+        List<ParsedItem> parsedItems = getValidParsedItems();
+        Cart cart = convenienceStoreService.createCart(parsedItems);
+
+        convenienceStoreService.applyPromotionToCartItems(cart, storeInput);
+
+        Membership membership = getValidMembershipResponse();
+
+        Receipt receipt = convenienceStoreService.createReceipt(cart);
+        storeOutput.printReceipt(receipt, cart, membership);
+
+        updateInventory(cart);
+    }
+
+    private List<ParsedItem> getValidParsedItems() {
+        while (true) {
+            try {
+                String input = storeInput.getPurchaseItemsInput();
+                return convenienceStoreService.parseItems(input);
+            } catch (IllegalArgumentException | IllegalStateException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+
+    private Membership getValidMembershipResponse() {
+        while (true) {
+            try {
+                return convenienceStoreService.determineMembership(storeInput);
+            } catch (IllegalArgumentException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+
+    private void updateInventory(Cart cart) {
+        try {
+            convenienceStoreService.updateInventory(cart);
+        } catch (IllegalStateException e) {
+            storeOutput.printError(e.getMessage());
+        }
+    }
+
+    private boolean getValidAdditionalPurchaseResponse() {
+        while (true) {
+            try {
+                return storeInput.askForAdditionalPurchase();
+            } catch (IllegalArgumentException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+}

리뷰: 해당 함수가 `함수 내부가 10라인 이하`라는 기준을 지키지 않는 것 같습니다.
@@ -0,0 +1,90 @@
+package store.controller;
+
+import java.util.List;
+import store.domain.Cart;
+import store.domain.Membership;
+import store.domain.ParsedItem;
+import store.domain.Receipt;
+import store.io.input.StoreInput;
+import store.io.output.StoreOutput;
+import store.service.ConvenienceStoreService;
+
+public class ConvenienceStoreController {
+    private final StoreInput storeInput;
+    private final StoreOutput storeOutput;
+    private final ConvenienceStoreService convenienceStoreService;
+
+    public ConvenienceStoreController(StoreInput storeInput, StoreOutput storeOutput,
+                                      ConvenienceStoreService convenienceStoreService) {
+        this.storeInput = storeInput;
+        this.storeOutput = storeOutput;
+        this.convenienceStoreService = convenienceStoreService;
+    }
+
+    public void start() {
+        boolean continueShopping;
+        try {
+            do {
+                executeShoppingCycle();
+                continueShopping = getValidAdditionalPurchaseResponse();
+            } while (continueShopping);
+        } finally {
+            storeOutput.close();
+        }
+    }
+
+    private void executeShoppingCycle() {
+        convenienceStoreService.printInventoryProductList(storeOutput);
+
+        List<ParsedItem> parsedItems = getValidParsedItems();
+        Cart cart = convenienceStoreService.createCart(parsedItems);
+
+        convenienceStoreService.applyPromotionToCartItems(cart, storeInput);
+
+        Membership membership = getValidMembershipResponse();
+
+        Receipt receipt = convenienceStoreService.createReceipt(cart);
+        storeOutput.printReceipt(receipt, cart, membership);
+
+        updateInventory(cart);
+    }
+
+    private List<ParsedItem> getValidParsedItems() {
+        while (true) {
+            try {
+                String input = storeInput.getPurchaseItemsInput();
+                return convenienceStoreService.parseItems(input);
+            } catch (IllegalArgumentException | IllegalStateException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+
+    private Membership getValidMembershipResponse() {
+        while (true) {
+            try {
+                return convenienceStoreService.determineMembership(storeInput);
+            } catch (IllegalArgumentException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+
+    private void updateInventory(Cart cart) {
+        try {
+            convenienceStoreService.updateInventory(cart);
+        } catch (IllegalStateException e) {
+            storeOutput.printError(e.getMessage());
+        }
+    }
+
+    private boolean getValidAdditionalPurchaseResponse() {
+        while (true) {
+            try {
+                return storeInput.askForAdditionalPurchase();
+            } catch (IllegalArgumentException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+}

리뷰: while + try-catch가 반복되는 것 같은데, 이를 함수로 만들어 처리해도 좋을 것 같아요.
@@ -0,0 +1,64 @@
+package store.io.input.impl;
+
+import camp.nextstep.edu.missionutils.Console;
+import store.common.ConsoleMessages;
+import store.common.ErrorMessages;
+import store.io.input.StoreInput;
+
+
+public class InputConsole implements StoreInput {
+
+    @Override
+    public String getPurchaseItemsInput() {
+        System.out.print(ConsoleMessages.LINE_SEPARATOR);
+        System.out.println(ConsoleMessages.PURCHASE_ITEMS_PROMPT);
+        return Console.readLine();
+    }
+
+    @Override
+    public boolean askForAdditionalPromo(String itemName, int additionalCount) {
+        System.out.print(ConsoleMessages.LINE_SEPARATOR);
+        System.out.printf(ConsoleMessages.ADDITIONAL_PROMO_PROMPT + ConsoleMessages.LINE_SEPARATOR, itemName,
+                additionalCount);
+        return getYesNoResponse();
+    }
+
+    @Override
+    public boolean askForFullPricePurchase(String itemName, int shortageCount) {
+        System.out.print(ConsoleMessages.LINE_SEPARATOR);
+        System.out.printf(ConsoleMessages.FULL_PRICE_PURCHASE_PROMPT + ConsoleMessages.LINE_SEPARATOR, itemName,
+                shortageCount);
+        return getYesNoResponse();
+    }
+
+    @Override
+    public boolean askForMembershipDiscount() {
+        System.out.print(ConsoleMessages.LINE_SEPARATOR);
+        System.out.println(ConsoleMessages.MEMBERSHIP_DISCOUNT_PROMPT);
+        return getYesNoResponse();
+    }
+
+    @Override
+    public boolean askForAdditionalPurchase() {
+        System.out.print(ConsoleMessages.LINE_SEPARATOR);
+        System.out.println(ConsoleMessages.ADDITIONAL_PURCHASE_PROMPT);
+        return getYesNoResponse();
+    }
+
+    private boolean getYesNoResponse() {
+        while (true) {
+            try {
+                String input = Console.readLine();
+                if ("Y".equals(input)) {
+                    return true;
+                }
+                if ("N".equals(input)) {
+                    return false;
+                }
+                throw new IllegalArgumentException(ErrorMessages.INVALID_INPUT_MESSAGE);
+            } catch (IllegalArgumentException e) {
+                System.out.println(ErrorMessages.ERROR_MESSAGE + e.getMessage());
+            }
+        }
+    }
+}

리뷰: 이 2개의 if문을 별개의 함수로 만들었으면 함수 라인이 좀 더 줄어들 것 같습니다.
@@ -0,0 +1,12 @@
+package store.common;
+
+public class ConsoleMessages {
+    public static final String WELCOME_MESSAGE = "안녕하세요. W편의점입니다.";
+    public static final String PRODUCT_LIST_HEADER = "현재 보유하고 있는 상품입니다.";
+    public static final String PURCHASE_ITEMS_PROMPT = "구매하실 상품명과 수량을 입력해 주세요. (예: [사이다-2],[감자칩-1])";
+    public static final String ADDITIONAL_PROMO_PROMPT = "현재 %s은(는) %d개를 무료로 더 받을 수 있습니다. 추가하시겠습니까? (Y/N)";
+    public static final String FULL_PRICE_PURCHASE_PROMPT = "현재 %s %d개는 프로모션 할인이 적용되지 않습니다. 그래도 구매하시겠습니까? (Y/N)";
+    public static final String MEMBERSHIP_DISCOUNT_PROMPT = "멤버십 할인을 받으시겠습니까? (Y/N)";
+    public static final String ADDITIONAL_PURCHASE_PROMPT = "감사합니다. 구매하고 싶은 다른 상품이 있나요? (Y/N)";
+    public static final String LINE_SEPARATOR = System.lineSeparator();
+}

리뷰: enum은 서로 관련이 있는 상수 집합을 나타낼 때 사용하는것이 좋을 것 같다고 생각해요. 타입 안정성을 강조하는 enum과는 다르게 단지 문자열이나 숫자 값에 대한 재사용성의 의미를 전달하고 싶었어요. 
사실 이런 간단한 문자열 출력까지 상수로 관리해야하나 싶었지만 공통 피드백의 내용을 무시할 순 없어서 상수로 관리 했습니다.
@@ -0,0 +1,90 @@
+package store.controller;
+
+import java.util.List;
+import store.domain.Cart;
+import store.domain.Membership;
+import store.domain.ParsedItem;
+import store.domain.Receipt;
+import store.io.input.StoreInput;
+import store.io.output.StoreOutput;
+import store.service.ConvenienceStoreService;
+
+public class ConvenienceStoreController {
+    private final StoreInput storeInput;
+    private final StoreOutput storeOutput;
+    private final ConvenienceStoreService convenienceStoreService;
+
+    public ConvenienceStoreController(StoreInput storeInput, StoreOutput storeOutput,
+                                      ConvenienceStoreService convenienceStoreService) {
+        this.storeInput = storeInput;
+        this.storeOutput = storeOutput;
+        this.convenienceStoreService = convenienceStoreService;
+    }
+
+    public void start() {
+        boolean continueShopping;
+        try {
+            do {
+                executeShoppingCycle();
+                continueShopping = getValidAdditionalPurchaseResponse();
+            } while (continueShopping);
+        } finally {
+            storeOutput.close();
+        }
+    }
+
+    private void executeShoppingCycle() {
+        convenienceStoreService.printInventoryProductList(storeOutput);
+
+        List<ParsedItem> parsedItems = getValidParsedItems();
+        Cart cart = convenienceStoreService.createCart(parsedItems);
+
+        convenienceStoreService.applyPromotionToCartItems(cart, storeInput);
+
+        Membership membership = getValidMembershipResponse();
+
+        Receipt receipt = convenienceStoreService.createReceipt(cart);
+        storeOutput.printReceipt(receipt, cart, membership);
+
+        updateInventory(cart);
+    }
+
+    private List<ParsedItem> getValidParsedItems() {
+        while (true) {
+            try {
+                String input = storeInput.getPurchaseItemsInput();
+                return convenienceStoreService.parseItems(input);
+            } catch (IllegalArgumentException | IllegalStateException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+
+    private Membership getValidMembershipResponse() {
+        while (true) {
+            try {
+                return convenienceStoreService.determineMembership(storeInput);
+            } catch (IllegalArgumentException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+
+    private void updateInventory(Cart cart) {
+        try {
+            convenienceStoreService.updateInventory(cart);
+        } catch (IllegalStateException e) {
+            storeOutput.printError(e.getMessage());
+        }
+    }
+
+    private boolean getValidAdditionalPurchaseResponse() {
+        while (true) {
+            try {
+                return storeInput.askForAdditionalPurchase();
+            } catch (IllegalArgumentException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+}

리뷰: 기본 제네릭 인터페이스를 사용한다면 좀 더 가독성 좋은 코드가 될 것 같아요 ! 좋은 리뷰 감사해요 :)
@@ -0,0 +1,90 @@
+package store.controller;
+
+import java.util.List;
+import store.domain.Cart;
+import store.domain.Membership;
+import store.domain.ParsedItem;
+import store.domain.Receipt;
+import store.io.input.StoreInput;
+import store.io.output.StoreOutput;
+import store.service.ConvenienceStoreService;
+
+public class ConvenienceStoreController {
+    private final StoreInput storeInput;
+    private final StoreOutput storeOutput;
+    private final ConvenienceStoreService convenienceStoreService;
+
+    public ConvenienceStoreController(StoreInput storeInput, StoreOutput storeOutput,
+                                      ConvenienceStoreService convenienceStoreService) {
+        this.storeInput = storeInput;
+        this.storeOutput = storeOutput;
+        this.convenienceStoreService = convenienceStoreService;
+    }
+
+    public void start() {
+        boolean continueShopping;
+        try {
+            do {
+                executeShoppingCycle();
+                continueShopping = getValidAdditionalPurchaseResponse();
+            } while (continueShopping);
+        } finally {
+            storeOutput.close();
+        }
+    }
+
+    private void executeShoppingCycle() {
+        convenienceStoreService.printInventoryProductList(storeOutput);
+
+        List<ParsedItem> parsedItems = getValidParsedItems();
+        Cart cart = convenienceStoreService.createCart(parsedItems);
+
+        convenienceStoreService.applyPromotionToCartItems(cart, storeInput);
+
+        Membership membership = getValidMembershipResponse();
+
+        Receipt receipt = convenienceStoreService.createReceipt(cart);
+        storeOutput.printReceipt(receipt, cart, membership);
+
+        updateInventory(cart);
+    }
+
+    private List<ParsedItem> getValidParsedItems() {
+        while (true) {
+            try {
+                String input = storeInput.getPurchaseItemsInput();
+                return convenienceStoreService.parseItems(input);
+            } catch (IllegalArgumentException | IllegalStateException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+
+    private Membership getValidMembershipResponse() {
+        while (true) {
+            try {
+                return convenienceStoreService.determineMembership(storeInput);
+            } catch (IllegalArgumentException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+
+    private void updateInventory(Cart cart) {
+        try {
+            convenienceStoreService.updateInventory(cart);
+        } catch (IllegalStateException e) {
+            storeOutput.printError(e.getMessage());
+        }
+    }
+
+    private boolean getValidAdditionalPurchaseResponse() {
+        while (true) {
+            try {
+                return storeInput.askForAdditionalPurchase();
+            } catch (IllegalArgumentException e) {
+                storeOutput.printError(e.getMessage());
+            }
+        }
+    }
+}

리뷰: 10줄 이하라는 기준이 명확한 의도 전달과 불필요한 복잡성 때문이라고 생각해요. 읽기 쉽게 논리적 흐름을 유지한다면 여러 메서드로 분리한 코드보다 좀 더 읽기 쉽지 않을까요 ? 
해당 코드가 읽기 어려우시다면 어떤 부분이 문제라고 생각하세요 ?