(24.11.22 작성)
[Lv1,2]
1. branch 커밋 실수
• 본래 의도: 각 레벨마다 브렌치를 따로 만들어 사용하기.
• 문제 발생:
1) kioskLv2 branch에 Lv1 디렉토리가 같이 push되어 섞임
(이유를 모르겠다.. git pull해서 그런가..? 아님 원래 이런가..? add도 '.' 안 쓰고 파일명 하나씩 지정해서 했는데..)
2) 브렌치 바꾸는걸 까먹는 바람에 Lv1 파일을 kioskLv2 branch에 잘못 push함
• 해결 시도:
만약 잘못 푸쉬했다는 사실을 빨리 발견했더라면 git reset HEAD~1 명령어를 시도해보기라도 했을텐데, 내 실수를 뒤늦게 알아차리는 바람에 이 방법을 시도할 수 없었다.
잘못된 커밋을 되돌려 보려고 git log를 건드렸다가 커밋 메시지가 서로 섞여버리기도 했고,
stale info 오류, fatal: 'kioskLv2' does not appear to be a git repository 오류 등 평생 만날 오류라는 오류는 다 접한 것 같다. (거의 '오류 박물관🏛️' )
• 차선책:
그래서 어차피 kioskLv2 branch에 Lv1 파일의 커밋까지 다 섞여버렸으니, 기왕 이렇게 된거 kioskLv2의 branch 이름을 kioskDev로 바꾸고 모든 파일(Lv1~Lv5)파일을 싹 다 kioskDev branch에 올려버리기로 계획을 전면 수정 했다.
이러면 적어도 브렌치명 헷갈려서 잘못 푸쉬하는 실수는 막을 수 있다.
2. 커밋 메세지 입력 실수
• 본래 의도:
전에 다른 분이 콘솔창을 안 쓰고 인텔리제이에서 제공하고 있는 커밋 창에서 파일을 커밋하는 것을 보고, 나도 한 번 시도해보고싶어서 인텔리제이 자체 커밋 기능을 써봤다.
• 문제 발생:
평소 하던것 처럼 🔨 이모티콘을 붙여주려고 :hammer:이렇게 적어서 커밋 버튼을 눌렀는데,
github에서 확인해보니 이모지는 안 나오고 :hammer: 문자열만 찍혀있었다...
'gitmoji' 플러그 인을 다운 받았어야했는데...
콘솔창에도 그냥 썼기에, 따로 플러그인을 다운 받지 않아도 사용 가능할 줄 알았다.
• 해결 시도:
나홀로 눈에띄는 커밋 메세지를 가만 놔둘 수 없었다.
git commit --amend 명령어를 사용해서 커밋 메세지를 수정하고 다시 push했다.
콘솔창에서 수정하는거니 gitmoji도 다시 정상적으로 반영이 될 줄 알았는데 여전히 이모지는 나오지 않고 :hammer: 문자열이 남아있었다.
• 차선책:
할 일이 많은데 이모지 하나에 시간을 더 쓸 수가 없어서, 메시지 수정은 포기하고
이후 사고를 방지하기 위해 바로 gitmoji 플러그인을 다운 받았다.
(24.11.25 작성)
[Lv2, 3]
1. 가독성 문제
초반에는 MenuItem을 저장하는 필드 List를 선언하고, .add를 사용해 MenuItem을 저장했다.
후에 지현님이 List.of()로 List를 초기화하는 방법을 알려주셨는데, .add()로 범벅된 것보다 깔끔해보였다.
다만 단점이 List 사이즈가 고정된다는 것인데, 일단은 메뉴를 더 입력 받을 일이 없기 때문에 괜찮은 방법이라 판단했다.
MenuItem을 저장하는 필드 List 에 .add()대신 List.of()를 적용하였다.
List<MenuItem> menuItems= List.of(
new MenuItem("ShackBurger", 6.9, "토마토, 양상추, 쉑소스가 토핑된 치즈버거"),
new MenuItem("SmokeShack", 8.9, "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거"),
new MenuItem("Cheeseburger", 6.9, "포테이토 번과 비프패티, 치즈가 토핑된 치즈버거"),
new MenuItem("Hamburger", 5.4, "비프패티를 기반으로 야채가 들어간 기본버거")
);
2. 요구사항 이해의 어려움
Lv3에는 다음과 같은 요구사항이 있다.
- List<MenuItem> menuItems 는 Kiosk 클래스 생성자를 통해 값을 할당합니다.
⇨ Kiosk 객체를 생성하고 사용하는 main 함수에서 객체를 생성할 때 값을 넘겨줍니다.
저 요구사항이 무슨 의도를 가지고 있는지 도무지 이해가 가지 않았다.
이미 Kiosk 클래스에 List<MenuItem> menuItems 필드를 만들고 List.of()로 메뉴들까지 싹 다 넣어놨는데,
생성자로 또 무엇을 넘기라는 것일까..?
튜터님께 도움을 청하러 가는 도중 다른 동료분을 만나 의문을 해결할 수 있었다.
문제의 요구사항을 이해할 수 없었던 이유는 내가 Kiosk Class의 필드 menuItems에 메뉴들을 다 적어두었기 때문이다.
List<MenuItem> menuItems= List.of(
new MenuItem("ShackBurger", 6.9, "토마토, 양상추, 쉑소스가 토핑된 치즈버거"),
new MenuItem("SmokeShack", 8.9, "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거"),
new MenuItem("Cheeseburger", 6.9, "포테이토 번과 비프패티, 치즈가 토핑된 치즈버거"),
new MenuItem("Hamburger", 5.4, "비프패티를 기반으로 야채가 들어간 기본버거")
);
• 해결:
문제의 의도는 '기능분리'이다. Kiosk는 프로그램을 실행하는 역할만 담당하면 된다.
메뉴 정보 관리는 Main에서 수행하면 된다(일단 Lv3는 그렇다).
그래서 모든 메뉴 정보를 담은 List인 menuItems는 Main Class에 두고,
Kiosk Class의 생성자를 오버로딩해서 List를 Main Class로부터 할당 받도록 수정했다.
public class Kiosk {
private List<MenuItem> menuItems; //menuItem을 관리하는 필드
/*생성자*/
public Kiosk(List<MenuItem> menuItems){ //Main으로 부터 menuItems를 할당 받는 생성자
this.menuItems=menuItems;
}
}
public class Main {
public static void main(String[] args) {
List<MenuItem> menuItems= List.of( //MenuItem을 관리하는 list
new MenuItem("ShackBurger", 6.9, "토마토, 양상추, 쉑소스가 토핑된 치즈버거"),
new MenuItem("SmokeShack", 8.9, "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거"),
new MenuItem("Cheeseburger", 6.9, "포테이토 번과 비프패티, 치즈가 토핑된 치즈버거"),
new MenuItem("Hamburger", 5.4, "비프패티를 기반으로 야채가 들어간 기본버거")
);
Kiosk kiosk=new Kiosk(menuItems); //kiosk에 menuItems 할당함
}
}
3. Index 활용 실수
List에 있는 메뉴를 출력하기 위해 for문을 아래와 같이 작성했었다.
for (int i = 0; i < menuList.size(); i++) { //list에 있는 메뉴 출력
System.out.println(i + ". " + menuList.get(i).foodName + " | W "
+ menuList.get(i).prize + " | " + menuList.get(i).description);
}
메뉴 번호로 index 번호를 그대로 가져다 사용하는 바람에 메뉴가 0번 부터 출력되는 상황이 벌어졌다.
또, 사용자가 입력한 숫자를 index로 활용하려면 '입력된 숫자-1'로 사용해야하는데 입력된 숫자 자체를 index로 활용해버렸다... 그래서 만약 사용자가 Hamburger을 고르겠다고 4를 입력하는 순간 'ArrayIndexOutOfBoundsException'이라는 런타임에러가 빵!하고 터져버린다. (list.size()==4였음)
• 해결:
코드는 다음과 같이 수정하였다.
(24.11.26 작성 / 24.11.28 수정)
[Lv4]
1. Menu Class활용 문제
Lv4에서 내가 객체지향에 대한 이해가 충분하지 않다는 것을 많이 느꼈다.
도전과제까지 통틀어서 제일 어려웠던 부분이다.
• 문제 상황:
Lv4의 요구사항은 아래 사진에 쓰여있는 것과 같이 Menu클래스를 생성해서 카테고리를 만들고 MenuItem객체들을 관리하는 것이다.
'Menu가 MenuItem을 포함한다고..?' 라는 생각으로 처음에 Menu List를 만들어서 그 안에 카테고리 List를 집어 넣고, 또 그 안에 MenuItem List를 넣겠다는!! 생각을 했었다.
그리고 잠깐이지만 시도도 했었다.
하지만 저렇게 만들면 일단 각 음식 종류별로 카테고리 이름을 지어주기도 어려울 뿐만 아니라, 메뉴 하나를 수정하거나 새로운 카테고리가 추가될 경우 Menu 뿐만 아니라 Kiosk 클래스, Main 클래스도 건드려야할 것 같았다.
Menu 클래스에 모든 정보를 욱여 넣으려던 내 방식이 OCP에 위배된다는 것은 알게되었다.
• 해결:
다행히 한 동료분의 도움으로 '가변 인수'라는 아이디어를 얻게 되었다.
그래서 다음과 같이 적용해 보았다.
Menu에는 카테고리 이름과 음식 메뉴들을 담을 수 있는 List 타입의 menuItems를 필드로 생성한다.
그리고 생성자를 오버로딩해서 생성자로 Menu 객체를 생성함과 동시에 카테고리 이름을 지정할 수 있게 해준다.
또한 addItems 메서드를 사용하여 menuItem 객체들을 menuItems에 저장한다.
이때 addItems 메서드는 가변 인수를 사용한다, menuItem 객체들을 개수에 관계 없이 받을 수 있다.
새로 메뉴가 추가되더라도 Main에서만 반영해주면 된다.
이를 Main Class에서 활용한 예는 다음과 같다.
생성자를 통해 만들어진 Menu 객체들도 이제 한데 모아서 관리해야한다.
Menu 객체들은 Kiosk 클래스에서 List 타입의 menus 필드를 만들어 저장했다.
이때도 가변 인수를 활용했다. 새로운 카테고리가 아무리 많이 만들어져도 역시 Main에서만 수정해주면 된다.
가변인수를 사용할 때는 가변인수로 넘겨지는 값들이 배열로 처리된다는것에 유의하고 사용해야한다.
2. '음식 메뉴 선택' 단계에서 입력된 숫자와 맞지 않는 음식 메뉴가 출력됨.
• 문제 상황(1차):
Kiosk Class의 '음식 메뉴 선택' 단계에서, 입력한 숫자와 맞지 않는 음식 메뉴가 출력되는 버그가 발생했다.
위 사진에서 두 가지 문제점을 발견할 수 있다.
① 5를 입력했는데 엉뚱한 2번 메뉴가 출력된다.
② 5는 유효한 숫자가 아닌데 에러 메세지가 출력되지 않는다.
②번 오류는 좀 뒤에 다루고 지금은 ①번 해결과정 먼저 풀어내보겠다.
수정 전 코드는 다음과 같다.
빨간 박스로 표시해두었지만 설명하자면, 카테고리 출력을 위해 입력받은 번호가 음식 메뉴 선택에도 영향을 주고 있다.
파란 박스 부분에서 음식 메뉴 번호를 입력받도록 되어있으나, 그 다음줄에 있는 선택된 음식을 출력해주는 if문 안에서 파란박스에서 입력받은 번호를 전혀 사용하지 않고있다.
• 해결(1차):
따라서 MenuItem menuItem 과 command 두 코드의 순서를 바꿔줌으로서, MenuItem menuItem가 index로 파란 박스 안에 있는 command의 값을 받아 사용하도록 수정하였다.
결과도 잘 나오는 것을 확인할 수 있다.
• 문제 상황(2차):
하지만 아직 해결되지 않은 문제가 남아있다.
만약 command에 0이 입력된다면?.. 'IndexOutOfBoundsException'에러가 터진다..🥲
(런타임에러 나쁜 에러..)
원인은 간단하다.
command에 0이 입력될 경우 menuItemsList는 index로 -1을 입력 받게 된다.
• 해결(2차):
MenuItem menuItem을 아예 if문 내부로 넣어버렸다.
덕분에 command가 0인 상황은 피할 수 있게 되었다.
이제 0을 넣어도 문제없이 잘 작동한다.