고민했던 점
1. Kiosk의 start()메서드의 복잡함
- Kiosk에서 사용자의 입력에 따라서 출력을 보여주는 start()메서드의 로직이 너무 길고 복잡해보여서 개발을 진행하면서도 너무 복잡하고 알아보기가 쉽지 않았음
- 카테고리를 출력하는 부분과, 메뉴를 출력하는 부분을 각각 showCategories(), showMainMenes(Menu menu) 메서드로 분리하여 해결
private void showCategories() {
System.out.println("[ MAIN MENU ]");
for (int i = 0; i < menus.size(); i++) {
System.out.println(i + 1 + ". " + this.menus.get(i).getCategory());
this.indexList.add(i);
}
System.out.println("0. 종료 | 종료");
}
2. 사용자로부터 적절한 값을 검증하는 부분에 대한 고민
- 화면에 출력되는 부분에서 보여지는 숫자값만을 입력해서 검증하는 부분에서 이를 어떤 식으로 할 지 고민을 많이 했음
- 화면에서 리스트 값들을 출력할 때 인덱스 리스트를 만들어, 이 리스트에 값들을 함께 추가한 다음에 사용자가 이 리스트에 해당되는 값만 입력했는지를 검증하는 방법으로 구현
private void showCategories() {
System.out.println("[ MAIN MENU ]");
for (int i = 0; i < menus.size(); i++) {
System.out.println(i + 1 + ". " + this.menus.get(i).getCategory());
this.indexList.add(i);
}
System.out.println("0. 종료 | 종료");
}
검증
private void validInputRangeValue(int inputIndex, List<Integer> validIndexList) throws InvalidInputRangeException {
if (!validIndexList.contains(inputIndex)){
throw new InvalidInputRangeException();
}
}
3. 검증메서드를 실행할 때, 유효한 인덱스 리스트의 조회 방법에 대한 고민
- 동일한 클래스 내부에 있는 indexList 필드이기 때문에 그냥 this.indexList로 검증메서드 매개변수에 전달해야할지 아니면 getter를 만들어서 getter를 통하여 전달해야 할지 고민이 됐음
- 검색을 해본 결과 지금 같은 경우는 상관없지만 JPA 프록시를 다루게 되면 중요해진다고 한다. (김영한 선생님의 답변..)
- 나중에 JPA를 다뤄볼 때 기억할 것!
MenuItem
- 카테고리 내부에 있는 해당 음식들을 관리하는 클래스
- 음식 이름(name), 음식 가격(price), 음식 설명(description) 필드를 가지고 있음
- 무결성을 지키기 위해 각각의 필드는 private 으로 설정하고 getter, setter을 이용 (캡슐화)
public class MenuItem {
private String name;
private double price;
private String description;
MenuItem (String name, double price, String description) {
this.name = name;
this.price = price;
this.description = description;
}
// 각각의 필드에 대한 getter, setter
}
Menu
- 카테고리별로 메뉴를 관리하는 클래스, 해당 카테고리에 해당하는 메뉴 리스트를 가지고 있음
- 음식리스트(menuItems), 해당 음식의 카테고리(category), 음식리스트의 인덱스리스트(menuItemIndexList)
- menuItemIndexList를 만든 이유
- 사용자의 입력번호에 따라서 해당 로직(선택한 음식 출력)을 수행해야 하는데, 유요한 값을 검증하는 부분에서 해당 리스트에 벗어나는 값을 입력하는 경우 InvalidInputRangeException 을 수행하도록 함
- 음식리스트(menuItems)를 출력할 때 menuItemIndexList에 값을 추가함
public class Menu {
private final String category;
private final List<MenuItem> menuItems;
private final List<Integer> menuItemIndexList = new ArrayList<>();
public Menu(String category, List<MenuItem> menuItems) {
this.category = category;
this.menuItems = menuItems;
}
public void showMenuItems(){
for(int i = 0; i < menuItems.size(); i++){
System.out.println( i + 1 + ". " + menuItems.get(i).getName() + " | W " + menuItems.get(i).getPrice() + " | " + menuItems.get(i).getDescription());
menuItemIndexList.add(i+1);
}
}
public List<MenuItem> getMenuItems(){
return this.menuItems;
}
public String getCategory(){
return this.category;
}
public List<Integer> getMenuItemIndexList() {
return this.menuItemIndexList;
}
}
Kiosk
- 사용자에게 메뉴를 보여주고, 해당 입력값에 따라서 결과를 보여주는 역할을 수행하는 클래스
- 카테고리별 메뉴 리스트(menus), 사용자에게 숫자를 입력받았는지를 검증하는 정규표현식 변수(NUMBER_REG), 카테고리 인덱스 리스트(indexList)
- 카테고리 인덱스 리스트(indexList) 또한 menuItemIndexList를 만든 이유와 동일
- 에러를 검증하는 메서드
- validInputValue : 사용자가 숫자를 입력했는지 검증, 숫자 이외의 값을 입력했을 시에 InvalidInputException 객체 생성
- validInputRangeValue : 사용자가 유효한 범위의 숫자를 입력했는지 검증, 유효하지 않은 범위의 숫자를 입력했을 시에 InvalidInputRangeException에러 객체 생성
private void validInputValue(String inputIndex) throws InvalidInputException {
if (!inputIndex.matches(NUMBER_REG)){
throw new InvalidInputException();
}
}
private void validInputRangeValue(int inputIndex, List<Integer> validIndexList) throws InvalidInputRangeException {
if (!validIndexList.contains(inputIndex)){
throw new InvalidInputRangeException();
}
}
public class Kiosk {
private final List<Menu> menus;
private final String NUMBER_REG = "[0-9]+";
private final List<Integer> indexList = new ArrayList<>();
public Kiosk(List<Menu> menus) {
this.menus = menus;
}
public void start() {
Scanner sc = new Scanner(System.in);
while (true) {
try {
showCategories();
String inputCategoryIndex = sc.next();
if ("0".equals(inputCategoryIndex)) {
System.out.println("프로그램이 종료되었습니다.");
break;
}
validInputValue(inputCategoryIndex);
int categoryIndex = Integer.parseInt(inputCategoryIndex) - 1;
validInputRangeValue(categoryIndex, this.getIndexList());
Menu menu = this.menus.get(categoryIndex);
showMainMenes(menu);
while (true){
String inputMenuIndex = sc.next();
if ("0".equals(inputMenuIndex)) {
System.out.println("메인 화면으로 돌아갑니다.");
break;
}
validInputValue(inputMenuIndex);
int menuIndex = Integer.parseInt(inputMenuIndex) - 1;
validInputRangeValue(menuIndex, menu.getMenuItemIndexList());
MenuItem menuItem = menu.getMenuItems().get(menuIndex);
System.out.println("선택한 메뉴 : " + menuItem.getName() + " | W " + menuItem.getPrice() + " | " + menuItem.getDescription());
}
} catch (InvalidInputException | InvalidInputRangeException e){
System.out.println(e.getMessage());
}
}
}
public List<Integer> getIndexList() {
return this.indexList;
}
private void showCategories() {
System.out.println("[ MAIN MENU ]");
for (int i = 0; i < menus.size(); i++) {
System.out.println(i + 1 + ". " + this.menus.get(i).getCategory());
this.indexList.add(i);
}
System.out.println("0. 종료 | 종료");
}
private void showMainMenes(Menu menu) {
System.out.println("[ " + menu.getCategory()+ " MENU ]");
menu.showMenuItems();
System.out.println("0. 뒤로가기");
}
}
'JAVA' 카테고리의 다른 글
키오스크에 장바구니 및 구매하기 기능 추가하기 (+반성의 글..) (0) | 2025.01.20 |
---|---|
객체지향적인 계산기 만들기 : 멘토님 코드와 나의 코드간의 개선점 비교 (0) | 2025.01.13 |
제네릭 타입제한과 필드에서의 값 전달 (feat : 계산기 과제) (0) | 2025.01.13 |
Enum 및 예외처리를 적용한 계산기 만들기 (0) | 2025.01.10 |
Lambda & Stream을 이용하여 특정 값보다 큰 값들만 조회하기 (0) | 2025.01.09 |