Light Blue Pointer
본문 바로가기
Developing/Journal

[내일배움캠프][Team Project]키오스크 개발일지

by Greedy 2023. 10. 25.

https://github.com/minisundev/Kiosk

 

GitHub - minisundev/Kiosk: Kiosk program for a burger place

Kiosk program for a burger place. Contribute to minisundev/Kiosk development by creating an account on GitHub.

github.com

오늘의 목표

오늘의 목표는 Burger,Icecream,Beer,Drink(Product의 subclass들)을 Product로 대체하기

burgers 등으로 Product ArrayList들 명명 x 이름 없이 그냥 Menu에 Product ArrayList 넣고

size와 index로 다 돌아가는 프로그램을 만드는 것이다

달성 완료했고 내가 팀에서 맡은 기능 구현까지 끝냈다!

 

개발하면서 생각한 것

키오스크롤 다시 뜯어고치면서 보니까

오버라이딩에 집착하면서 Product를 세세하게 나누고 Product에 field로 안 만들고 static으로 값을 저장해서 이용했던 과거의 방식이 얼마나 비효율적인지 알게되었다

이름 따로 가격 따로 설명 따로 각각 별개의 Static ArrayList에다 넣고 이용했는데 field의 종류와 개수, 사용하는 함수가 모두 동일한 객체들을 Subclass로 세세하게 쪼개니까 너무 비효율적이었음

field가 동일한 객체들을 어떻게 잘 일반화하여 하나의 객체로 묶어내느냐가 효율적인 코드에 중요한 거 같다

그리고 오버라이딩에 대한 집착을 버리기로 했다 클래스 설계가 효과적으로 되는 것이 그 무엇보다도 중요하다고 느꼈다

클래스 설계가 효율적으로 되자마자 if else나 switch로 case 분류해야 했던 코드가 이십몇줄이나 줄어드는 기적을 보았다

Q. selectP는 한줄인데 저걸 빼는게 좋은지 그냥 넣어두는게 좋은지 질문

 

하다보니까 메뉴랑 상품이랑 상속관계가 있으면 안 될 거 같아서 그냥 extends 빼고 분리했는데 처음부터 그런 생각이 드는 설계를 잘 하는 개발자가 되고싶다 Menu 안에 Product들이 담겨야 하는데 그럼 상속되면 구조가 이상해진다는 걸 개발하다가 깨달았다

내가 초보라서 항상 일단 코드 우다다다 써놓고 좀 이상하니까 효율적으로 되도록 클래스 설계부터 그냥 모든걸 뜯어고치는 거 같은데 코드를 다량으로 써놓고 수정하려니까 에러날까봐 좀 조심스럽게 단계적으로 고치게 되고 일이 무척이나 쓸데없이 많아진 걸 느꼈다 코드를 새로 작성하는 것보다 이미 비효율적으로 많이 짜놓고 나중에 개선하는게 더 힘들다는 것을 느꼈다

 

그리고 자바 기반으로 자료구조에 대해서 공부하고 싶어졌다 

현재 코드에서 for문으로 하나하나 대조하면서 상품이나 메뉴를 찾고 있는데

며칠 전에 코테 푸는데 딕셔너리 안 쓰고 for문으로 하니까 되긴 되는데 시간초과로 통과가 안 돼서 딕셔너리로 푼 문제가 떠올랐다. 

for문 돌리는게 너무 비효율적으로 느껴져서 HashMap에다 인덱스랑 이름만 따로 저장해볼까 하는 생각이 들고 좀 데이터를 효율적으로 다루는 개발자가 되고싶어졌다.

 

맨날 뭔가 처리해야할때 함수를 return 한 후에 호출한 함수에서 처리하는 식으로 함수를 짰었다

왜 그런 버릇이 있는지는 모르겠으나 오늘 코드를 다시 보면서 내 습관이 비효율적이고 상당히 좋지 못한 방식이라는 걸 느끼게 되었다

남들이 이해하기에 상당히 어렵고 코드가 지저분해지는 방식인 거 같다

오늘 그냥 호출된 함수 내에서 처리를 다 끝내는 방식으로 함수를 수정하니까 함수 이름이랑 함수에서 처리하는 일이 맥락에 맞고 딱딱 함수별로 수행하는 일이 구분이 되면서 더 깔끔해졌다

 

그리고 내가 어떻게 허접한지를 깨달아가는 과정이 너무 재밌다 예전에는 개발에 미쳐서 주말에도 사이드프로젝트 하는 사람들 이해가 안 됐는데 지금은 이해가 간다

이런 기본적인 과제 하는데도 어제보다 나아지는걸 느끼고 재밌는데 개발자로 성장하는게 어떻게 재미가 없을수가 있을까

빨리 취직해서 사수한테 코드리뷰도 당해보고싶고 이것보다 더 복잡하고 큰 프로그램 개발에 일조하면서 더 많은 생각을 하면서 더 나은 개발을 하는 사람이 되고싶다

개발하면서 돈을 벌 수 있다면 축복받은 삶일 것 같아

 

 

개발 과정

