TIL - 이전 코드 수정하기

su·2023년 5월 31일
0

TIL

목록 보기
12/93
post-thumbnail

문제 1 - 상품의 Detail을 추가해보자 !

1) 문제

나는 카페의 키오스크를 만들고 있다.
처음에 구현했을 때는 음료의 사이즈에 상관없이 그냥 하나의 사이즈로만 설정해두었는데
실제 카페를 가면, small regular 사이즈로 나뉘어있는 경우가 대부분이라 이를 구현하고 싶었다.
요구사항에서는 일단 일반 메뉴로 주문을 받고, 그 안에서 사이즈를 한 번 더 물어보는 형태이다.
그 요구사항대로 작성해보려고 한다 !

2) 시도

현재 내가 작성한 리스트의 형태이다. (정렬을 위해서 슬프지만 메뉴명은 영어이다.)

List<Goods> goodsListCoffee = Arrays.asList(
	new Goods("1." , "Americano", 5.0, "에스프레소와 물의 컴비네이션"),
    new Goods("2.", "Cafe Latte", 5.8, "에스프레소와 우유의 컴비네이션"),
    new Goods("3.", "Hazelnut Americano", 5.5, "에스프레소와 물과 헤이즐넛 파우더의 컴비네이션"),
    new Goods("4.", "Vanilla Latte", 6.3, "에스프레소와 프렌치 디럭스 바닐라파우더, 저지방 우유"),
    new Goods("5.", "Cafe Sua", 6.9, "깊고 진한 더블 에스프레소와 달콤한 연유의 만남")
);

어떻게 해볼까 .. 고민해보았다.
Goods 라는 인스턴스는 내가 Goods 클래스를 따로 생성해서 그 안에
String 타입의 번호, 메뉴명, 메뉴설명과 Double 타입의 메뉴 가격이 필드로 지정되어 있다.

그렇다면 Goods 안에 메뉴명2, 메뉴가격2 를 추가해주면 되지 않을까 ? 하는 생각에 Goods 클래스를 수정하게 되었다.

public class Goods {
	private double price;
    private double price2; // 추가
    private String name;
    private String name2; // 추가
    
    public double getPrice2() {
    	this.price2 = price + 0.5; // 500원씩 추가해준다
    }
    
    public String getName2 () {
    	this.name2 = this.name + "(Regular)";
    	return this.name2;
    }
}

이렇게 두 개의 필드와 두 개의 메소드를 추가해보았다 ! (name과 price는 기존에 있던 필드)

그렇다면 이제 메뉴를 구매할 때의 코드를 수정해주면 된다 !

// 위에서 고객이 1. small을 눌렀을 경우, 2. regular를 눌렀을 경우
System.out.println("\n위 메뉴의 어떤 옵션으로 추가하시겠습니까?");
System.out.printf("%-2s %-15s %-2s %-15s\n", "1.", 
                  "Small(W " + goods.getPrice() + ")", 
                  "2.", "Regular(W " + (goods.getPrice()+0.5) +")");
String s = sc.nextLine();
// 여기서 조건문으로 구분해보자 !
if ("1.Small".contaions(s)) {
	// 원래 입력받았던 그 상품을 그대로 출력해준다.
    System.out.printf("%-25s %s %5s %s %s", 
                      "\""+goods.getName(), "|", "W " +goods.getPrice(), 
                      "|", goods.getDetail()+"\"");
} else {
   // 원래 입력받았던 상품의 Regular 버전을 출력해준다.
   System.out.printf("%-25s %s %5s %s %s", 
                      "\""+goods.getName2(), "|", "W " +goods.getPrice2(), 
                      "|", goods.getDetail()+"\"");
}

출력하는 부분에서 변화를 주었다.
그리고 정말 추가할 것이냐는 문장을 한 번 더 출력해준다. (기존의 코드이다)

System.out.println("\n위 메뉴를 장바구니에 추가하시겠습니까?");
System.out.printf("%-2s %-7s %-2s %-7s\n", "1.", "확인", "2.", "취소");

String call = sc.nextLine();

그 후에 장바구니에 아이템을 넣어준다고 생각해서

System.out.println(newGood.getName() + " 가 장바구니에 추가되었습니다.");
order.addOrderList(newGood); // 장바구니 객체에 담을 메소드 호출

원래 작성했던 코드 그대로 놔두었다.

