<일기>
피부과 다녀왔다. 두드러기가 이제 거의 없어져서 4일치 약 처방해줄테니 다 먹고 나으면 안 와도 된다고 했다. 벌써 의사분이랑 간호사분들, 약사분들 정들었는데 아쉽?네.
</일기>
오늘은 하루종일 자바 개인 과제 리팩토링을 진행했다. 정말 대공사였다.
디렉토리 구조가 왼쪽에서 오른쪽으로 간.. 하루 내내 작업했다. 다 리팩토링 해두고 보니까 정말 깔끔하게 잘 해뒀다.
과제 피드백에서 나온 개선할 점들은 크게 4가지다.
1. 클래스 분리가 너무 과하다.
2. Input 인터페이스 분리가 과한 거 같다.
3. Order 의 역할이 없다.
4. 주석이 없다.
그래서 1, 2, 3번 다 삭제를 해버렸고, 주석도 public 클래스와 메서드에 대해서 다 javadoc 달아두었다.
그리고 InputUtil 클래스를 추가했고, 메뉴와 주문 도메인을 나누어 MVC 패턴을 적용했다.
특히 리팩토링 하면서 튜터님께서 다음 고칠 때는 잘못된 입력을 받으면 다시 받아보게 해보라고 숙제를 냈었는데, 그거는 InputUtil 클래스 내에서 람다를 이용했다.
public final class InputUtil { // 유틸 클래스로 상속, 생성 불가능
private static final int MENU_LENGTH = Category.values().length + 2;
private static final Scanner scanner = new Scanner(System.in);
private InputUtil() {}
/**
* 잘못된 입력 받을 시 계속 입력을 받도록 하는 함수.
*
* @param validator 올바른 입력을 검증하는 람다식
* @return 검증된 입력 번호를 리턴
*/
private static int readWithValidator(Predicate<Integer> validator) {
while (true) {
try {
int number = scanner.nextInt(); // 정수가 아니라면 예외 발생으로 다시 입력 받음
validate(validator, number); // 올바른 입력이 아니라면 예외 발생으로 다시 입력 받음
return number;
} catch (RuntimeException e) {
System.out.println("잘못된 입력입니다. 다시 입력해주세요.");
scanner.nextLine(); // 버퍼에 남은 값들 제거
}
}
}
private static void validate(Predicate<Integer> validator, int number) {
if (!validator.test(number)) {
throw new IllegalArgumentException();
}
}
/**
* 메인화면에서 메뉴 번호를 입력 받음
*/
public static int readMenuNumber() {
return readWithValidator(input -> (0 <= input && input <= MENU_LENGTH));
}
/**
* 특정 카테고리 내의 상품 번호를 입력 받음
*
* @param categoryNumber 특정 카테고리 번호
*/
public static int readProductNumber(int categoryNumber) {
return readWithValidator(input -> (0 < input && input <= getCategorySize(categoryNumber)));
}
}
Predicate 인터페이스를 이용하여 특정 입력 케이스 전용 검증기로 검증받도록 짰다. 이거 좀 잘 짠..줄 알았는데 ㅈㅎ님께 리뷰 받아보니 입력 역할과 검증 역할을 동시에 하고 있다고 피드백 받았다. 그렇네,,
기존에는 입력과 출력을 묶었는데, 이제는 MVC 패턴으로 출력은 View가 담당하고, 입력은 유틸 클래스로 위처럼 하도록 했다.
그리고 또 기존 코드에서는 if-else if 문을 핸들러로 처리를 했었는데, 핸들러를 지우면서 다시 if-else if 문들이 여러 줄 있었다.
public final class CafeKioskApp { // 상속 불가능
// 메뉴 담당 컨트롤러
private static final MenuController menuController = new MenuController(new MenuView());
// 주문 담당 컨트롤러
private static final OrderController orderController = new OrderController(new OrderView(), new Cart(), new SalesRecord());
private static final int SALES_RECORD_NUMBER = 0;
private static final int MENU_START_NUMBER = 1;
private static final int MENU_END_NUMBER = Category.size();
private static final int ORDER_NUMBER = Category.size() + 1;
private static final int ORDER_CANCEL_NUMBER = Category.size() + 2;
private CafeKioskApp() {} // 생성 불가능
public static void run() { // 유일한 진입점
while (true) { // 아래 로직을 계속 반복
int menuNumber = menuController.getMenuNumber(); // 메뉴 번호를 입력 받음
if (menuNumber == SALES_RECORD_NUMBER) { // 총 판매 실적 조회
orderController.showAllSalesRecord();
} else if (MENU_START_NUMBER <= menuNumber && menuNumber <= MENU_END_NUMBER) { // 카테고리 선택
int productNumber = menuController.getProductNumber(menuNumber); // 카테고리 내 상품 선택
orderController.putCart(menuNumber, productNumber); // 장바구니 추가
} else if (menuNumber == ORDER_NUMBER) { // 주문 진행
orderController.order();
} else if (menuNumber == ORDER_CANCEL_NUMBER) { // 주문 취소
orderController.cancelOrder();
}
}
}
}
줄이 꽤 길어서 불-편해서 이를 다시 핸들러로 처리를 하는게 옳은가, 아니면 이정도는 요구사항이 변할 일이 거의 없으니 괜찮은가를 고민해서 튜터님께 찾아갔다. 그랬더니 튜터님은 정답은 없다고 했다. ㅠㅠ,, 하지만 클래스를 잘게 분해도 해보고, 이렇게 늘여놓기도 해봤으니 나중에 더 길어지면 일단 방법은 알고 있으니 이후에 처리해도 괜찮은 것 같다고 말 했던 것 같다.
너무 클린코드를 신봉한걸까 싶다. 주석도 코드를 잘 읽히게 쓰면 필요없다고 적혀있지만 사실 구글 스타일 가이드에서도 자바독은 쓰라고 되어있으니,,
내일부터 드디어 스프링!
'TIL ✍️' 카테고리의 다른 글
23년 11월 1일(수요일) - 23번째 TIL : String.repeat vs StringBuilder.append 속도 차이 (2) | 2023.11.01 |
---|---|
23년 10월 31일(화요일) - 22번째 TIL (1) | 2023.10.31 |
23년 10월 28일(토요일) - 20번째 TIL (0) | 2023.10.28 |
23년 10월 27일(금요일) - 19번째 TIL (0) | 2023.10.27 |
23년 10월 26일(목요일) - 18번째 TIL (1) | 2023.10.26 |