💡개선 : 이렇게 있고 이렇게 쓰던 거 그냥 Product에 인덱스 붙어서 출력되는 버전으로 바꿔버림

Beer.java
public static void printProduct() {//메뉴 선택시 출력
        System.out.println("[ Beer MENU ]");
        for (int i = 0; i < beers.size(); i++) {//for문 돌면서 있으면 출력
            System.out.println((i + 1) + ". " + beers.get(i).getName() + "   | W " + beers.get(i).getPrice() + " | " + beers.get(i).getDesc());
        }
    }

이렇게 각각 구현되어 있던 것을

Product.java
public static void printIndex(ArrayList<Product> p) {
        for (int i = 0; i < p.size(); i++) {//for문 돌면서 있으면 출력
            System.out.println((i + 1) + ". " +p.get(i).getName() + "   | W " + p.get(i).getPrice() + " | " + p.get(i).getDesc());
        }
    }

그냥 이렇게 상위클래스에다 합침

case 1:
                    System.out.println("[ Burger MENU ]");
                    Product.printIndex(Burger.burgers);
                    break;

이렇게 개선되었다

 

💡개선 :  그리고 버거의 모든 버거를 Product로 대체했다, 장차 ArrayList burgers와 모든 함수들을 다른 클래스로 옮기기 위해서

public class Burger extends Product {

    public static ArrayList<Product> burgers = new ArrayList<Product>();

    public static Product select(int select){
        int index = select-1;
        return burgers.get(index);
    }

    public Burger(String name, String desc, double price) {//새로 생성하는 생성자
        super.setName(name);
        super.setId("burger"+burgers.size());
        super.setDesc(desc);
        super.setCount(0);
        super.setPrice(price);
        burgers.add(this);
    }

    public static void clear() {//count 비우는 함수
        for (Product x : burgers) {//for문 돌면서 있으면 출력
            x.setCount(0);
        }
    }

    public static int getSize() {
        return burgers.size();
    }
}

 

💡개선 :   burgers로 코드 내에서 명명하지 않고 사용할 수 있어야 새 메뉴를 추가할 수 있을 거 같아서 burgers대신 이름없는 Product ArrayList를 Menu당 하나씩 넣어놓고 쓰기로 함

 

💡개선 :   clear함수 Burger,Icecream,Drink,Beer에 따로따로 있던거 Product로 합침

Burgers.java(Burger extends Product)
public static void clear() {//count 비우는 함수
        for (Burger x : burgers) {//for문 돌면서 있으면 출력
            x.setCount(0);
        }
    }
//4개를 1개로 합침->

Product.java
public static void clear(ArrayList<Product> products) {//count 비우는 함수
        for (Product x : products) {//for문 돌면서 있으면 출력
            x.setCount(0);
        }
    }

 

 

💡개선 :   그리고 각 서브클래스에 있던 Product ArrayList burgers,icecreams,beers,drinks 들을 Menu로 옮김

💡개선 :   select 함수들도 통합

public static Product select(int select){
        int index = select-1;
        return burgers.get(index);
    }

이런식으로 각각 클래스 내부에 있던거 KioskApp으로 다 옮김

public static Product selectBurger(int select){
        int index = select-1;
        return burgers.get(index);
    }

이렇게 각각 구현했다가 하나의 select 함수로 통일함

public static Product selectP(int menu, int product){
        return menus.get(menu-1).products.get(product-1);
    }

💡개선 :   getSize() 함수들도 통합

public static int getIcecreamSize(){
        return icecreams.size();
    }

통합하려다가 이 ArrayList들이 KioskApp 내부에 있게 되면 private이어도 상관없이 size 그냥 읽으면 돼서 없애버림

 

 

💡개선 :   Menu랑 Product 필드 수정하고 Burger,Icecream,Beer,Drink에 있던 생성자 Product 생성자만 쓰게 함

public Product(String name, String desc, double price, int count) {
        super(name, desc);
        this.price = price;
        this.count = count;
    }

이걸
이렇게 수정

public Product(String productName, String productDesc, double price, int count) {
        //super(name, desc);
        this.productName = productName;
        this.productDesc = productDesc;
        this.price = price;
        this.count = count;
    }
    public Product(String menuName, String menuDesc,String productName, String productDesc, double price, int count) {
        super(menuName, menuDesc);
        this.productName = productName;
        this.productDesc = productDesc;
        this.price = price;
        this.count = count;
    }

💡개선 :   Burger생성자 대신 Product에 모든거 다 넣고 menu명으로 burger인지 구분하고 menu명으로 어디 들어있는지 알아내서 거기다 넣어줌

💡개선 :   하다보니까 메뉴랑 상품이랑 상속관계가 있으면 안 될 거 같아서 그냥 extends 빼고 분리함

Menu 안에 Product들이 담겨야 하는데 그럼 상속되면 구조가 이상해짐

public Burger(String name, String desc, double price) {//새로 생성하는 생성자
        super.setName(name);
        super.setId("burger"+KioskApp.burgers.size());
        super.setDesc(desc);
        super.setCount(0);
        super.setPrice(price);
        KioskApp.burgers.add(this);
    }