난 원하는 대로 잘 구현하고 있다고 생각했다.
여기까지는 상관없었는데, 문제가 생겼다. 장바구니 내용을 출력해줄 때이다.

<발생한 문제점>

  • 1) Small 사이즈, Regular 사이즈 별로 상품 개수를 따로 설정해주지 않았다.
    • 그럼 출력할 때 오류가 생긴다. 너가 그래서 Small을 얼마나 주문했고, Regular를 얼마나 주문했는데 ..? 이 상태가 되어버리는 것이다.
  • 2) 총합 계산이 안된다.
    • 마찬가지로 Small과 Regular를 하나의 인스턴스 안에 넣어버려서, 총합 필드가 따로 따로 계산되지 않아 출력할 때 문제가 생긴다.

결국 장바구니에 담긴 내용을 출력할 때의 오류가 발생해버린 것이다..
사실 작성하지 않았던 필드들을 추가해서 해보면 될 것 같은데, 그렇게 되면 다른 메소드 안에서 조건문을 너무 많이 추가해주어야 할 것 같아서 다른 방법을 생각하게 되었다.

3) 해결

리스트를 수정하는 것이다. 원래 리스트에서 Regular 버전들을 더 추가해준다.

List<Goods> goodsListCoffee = Arrays.asList(
	new Goods("1." , "Americano", 5.0, "에스프레소와 물의 컴비네이션"),
    new Goods("2.", "Cafe Latte", 5.8, "에스프레소와 우유의 컴비네이션"),
    new Goods("3.", "Hazelnut Americano", 5.5, "에스프레소와 물과 헤이즐넛 파우더의 컴비네이션"),
    new Goods("4.", "Vanilla Latte", 6.3, "에스프레소와 프렌치 디럭스 바닐라파우더, 저지방 우유"),
    new Goods("5.", "Cafe Sua", 6.9, "깊고 진한 더블 에스프레소와 달콤한 연유의 만남"),
    new Goods("1." , "Americano(Regular)", 5.5, "에스프레소와 물의 컴비네이션"),
    new Goods("2.", "Cafe Latte(Regular)", 6.3, "에스프레소와 우유의 컴비네이션"),
    new Goods("3.", "Hazelnut Americano(Regular)", 6.0, "에스프레소와 물과 헤이즐넛 파우더의 컴비네이션"),
    new Goods("4.", "Vanilla Latte(Regular)", 6.8, "에스프레소와 프렌치 디럭스 바닐라파우더, 저지방 우유"),
    new Goods("5.", "Cafe Sua(Regular)", 7.4, "깊고 진한 더블 에스프레소와 달콤한 연유의 만남")
);

앞의 번호를 수정하지 않은 이유는 어차피 저 부분은 출력되지 않게 할 것이기 때문이다.

그리고 메뉴를 출력해주는 부분의 코드를

for (int i=0; i<(detaillist.size()/2); i++) {
	System.out.printf("%-2s %-23s %1s %5s %1s %s\n",
                      detaillist.get(i).getNum(), detaillist.get(i).getName(), "|",
                      "W "+detaillist.get(i).getPrice(), "|", detaillist.get(i).getDetail());
}

이렇게, 리스트 사이즈의 절반까지만 출력하도록 바꾸었다 !
뒤에 추가한 Regular 메뉴는 상세 메뉴판 안에서는 볼 수 없도록 수정했다.

그리고 구매 화면을 다시 작성해보았다.

System.out.println("\n위 메뉴의 어떤 옵션으로 추가하시겠습니까?");
System.out.printf("%-2s %-15s %-2s %-15s\n",
                  "1.", "Small(W " + goods.getPrice() + ")",
                  "2.", "Regular(W " + (goods.getPrice()+0.5) +")");
String s = sc.nextLine();
Goods newGood;

구매할 것이냐고 먼저 물어보기 전에, 상품의 옵션을 선택할 수 있도록 코드를 추가하였다.
Regular 메뉴의 가격은 기존의 가격 + 0.5 을 출력해주었다.
그리고 새로운 Goods 타입의 인스턴스를 담을 변수명을 만들어준다.

