오늘은 코드카타 SQL과 알고리즘 16번 문제를 풀고, 키오스크 프로젝트의 Lv.6과 Lv.7을 진행했다.
오늘 진행한 SQL 문제는 어제에 이어서 Null을 처리하는 내용이었다.
어제 정리했던 coalesce(A, B)를 사용하여 쉽게 해결할 수 있었다.
오늘 진행한 알고리즘 문제는 x만큼 간격이 있는 n개의 숫자, 즉 x의 배수 n개를 배열에 담는 내용이었다.
문제에 대한 접근 자체는 문제 없이 할 수 있었는데, 문제의 제한사항에서 x가 int 자료형의 범위를 벗어날 수 있다는 사실을 알아채지 못했다.
계속해서 x를 int 자료형으로만 다루니 테스트 케이스에서 int 자료형의 범위를 넘어가게 되는 경우를 만났을 때 처리를 할 수 없었다.
int를 long으로 바꾸면서 해결은 됐지만, 무엇이 문제인지 알 수 없어서 다른 사람들의 풀이를 참고해야만 했다.
앞으로는 문제를 꼼꼼하게 읽어봐야겠다...
각각의 문제와 풀이는 깃허브를 통해 업로드해두었다.
GitHub 보러가기
오늘은 키오스크 프로젝트의 도전과제, Lv.6를 트러블슈팅으로 마무리짓고, Lv.7을 시작했다.
먼저, 어제 마무리하지 못한 Lv.6의 이슈는 2가지가 있었다.
첫 번째는 MenuItem이 없는 Menu를 출력하려고 할 때 NullPointerException이 발생하며 프로세스가 종료된다는 점이다.
이전에 강의를 통해 배웠던 Optional을 사용해보려 했지만, 컬렉션에는 Optional을 사용하지 않는다고 한다.
컬렉션에 Optional을 붙이게 되면 객체에 접근할 때마다 Optional을 처리해야하기 때문에 복잡해지기 때문이다.
그래서 menuItems.isEmpty() ? Collections.emptyList() : this.menuItems;처럼 컬렉션이 비어있을 경우 emptyList를 반환하도록 지정한다.
그런데 사실 나에게 NullPointerException이 발생했던 이유는 Menu 클래스에서 컬렉션을 선언해두기만 하고, 생성해두지 않았기 때문이었다.
클래스를 생성할 때 컬렉션도 생성하는 것이 아니라, Menu에 MenuItem 객체를 담는 메서드를 실행할 때 컬렉션이 생성되도록 설정했기에
MenuItem 객체를 담아두지 않은 Menu는 NullPointerException으로 예외가 생기는 것이었다.
emptyList를 반환하게 하지 않아도 잘 작동이 되지만... 그래도 해둬서 안좋을건 없으니 그냥 해뒀다.
Lv.6의 두 번째 이슈는 double 자료형 여러개를 더할 때 0.000000003의 오차가 발생한다는 것이다.
이는 컴퓨터가 10진수를 2진수로 바꿀 때, 정확하게 바꾸지 못하기에 근사치로 바꾸게 되는데, 다시 2진수를 10진수로 바꿀 때 원래 입력한 값대로가 아니라 근사치로 바꾸기 때문이다.
사실 그냥 double을 출력하거나 2개의 double을 더할 때도 오차는 발생하지만, 그건 너무 작아서 반올림 되어서 출력되기에 나에게 안 보였던 것이다.
어쨌든 여기엔 2가지 해결 방법이 있는데, 첫 번째는 특정 자릿수에서 반올림하는 것이다.
그냥 UI로 출력하는 용도라면 이 방법을 써도 상관 없지만, 나는 실제로 결제하는 것은 아니지만... 결제에 사용하는 내용을 다루기에 이 방법은 사용하지 않기로 했다.
두 번째 방법은 오차 없는 소수끼리의 연산을 제공하는 BigDecimal 클래스를 사용하는 것이다.
BigDecimal 클래스는 String으로 숫자를 받아 처리하기 때문에 숫자를 정밀하게 저장하고, 표현할 수 있다.
new BigDecimal("0.001")과 같이 객체를 생성할 수 있다.
이때 BigDecimal끼리 연산할 때 기본 연산자를 사용할 수 없기에 BigDecimal.add(BigDecimal) 등의 메서드를 활용해서 연산을 진행할 수 있다.
기존에는 MenuItem의 가격을 double로 다뤘지만, 이를 BigDecimal로 바꾸면서 해결할 수 있었다.
이렇게 어제 끝내지 못한 트러블슈팅을 하며 Lv.6 키오스크 과제를 마무리할 수 있었다.
오늘 새롭게 시작한 Lv.7 키오스크 과제는 Enum을 활용해 사용자 유형별로 다른 할인율을 적용하고, 람다와 스트림을 활용해 장바구니 조회 기능을 구현하는 것을 요구한다.
오늘은 이 중 Enum을 활용한 할인율 적용과 스트림을 활용해 장바구니 조회 기능을 구현하는 부분을 완성했다.
내일 스트림을 활용해 장바구니에서 특정 메뉴를 제거하는 내용을 추가할 예정이다.
지난 계산기 과제에서 Enum을 만들어두고 제대로 활용하지 못했었는데,
계산기 해설 세션에서 Enum을 활용하는 방법을 제대로 알게 되었고, 이번 과제에서 활용할 수 있었다.
지난 과제의 코드들을 많이 참고해야 했지만... 그래도 Enum은 큰 어려움 없이 구현을 마무리할 수 있었다.
스트림을 사용해 menuItem을 출력하는 것 또한 큰 어려움 없이 해결할 수 있었다.
문제는 스트림으로 장바구니에서 특정 메뉴를 삭제하는 것인데... 이 부분은 아무리 해도 제대로 작동하지 않아서 내일 더 시도해봐야한다.
문제에서는 람다를 활용하라고 하는데, 어디에 어떻게 활용을 해야하는 것인지 감이 잘 안 잡힌다.
이 부분 또한 내일 더 고민해보고, 시도해봐야겠다.
내가 작성한 코드는 깃허브에 업로드해두었다.
GitHub 보러가기
확실히 도전과제가 되니 하루만에 한 단계를 마무리지을 수가 없어졌다...
그래도 필요한 내용들은 모두 구현을 했으니...
이제 정말 미루고 미뤄왔던 계산기 프로젝트의 트러블슈팅을 마무리지을 차례가 왔다...
이제 내일까지 과제를 진행하면 3주간의 프로그래밍 기초 주차가 마무리된다.
Java는 듣기만 해봤지 제대로 다뤄본 적이 없었는데, 이제 원하는대로 동작하게 만들 수 있는 수준이 되었다니 뿌듯하다.
아직 계속 검색해가며 해결해가야 하지만... 언젠간 혼자 해낼 수 있는 수준까지 되길 바란다.