이렇게 네개가 다 따로 구현되어 있던 거 수정함
public Product(String productName, String productDesc, double price, int count) {
        this.name = productName;
        this.desc = productDesc;
        this.price = price;
        this.count = count;
    }

    //새로 상품 추가할때
    public static void createProduct(String menuName, String productName, String productDesc, double price) {

        Product tempP = new Product(productName,productDesc,price,0);

        ArrayList<Menu> menus =KioskApp.menus;
        boolean newMenus = true;
        for (int i=0;i<menus.size();i++){
            if(menus.get(i).getName().equals(menuName)){
                menus.get(i).products.add(tempP);
                newMenus = false;//새 메뉴가 아님
            }
        }
        //for문을 도는 동안 같은 메뉴이름인게 안 나왔으면 새 메뉴임
        if(newMenus){
            System.out.println("메뉴 설명을 입력해 주세요");
            Scanner sc = new Scanner(System.in);
            String menuDesc = sc.nextLine();
            Menu tempM = new Menu(menuName,menuDesc);
            tempM.products.add(tempP);
            menus.add(tempM);
        }
    }

public static void createMenu(String name, String desc){
        ArrayList<Menu> menus =KioskApp.menus;
        boolean newMenus = true;
        for (int i=0;i<menus.size();i++){
            if(menus.get(i).getName().equals(name)){
                newMenus = false;//새 메뉴가 아님
            }
        }
        //for문을 도는 동안 같은 메뉴이름인게 안 나왔으면 새 메뉴임
        if(newMenus){
            menus.add(new Menu(name,desc));
        }
    }

    public Menu(String name, String desc) {
        this.name = name;
        this.desc = desc;
//        ArrayList<Menu> menus =KioskApp.menus;
//        menus.add(this);
    }

장바구니 이름이 menus였는데 그거 cart로 수정함

Menu 객체를 담는 menus ArrayList를 새로 생성했다

 

 

💡개선 :   클래스 설계가 잘 되니까 대충 16줄이 4줄로 줄어든다

/*개수 카운트 비워줌*/
                Product.clear(burgers);
                Product.clear(icecreams);
                Product.clear(beers);
                Product.clear(drinks);

이거 이렇게 수정

/*개수 카운트 비워줌*/
for (Menu m : menus) {
                    for (Product p : m.products) {
                        p.setCount(0);
                    }
                }

 

 

💡개선 :  하드코딩 메뉴판 대신 ArrayList에 있는 값에 따라 변화하게 바꿨다

코드는 수정을 안 해도 되고 ArrayList만 건드리면 되게 되었다

Scanner sc = new Scanner(System.in);
            System.out.println("SHAKESHACK BURGER 에 오신걸 환영합니다.\\n" +
                    "아래 메뉴판을 보시고 메뉴를 골라 입력해주세요.\\n" +
                    "[ SHAKESHACK MENU ]\\n" +
                    "1. Burgers         | 앵거스 비프 통살을 다져만든 버거\\n" +
                    "2. Forzen Custard  | 매장에서 신선하게 만드는 아이스크림\\n" +
                    "3. Drinks          | 매장에서 직접 만드는 음료\\n" +
                    "4. Beer            | 뉴욕 브루클린 브루어리에서 양조한 맥주\\n\\n" +
                    "[ ORDER MENU ]\\n" +
                    "5. Order       | 장바구니를 확인 후 주문합니다.\\n" +
                    "6. Cancel      | 진행중인 주문을 취소합니다.\\n" +
                    "7. Exit      | 주문 앱에서 나갑니다."
            );
            menu = sc.nextInt();

이거 이렇게 수정

Scanner sc = new Scanner(System.in);
            System.out.println("SHAKESHACK BURGER 에 오신걸 환영합니다.\\n" +
                    "아래 메뉴판을 보시고 메뉴를 골라 입력해주세요.\\n" +
                    "[ SHAKESHACK MENU ]\\n");
            
            int i = Menu.printIndex(menus);

            System.out.println("[ ORDER MENU ]\\n" +
                    i+". Order       | 장바구니를 확인 후 주문합니다.\\n" +
                    (i+1)+". Cancel      | 진행중인 주문을 취소합니다.\\n" +
                    (i+2)+". Exit      | 주문 앱에서 나갑니다."
            );
            menu = sc.nextInt();

 

 

if ((0 < menu) && (menu < 5)) {//버거,아이스크림,음료,맥주
                selectProduct(menu);
            } else if (menu == 5) {//Order
                int order = order();
                if (order == 1) {//1이면 주문 2이면 걍 반복
                    return 1;
                }
            } else if (menu == 6) {//Cancel
                int order = cancel();
                if (order == 1) {//1이면 주문취소 아니면 걍 반복
                    return 2;
                }
            }else if(menu==0){//총 판매 상품목록 출력
                return 3;
            }else if(menu ==7){//나가기, while문 break;
                return 0;
            }

이거 이렇게 수정