if (s.contains("Small") || s.contains("1") || s.contains("small")) {
	System.out.printf("%-25s %s %5s %s %s", "\""+goods.getName(), "|",
                      "W " +goods.getPrice(), "|", goods.getDetail()+"\"");
                      // 입력받은 상품 그대로 출력하기
} else if ((s.contains("Regular") || s.contains("2") || s.contains("regular"))) {
	for (Goods item: list) {
    	if (item.getName().equals(goods.getName()+"(Regular)")) {
        	newGood = item;
        }
    }
	System.out.printf("%-25s %s %5s %s %s", "\""+newGood.getName(), "|", 
                      "W " +newGood.getPrice(), "|", newGood.getDetail()+"\"");
}

코드가 좀 복잡해 보이지만 사실 그렇지 않다.
일단 가장 바깥쪽의 if~elseif 조건문은 위에서 1.Small을 선택했는지, 2.Regular를 선택했는지 구분하는 조건문이다.
그리고 if문의 조건인 1.Small 조건을 만족한다면, 기존에 선택했던 메뉴 그대로 출력해준다.
if문을 만족하지 못하고, 즉 2.Regular 를 선택했다면 받아온 list의 반복문을 돌리게 되는데,
그 리스트 안에서 goods.Name()에 "(Regular)"이 붙은 새로운 item을 찾으면!
그 아이템을 위에 선언해두었던 newGood에 넣어주면 된다.
출력은 goods가 아닌 newGood로 진행하면 된다 !

마찬가지로 장바구니에 넣을 때도

System.out.println("\n위 메뉴를 장바구니에 추가하시겠습니까?");
System.out.printf("%-2s %-7s %-2s %-7s\n", "1.", "확인", "2.", "취소");

String call = sc.nextLine();
if (newGood != null) { 
	System.out.println(newGood.getName() + " 가 장바구니에 추가되었습니다.");
    order.addOrderList(newGood); // 장바구니 객체에 담을 메소드 호출
} else {
	System.out.println(goods.getName() + " 가 장바구니에 추가되었습니다.");
	order.addOrderList(goods); // 장바구니 객체에 담을 메소드 호출
}

위에서 선언해둔 newGoods 값이 null이 아니라면, 즉 값이 담겼다면 newGood를 추가해주고
newGoods 값이 null 이라면, 기존에 받았던 goods를 추가해주면 된다.

4) 배운 점

원하는 바를 차근차근 생각하면 해결이 가능한 것 같다.
부족한 실력이라 코드가 많이 지저분한데, 다시 읽어보면서 간략히 쓸 수 있는 부분은 바꿔봐야겠다.
지금은 메뉴 리스트에 메뉴를 추가하는 방법으로 대체했지만,
원래 하려던 방법에 분명 답이 있을 것 같아서, 그 방법으로도 코드를 다시 작성해보는 게 좋을 것 같다.
생성해둔 클래스로 객체를 만들어 사용하는 방법에 조금 더 익숙해진 것 같다!
필요하다면 클래스 내부에 원하는 필드나 메소드를 추가해서 사용하는 방법을 알게 된 것 같다.

문제 2 - 장바구니에 무조건 메뉴명을 입력해야만 저장가능한가? 번호로도 저장하게 하고 싶다 !

1) 문제

사실 상세 메뉴판 뿐만 아니라 입력받고 판단해서 넘기는 모든 부분에서 공통적으로 생각하고 있는 부분이긴 하다.
이렇게 입력해도, 저렇게 입력해도 다 맞다고 해주고 싶어서
조건문이 매우 지저분하고 길어지게 되었는데, 이를 조금 해결해보고 싶었다.

2) 시도

원래 코드이다

// Goods 타입의 세부메뉴 변수를 null값으로 초기화한다.
Goods detailGoods = null;
// 메뉴명을 입력받는다.
String s = sc.nextLine();
// 입력받은 메뉴명을 판단한다.
for (Goods item: detailList) {
	if (s.equals(item.getName())) {
    	detailGoods = item;
    }
}

이렇게 조건문을 작성하게 되면, 사용자가 메뉴의 번호로 입력했을 경우에는 인식하지 못한다.
그렇다면 조건문에 조건을 또 추가해주어야 하나 ..?

// if문만 수정해보자 !
if (s.equals(item.getName()) || s.equals(item.getNum())) {
	detailGoods = item;
}

이렇게 되면 ,, 1 이 아니라 1. 까지 입력해주어야 올바르게 판단할 것이다.

3) 해결