if ((0 < menu) && (menu < menus.size())) {//메뉴 안에 있으면
                selectProduct(menu);
            } else if (menu == menus.size()) {//Order
                int order = order();
                if (order == 1) {//1이면 주문 2이면 걍 반복
                    return 1;
                }
            } else if (menu == (menus.size()+1)) {//Cancel
                int order = cancel();
                if (order == 1) {//1이면 주문취소 아니면 걍 반복
                    return 2;
                }
            }
            else if(menu == (menus.size()+2)){//나가기, while문 break;
                return 0;
            }else if(menu==0) {//총 판매 상품목록 출력
                return 3;
            }

 

💡개선 :   클래스를 쓸데없이 많이 분화시켜서 케이스분류를 이렇게나 많이 해줘야 했던 것이 대폭 줄어들었다

public static void selectProduct(int menu) {
        while (true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("SHAKESHACK BURGER 에 오신걸 환영합니다.\\n" +
                    "아래 상품메뉴판을 보시고 상품을 골라 입력해주세요.\\n\\n");

            switch (menu) {
                case 1:
                    System.out.println("[ Burger MENU ]");
                    Product.printIndex(burgers);
                    break;
                case 2:
                    System.out.println("[ Frozen Custard MENU ]");
                    Product.printIndex(icecreams);
                    break;
                case 3:
                    System.out.println("[ Drink MENU ]");
                    Product.printIndex(drinks);
                    break;
                case 4:
                    System.out.println("[ Beer MENU ]");
                    Product.printIndex(beers);
                    break;
                default:
                    continue;
            }

            int select = sc.nextInt();

            Product product;

            switch (menu) {
                case 1:
                    if ((0 < select) && (select <= getBurgerSize())){
                        product = selectBurger(select);
                    } else {
                        continue;
                    }
                    break;
                case 2:
                    if ((0 < select) && (select <= getIcecreamSize())) {
                        product = selectIcecream(select);
                    } else {
                        continue;
                    }
                    break;
                case 3:
                    if ((0 < select) && (select <= getDrinkSize())) {
                        product = selectDrink(select);
                    } else {
                        continue;
                    }
                    break;
                case 4:
                    if ((0 < select) && (select <= getBeerSize())) {
                        product = selectBeer(select);
                    } else {
                        continue;
                    }
                    break;
                default:
                    continue;
            }

이거 이렇게 수정함.

 정말 짧아졌다 이거 고치고 뼈저리게 느꼈다 클래스 설계가 진짜 중요하다는걸, 그리고 내가 쓸데없이 나눠놔서 케이스분류 하느라 여태까지 엄청 힘들었다는걸

public static void selectProduct(int menu) {
        while (true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("SHAKESHACK BURGER 에 오신걸 환영합니다.\\n" +
                    "아래 상품메뉴판을 보시고 상품을 골라 입력해주세요.\\n\\n");

            Menu m = menus.get(menu-1);
            System.out.println("[ "+m.getName()+" MENU ]");
            Product.printIndex(m.products);
            
            int select = sc.nextInt();

            Product product;

            if ((0 < select) && (select <= m.products.size())){
                product = selectP(menu,select);
            }else{
                continue;
            }

 

🚩문제 : 버거만 나오게 하고 싶은데 모든게 다 나옴

아래 메뉴판을 보시고 메뉴를 골라 입력해주세요. [ SHAKESHACK MENU ]

  1. Burger | 앵거스 비프 통살을 다져만든 버거
  2. Frozen Custard | 매장에서 신선하게 만드는 아이스크림
  3. Drink | 매장에서 직접 만드는 음료
  4. Beer | 뉴욕 브루클린 브루어리에서 양조한 맥주 [ ORDER MENU ]
  5. Order | 장바구니를 확인 후 주문합니다.
  6. Cancel | 진행중인 주문을 취소합니다.
  7. Exit | 주문 앱에서 나갑니다. 1 SHAKESHACK BURGER 에 오신걸 환영합니다. 아래 상품메뉴판을 보시고 상품을 골라 입력해주세요.

[ Burger MENU ]

  1. ShackBurger | W 6.9 | 토마토, 양상추, 쉑소스가 토핑된 치즈버거
  2. SmokeShack | W 8.9 | 베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거
  3. Shroom Burger | W 9.4 | 몬스터 치즈와 체다 치즈로 속을 채운 베지테리안 버거
  4. Cheeseburger | W 6.9 | 포테이토 번과 비프패티, 치즈가 토핑된 치즈버거
  5. Hamburger | W 5.4 | 비프패티를 기반으로 야채가 들어간 기본버거
  6. Lager | W 6.5 | 강한 탄산감이 있는 청량한 맥주
  7. Ale | W 6.5 | 풍부한 향과 단맛이 나는 높은 바디감의 맥주
  8. Abita Root Beer | W 5.4 | 맥주인 척 하는 탄산음료
  9. Classic Hand-Spun Shakes | W 6.5 | 쫀득하고 진한 커스터드가 들어간 클래식 쉐이크
  10. Floats | W 6.5 | 부드러운 바닐라 커스터드와 톡톡 터지는 탄산이 만나 탄생한 색다른 음료
  11. Cup & Cones | W 5.4 | 매일 점포에서 신선하게 제조하는 쫀득하고 진한 아이스크림
  12. Raspberry Lemonade | W 6.5 | 쉐이크쉑 시그니처 레몬에이드에 상큼 달콤한 라즈베리가 더해진 시즌 한정 레몬에이드
  13. Lemonade | W 6.5 | 매장에서 직접 만드는 상큼한 레몬에이드
  14. Fresh Brewed Iced Tea | W 5.4 | 직접 유기농 홍차를 우려낸 아이스 티
System.out.println("[ "+m.getName()+" MENU ]");
            Product.printIndex(m.products);

여기가 잘못된듯

public static void printIndex(ArrayList<Product> p) {
        for (int i = 0; i < p.size(); i++) {//for문 돌면서 있으면 출력
            System.out.println((i + 1) + ". " +p.get(i).getName() + "   | W " + p.get(i).getPrice() + " | " + p.get(i).getDesc());
        }
    }

이건 잘못되지 않았는데

⛳해결 : products를 내가 static으로 만들어서 거기 다 들어가버린듯

public static ArrayList<Product> *products* = new ArrayList<Product>();

public ArrayList<Product> products;

public Menu(String name, String desc) {
        this.name = name;
        this.desc = desc;
        this.products = new ArrayList<Product>();
    }

static 빼서 해결함

 

 

🚩문제:

4.Beer | 뉴욕 브루클린 브루어리에서 양조한 맥주 [ ORDER MENU ]

5.Order | 장바구니를 확인 후 주문합니다.

6.Cancel | 진행중인 주문을 취소합니다.

7.Exit | 주문 앱에서 나갑니다. 4 아래와 같이 주문 하시겠습니까? [ Orders ] ShackBurger | W 6.9 | 4개 | 토마토, 양상추, 쉑소스가 토핑된 치즈버거 [ Total ] W 20.700000000000003

  1. 주문 2. 메뉴판

⛳해결 : 주문 인덱스가 잘못됨

이거 수정했음

if ((0 < menu) && (menu < menus.size())) {//메뉴 안에 있으면
                selectProduct(menu);
            } else if (menu == menus.size()) {//Order
                int order = order();
                if (order == 1) {//1이면 주문 2이면 걍 반복
                    return 1;
                }

if ((0 < menu) && (menu <= menus.size())) {//메뉴 안에 있으면
                selectProduct(menu);
            } else if (menu == menus.size()) {//Order
                int order = order();
                if (order == 1) {//1이면 주문 2이면 걍 반복
                    return 1;
                }

 

이로써 오늘의 목표였던 burgers같이 이름 짓지 않고 동적으로 ArrayList에다 추가해서 쓰고

인덱스도 유동적으로 변하게 만드는 거 완료!

 

추가적으로 내가 팀플에서 맡은 부분인 상품/메뉴 생성 함수 구현함

KioskApp.java
Scanner sc = new Scanner(System.in);
            System.out.println("SHAKESHACK BURGER MANAGEMENT APP.\\n" +
                    "원하는 기능을 골라 입력해주세요.\\n" +
                            "1. 대기주문 목록\\n" +
                            "2. 완료주문 목록\\n" +
                            "3. 상품 생성\\n" +
                    "4. 상품 삭제\\n" +
                    "5. 나가기"
            );
            select = sc.nextInt();

            if(select == 1){//대기주문 목록 함수 호출

            }else if(select ==2){//완료주문 목록 함수 호출

            }else if(select ==3){//상품 생성 함수 호출
                createProduct();

...

public static void createProduct(){
        Scanner sc = new Scanner(System.in);
        System.out.println("[  상품 등록  ]");
        System.out.println("메뉴 이름을 입력해 주세요");
        String menuName = sc.nextLine();
        System.out.println("상품 이름을 입력해 주세요");
        String productName = sc.nextLine();
        System.out.println("상품 설명을 입력해 주세요");
        String productDesc = sc.nextLine();
        System.out.println("상품 가격을 입력해 주세요");
        double price = sc.nextDouble();
        Product.createProduct(menuName, productName, productDesc,price);
    }

Product.java
//새로 상품 추가할때
    public static void createProduct(String menuName, String productName, String productDesc, double price) {

        Product tempP = new Product(productName,productDesc,price,0);

        ArrayList<Menu> menus =KioskApp.menus;
        boolean newMenus = true;
        for (int i=0;i<menus.size();i++){
            if(menus.get(i).getName().equals(menuName)){
                menus.get(i).products.add(tempP);
                newMenus = false;//새 메뉴가 아님
            }
        }
        //for문을 도는 동안 같은 메뉴이름인게 안 나왔으면 새 메뉴임
        if(newMenus){
            System.out.println("메뉴 설명을 입력해 주세요");
            Scanner sc = new Scanner(System.in);
            String menuDesc = sc.nextLine();
            Menu tempM = new Menu(menuName,menuDesc);
            tempM.products.add(tempP);
            menus.add(tempM);
        }
    }

Menu.java
public static void createMenu(String name, String desc){
        ArrayList<Menu> menus =KioskApp.menus;
        boolean newMenus = true;
        for (int i=0;i<menus.size();i++){
            if(menus.get(i).getName().equals(name)){
                newMenus = false;//새 메뉴가 아님
                System.out.println("이미 존재하는 메뉴입니다.");
            }
        }
        //for문을 도는 동안 같은 메뉴이름인게 안 나왔으면 새 메뉴임
        if(newMenus){
            menus.add(new Menu(name,desc));
        }
    }

    public Menu(String name, String desc) {
        this.name = name;
        this.desc = desc;
        this.products = new ArrayList<Product>();
        this.id = "Menu"+products.size();
    }

for문의 코드 실행을 다소 향상시키기 위해서 break;를 추가해봄

for (int i=0;i<menus.size();i++){
            if(menus.get(i).getName().equals(menuName)){
                tempP.setId(menuName+(menus.get(i).products.size()));
                menus.get(i).products.add(tempP);
                newMenus = false;//새 메뉴가 아님
                break;
            }
        }

 

 

뭔가 처리해야할때 함수를 return 한 후에 호출한 함수에서 처리하는 버릇이 있는지 그런식으로 함수를 짰었는데

남들이 이해하기에 상당히 어렵고 코드가 지저분해지는 방식인 거 같다고 생각했다 

오늘 그냥 호출된 함수 내에서 처리를 다 끝내는 방식으로 함수를 수정하니까 함수 이름이랑 함수에서 처리하는 일이 딱딱 구분이 되면서 더 편리해졌다

 

 

💡개선 : 코드 정리해서 모음

selectProduct(int menu)함수 내부 -------

			int confirm = 0;
            while (confirm == 0) {
                product.printDescTotal();//개수출력
                **confirm = confirmMenu();**
            }
            if (confirm == 1) {

                product.increaseCount();//산다 하면 물품 개수만 올려준다 동일한 이름으로 생성 x
                boolean newMenu = true;
                for (Product p : cart) {
                    if(p.getId()==product.getId()){
                        newMenu = false;
                        break;
                    }
                }
                if(newMenu == true){
                    cart.add(product);
                }
                System.out.println(product.getName() + " 가 장바구니에 추가되었습니다.");
            }
public static int **confirmMenu()** {
        while (true) {

            Scanner sc = new Scanner(System.in);
            System.out.println("위 메뉴를 장바구니에 추가하시겠습니까?\\n" +
                    "1. 확인        2. 취소");
            int confirm = sc.nextInt();
            if (confirm == 1) {
                return confirm;
            } else if (confirm == 2) {
                return confirm;
            }
        }
    }

이렇게 두군데에 나눠져 있었던 코드를 함수 내용이 딱 구분되고 이름이 잘 나타내게 하나의 함수에 넣음

product.printDescTotal();//개수출력
confirmMenu(product);
public static void confirmMenu(Product product) {
        while (true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("위 메뉴를 장바구니에 추가하시겠습니까?\\n" +
                    "1. 확인        2. 취소");
            int confirm = sc.nextInt();
            if (confirm == 1) {
                product.increaseCount();//산다 하면 물품 개수만 올려준다 동일한 이름으로 생성 x
                boolean newMenu = true;
                for (Product p : cart) {
                    if(p.getId()==product.getId()){
                        newMenu = false;
                        break;
                    }
                }
                if(newMenu == true){
                    cart.add(product);
                }
                System.out.println(product.getName() + " 가 장바구니에 추가되었습니다.");
                return;
            }else if(confirm == 2){
                return;
            }
        }
    }

이렇게 모아서 넣었다

 

 

 

💡개선 : 코드 정리해서 모음

public static void run(){
        while(true) {//order반복
            int result = selectMenu();//주문하지 않으면 리턴되지 않는 while로 감싸인 함수임
            if (result == 1) {//주문했음

            } else if (result == 2) {//취소했음
                cart.clear();//static 메뉴선택 취소해서 장바구니 비워줌
                /*개수 카운트 비워줌*/
                for (Menu m : menus) {
                    for (Product p : m.products) {
                        p.setCount(0);
                    }
                }
            } else if (result == 3) {//총 판매목록
                double total = 0;
                System.out.println(
                        "[ 총 판매 목록 ]");
                for (Order o : orders) {
                    for (Product p : o.instanceMenus) {
                        //p.printDesc();
                        System.out.println(p.getName() + "     | W " + p.getPrice() +" | "+p.getCount()+ " | " + p.getDesc());
                        total = total + p.getPrice()*p.getCount();
                    }
                }
                System.out.println("[ Total ]\\nW " + total);

            } else if(result == 0){//나가기 눌렀음
                break;
            }
        }
    }
    public static int selectMenu() {
        int menu;
        while (true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("SHAKESHACK BURGER 에 오신걸 환영합니다.\\n" +
                    "아래 메뉴판을 보시고 메뉴를 골라 입력해주세요.\\n" +
                    "[ SHAKESHACK MENU ]\\n");

            int i = Menu.printIndex(menus);

            System.out.println("[ ORDER MENU ]\\n" +
                    i+". Order       | 장바구니를 확인 후 주문합니다.\\n" +
                    (i+1)+". Cancel      | 진행중인 주문을 취소합니다.\\n" +
                    (i+2)+". Exit      | 주문 앱에서 나갑니다."
            );
            menu = sc.nextInt();

            if ((0 < menu) && (menu <= menus.size())) {//메뉴 안에 있으면
                selectProduct(menu);
            } else if (menu == menus.size()+1) {//Order
                int order = order();
                if (order == 1) {//1이면 주문 2이면 걍 반복
                    return 1;
                }
            } else if (menu == (menus.size()+2)) {//Cancel
                int order = cancel();
                if (order == 1) {//1이면 주문취소 아니면 걍 반복
                    return 2;
                }
            }
            else if(menu == (menus.size()+3)){//나가기, while문 break;
                return 0;
            }else if(menu==0) {//총 판매 상품목록 출력
                return 3;
            }
        }
    }

이렇게 run→selectMenu→cancel→selectMenu→run으로 넘어가서 처리하던거 한쪽으로 모아넣음

public static int cancel() {
        while (true) {
            Scanner sc = new Scanner(System.in);

            System.out.println("주문을 취소 하시겠습니까?\\n" +
                    "1. 확인      2. 메뉴판");
            int x = sc.nextInt();
            if (x == 1) {//주문취소
                System.out.println("취소가 완료되었습니다!\\n\\n");
                //3초 기다려야됨
                cart.clear();//static 메뉴선택 취소해서 장바구니 비워줌
                /*개수 카운트 비워줌*/
                for (Menu m : menus) {
                    for (Product p : m.products) {
                        p.setCount(0);
                    }
                }
                return x;
            } else if (x == 2) {
                return x;
            }
        }
    }

 

 

💡개선 : 마찬가지로 얘도run→selectMenu→run까지 돌아와서 처리하던거 한쪽에다 모아넣음

public static void run(){
        while(true) {//order반복
            int result = selectMenu();//주문하지 않으면 리턴되지 않는 while로 감싸인 함수임
            if (result == 1) {//주문했음

            } else if (result == 2) {//취소했음

            } else if (result == 3) {//총 판매목록
                double total = 0;
                System.out.println(
                        "[ 총 판매 목록 ]");
                for (Order o : orders) {
                    for (Product p : o.instanceMenus) {
                        //p.printDesc();
                        System.out.println(p.getName() + "     | W " + p.getPrice() +" | "+p.getCount()+ " | " + p.getDesc());
                        total = total + p.getPrice()*p.getCount();
                    }
                }
                System.out.println("[ Total ]\\nW " + total);

            } else if(result == 0){//나가기 눌렀음
                break;
            }
        }
    }

public static int selectMenu() {
        ...코드 생략...
            }else if(menu==0) {//총 판매 상품목록 출력
                return 3;
            }
        }
    }

이러고 있었는데

public static int selectMenu() {
        ...코드 생략...
else if(menu==0) {//총 판매 상품목록 출력
                printAllProduct(); 
...코드 생략...

public static void printAllProduct(){

        double total = 0;
        System.out.println(
                "[ 총 판매 목록 ]");
        for (Order o : orders) {
            for (Product p : o.instanceMenus) {
                p.printDescTotal();
                //System.out.println(p.getName() + "     | W " + p.getPrice() +" | "+p.getCount()+ " | " + p.getDesc());
                total = total + p.getPrice()*p.getCount();
            }
        }
        System.out.println("[ Total ]\\nW " + total);

    }

이렇게 분리함

 

 

💡개선 : 그리고 껍데기만 남은 run()함수를 삭제함

public static void run(){
        while(true) {//order반복
            int result = selectMenu();//주문하지 않으면 리턴되지 않는 while로 감싸인 함수임
            if (result == 1) {//주문했음

            } else if (result == 2) {//취소했음

            } else if (result == 3) {//총 판매목록

            } else if(result == 0){//나가기 눌렀음
                break;
            }
        }
    }
    public static int selectMenu() {
        int menu;
        while (true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("SHAKESHACK BURGER 에 오신걸 환영합니다.\\n" +
                    "아래 메뉴판을 보시고 메뉴를 골라 입력해주세요.\\n" +
                    "[ SHAKESHACK MENU ]\\n");

            int i = Menu.printIndex(menus);

            System.out.println("[ ORDER MENU ]\\n" +
                    i+". Order       | 장바구니를 확인 후 주문합니다.\\n" +
                    (i+1)+". Cancel      | 진행중인 주문을 취소합니다.\\n" +
                    (i+2)+". Exit      | 주문 앱에서 나갑니다."
            );
            menu = sc.nextInt();

            if ((0 < menu) && (menu <= menus.size())) {//메뉴 안에 있으면
                selectProduct(menu);
            } else if (menu == menus.size()+1) {//Order
                int order = order();
                if (order == 1) {//1이면 주문 2이면 걍 반복
                    return 1;
                }
            } else if (menu == (menus.size()+2)) {//Cancel
                int order = cancel();
                if (order == 1) {//1이면 주문취소 아니면 걍 반복
                    return 2;
                }
            }
            else if(menu == (menus.size()+3)){//나가기, while문 break;
                return 0;
            }else if(menu==0) {//총 판매 상품목록 출력
                printAllProduct();
                return 3;
            }
        }
    }

다음과 같이 수정함

 

💡개선 :  order함수랑 cancel함수가 의미없이 int값 리턴하고 있는거 void로 수정함

public static void selectMenu() {
        int menu;
        while (true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("SHAKESHACK BURGER 에 오신걸 환영합니다.\\n" +
                    "아래 메뉴판을 보시고 메뉴를 골라 입력해주세요.\\n" +
                    "[ SHAKESHACK MENU ]\\n");

            int i = Menu.printIndex(menus);

            System.out.println("[ ORDER MENU ]\\n" +
                    i+". Order       | 장바구니를 확인 후 주문합니다.\\n" +
                    (i+1)+". Cancel      | 진행중인 주문을 취소합니다.\\n" +
                    (i+2)+". Exit      | 주문 앱에서 나갑니다."
            );
            menu = sc.nextInt();

            if ((0 < menu) && (menu <= menus.size())) {//메뉴 안에 있으면
                selectProduct(menu);
            } else if (menu == menus.size()+1) {//Order
                order();
            } else if (menu == (menus.size()+2)) {//Cancel
                cancel();
            }
            else if(menu == (menus.size()+3)){//나가기, while문 break;
                return;
            }else if(menu==0) {//총 판매 상품목록 출력
                printAllProduct();
            }
        }
    }

 

🚩문제 : Index가 범위 초과함

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 4, Size: 4 at java.util.ArrayList.rangeCheck(ArrayList.java:659) at java.util.ArrayList.get(ArrayList.java:435) at Product.createProduct(Product.java:50) at ManagerApp.createProduct(ManagerApp.java:45) at ManagerApp.run(ManagerApp.java:24) at Main.main(Main.java:54)

Process finished with exit code 1

tempP.setId(menuName+(menus.get(menus.size()).products.size()));

여기서 에러났다

menus.get(menus.size())이게 될리가…항상 마지막 index보다 size가 1이 클텐데

왜 저런 코드를 짜고 있었는지 전혀 기억이 안 난다

for (int i=0;i<menus.size();i++){
            if(menus.get(i).getName().equals(menuName)){
                tempP.setId(menuName+(menus.get(i).products.size()));
                menus.get(i).products.add(tempP);
                newMenus = false;//새 메뉴가 아님
                break;
            }
        }

위에서 내가 만들어둔 저 코드 무의식중에 저렇게 만들었나본데 뭔생각이었지

 

⛳해결 : 인덱스들 고침 어차피 새 메뉴면 1이겠지

//for문을 도는 동안 같은 메뉴이름인게 안 나왔으면 새 메뉴임
        if(newMenus){
            System.out.println("메뉴 설명을 입력해 주세요");
            Scanner sc = new Scanner(System.in);
            String menuDesc = sc.nextLine();
            Menu tempM = new Menu(menuName,menuDesc);
            tempP.setId(menuName+"1");
            tempM.products.add(tempP);
            menus.add(tempM);
        }

 

                tempP.setId(menuName+(menus.get(i).products.size()));
                ->
                tempP.setId(menuName+(menus.get(i).products.size()+1));

그리고 다시보니 id 위의것도 잘못되어서 바꿈

 

3

[ 상품 등록 ]

메뉴 이름을 입력해 주세요

Anti

상품 이름을 입력해 주세요

Fragile

상품 설명을 입력해 주세요

강하다

상품 가격을 입력해 주세요

6.9

메뉴 설명을 입력해 주세요

티티티티티

SHAKESHACK BURGER MANAGEMENT APP.

원하는 기능을 골라 입력해주세요.

  1. 대기주문 목록
  2. 완료주문 목록
  3. 상품 생성
  4. 상품 삭제
  5. 나가기 

5

SHAKESHACK BURGER 에 오신걸 환영합니다.

접속할 앱을 선택해 주세요.

주문

관리

앱 종료

1

SHAKESHACK BURGER 에 오신걸 환영합니다.

아래 메뉴판을 보시고 메뉴를 골라 입력해주세요.

[ SHAKESHACK MENU ]

  1. Burger | 앵거스 비프 통살을 다져만든 버거
  2. Frozen Custard | 매장에서 신선하게 만드는 아이스크림
  3. Drink | 매장에서 직접 만드는 음료
  4. Beer | 뉴욕 브루클린 브루어리에서 양조한 맥주
  5. Anti | 티티티티티

[ ORDER MENU ]
Order | 장바구니를 확인 후 주문합니다.
Cancel | 진행중인 주문을 취소합니다.
Exit | 주문 앱에서 나갑니다.

5.

[ Anti MENU ]
SHAKESHACK BURGER 에 오신걸 환영합니다.

아래 상품메뉴판을 보시고 상품을 골라 입력해주세요.

  1. Fragile | W 6.9 | 강하다

새 메뉴 등록도 잘 된다