방법을 다시 생각해보았다.
원래 갖고있던 getNum()과 getName()을 하나의 String으로 받고 그걸 입력받은 문자열과 비교하면?

if ( (item.getNum()+item.getName()).contaions(s) ) {
	detailGoods = item;
}

새로운 메소드를 사용하게 되었다!
문자열에 해당 문자열이 포함되어 있는지를 판단해주는 .contaions가 있었다.
이걸 사용할 생각을 왜 못했을까!!
일치 여부만 판단하느라, 각각의 일치 여부에 맞는 조건을 계속 추가해주고 있었는데 ..
이렇게 조건문을 작성하면 된다 !

4) 배운 점

하나의 관점으로만 생각하면 안될 것 같다.
입력받은 문자열이 내가 갖고있는 문자열과 일치해야해 !! 라고만 생각해서
.equals와 Objects.equals()만 계속 사용하려고 했었고,
그러다 보니 일치하는 경우에 맞는 조건들이 늘어나야만 내가 원하는 대로 코드구현이 가능했다.

다르게 생각해서 일치 여부가 아닌 포함 여부로 작성했더니 조건이 하나로 줄어들어 코드 읽기가 훨씬 편해졌다. 다른 코드들도 하나씩 수정해봐야겠다 !

지난번에 배운 내용 사용 - nextInt(), nextLine()

1) 문제

nextInt() 하고 나서 다시 다른 메소드로 넘어간 다음에
거기서 또 입력을 받아야 하는 형식의 코드를 만들었다.
넘어간 다른 메소드에서도 입력을 받게 되는데, 입력을 받은 문자열을 판별해주는 조건문이 있다.
만약 리스트에 없는 문자열을 입력하면

잘못된 메뉴를 입력했습니다. 다시 입력해주세요.

라는 문장이 출력되는데, 나는 숫자만 입력받고 엔터를 눌러서 넘어갔는데 ?
저 문장이 출력되는 것을 확인했다.
저는 아직 .. 문자열을 입력하지 않았는데요 ..?

2) 해결

그러다가 지난 과제에서 비슷하게 겪었던 문제가 떠올랐다.
그때는 아마 next()를 사용하고 다시 다른 nextLine() 등으로 입력받아야 하는 상황이었는데, 입력이 제대로 받아지지 않았었다.
Scanner의 next()나 nextInt() nextFloat() 등은 스페이스 단위로 입력을 받아서,
그 다음에 엔터를 누르면, 그 다음에 입력받는 메소드에 엔터가 입력이 되는 듯 하였다.
따라서 nextInt()를 하고 nextLine()을 밑에 적어주고 다른 메소드로 넘어가도록 코드를 수정했다.
그랬더니 멀끔하게 동작하는 것을 확인할 수 있었다.
배웠던 내용을 다시 확인하고, 까먹지 않고 응용할 수 있어 뿌듯했다 !

오늘 생긴 코드 작성하다 재밌는 일 - 아님


원하는 기능을 추가로 구현하고자, 코드를 수정중이었고 작성을 완료하고 보니
오른쪽에 저런 아름다운 ... 오류들이 생겼다.
진짜 멘붕이 왔다.
왜냐하면 코드를 수정하기 전까지는 저런 오류들이 하나도 없었고,
원하는 대로 작동도 잘 되고 있었기 때문이다.
순식간에 심각해져서 위에서부터 코드를 쭉 읽어보기도 했고, 다시 써야되나 ..? 싶은 찰나에


오류 부분에 '}' 가 빠져있다는 ,, 친절한 설명을 발견했다.

결국 괄호를 닫지 않아서 이런 .. 심각한 사태가 발생하고 만 것이었다.
사실 표현은 이렇게 했지만 정말 눈물이 날 것만 같았다 ..
그렇게 열심히 작성했고, 1초 전까지만 해도 말짱하게 작동되던 코드가
어째서 나에게 이런 시련을 가져다주나 ... 싶었는데, 코드를 수정하는 과정에서 그만 괄호 닫는 부분을 깜빡해버린 것이다 ..
참으로 ... 바보같은 실수가 아닐 수 없고, 짧은 찰나에 수만가지 생각이 지나갔다.
앞으로 이런 ... 실수에는 .. 당황하지 않고 침착하고 강인해질 수 있는 사람이 되도록 하자 .. (쫄지마!)

profile
(❁´◡`❁)

0개의 댓글