오늘 처음으로 같은 그룹원들과 코드 리뷰를 진행했다.
아마도 코드스쿼드를 하면서 가장 크게 배워야할 점은 역시 내 코드를 소개하고 리뷰하는 습관인 것 같다.
노력해봐도 내 생각의 흐름이나 질문하는 것은 어렵다.
시간이 지나면서 늘기를 바라며 코드를 짤 때부터 흐름을 정리해보는 것도 해봐야겠다.
크게 리뷰하면서 얻은 꿀팁이나 새로 정리한 내용들을 적어보려고 한다.
git clone <url> .
git clone <url> <새로 만들 폴더명>
그룹원 중 쿠킴이 테스트 코드에 대한 지식을 공유해주셨다. 예전에 [스프링 부트와 AWS로 혼자 구현하는 웹 서비스]를 읽을 때 테스트 코드를 접하긴 했지만 여전히 print를 통해 확인하고 있었다. 그러다 테스트 코드로 검증하는 것이 좋아보여서 이번 기회부터 적극적으로 사용해보려고 한다.
책과 마찬가지로 junit을 사용해서 테스트를 진행하였고 이 때 커버리지라는 개념도 배웠다. 예전에 github repository에 action 등으로 자동으로 테스트를 해서 coverage를 띄워주는 걸 본적이 있는데 아마 유사한 개념같다. 테스트 관련해서도 책이나 검색을 통해서 좀 배워봐야겠다.
어제 미션을 구현하면서 가변 크기의 배열을 쓰기 위해서 Arraylist를 사용했다. 그런데 Arraylist에는 우리가 흔히 사용하는 boolean, integer와 같은 primitive type이 아닌 Boolean, Integer와 같은 reference type을 사용해야 한다.
급하게 arraylist를 쓰기 전에 검색했을 때는 NULL을 담을 수 있냐, 없냐가 가장 큰 차이라는 말을 많이 보았다. 그래서 찾아보기 전에 다음과 같이 추론했다.
정확한 이유를 알기 위해 찾아보았다.
자바 기본서인 [자바의 정석]에는 이렇게 나와있다.
대충 wrapper class란 기본형 데이터를 객체로 만들어 주기 위한 wrap인 것이다.
(이 과정을 Boxing이라 하고, 역은 Unboxing이다)
설명이 조금 부족해서 더 찾아보았다.
왜 우리는 Arraylist에서 wrapper class를 써야 하나요?
stackoverflow에 있는 이 글이 질문을 관통하는 글인 것 같다.
ArrayList는 제네릭을 통해 구현되어 있다. 당연하게도 ArrayList는 사용자에 따라 어떤 객체가 담길지가 달라지기 때문이다.
즉, ArrayList는 object class의 하위 클래스들을 담을 수 있도록 제네릭으로 구현되어 있다.
이 때, primitive type의 자료형은 객체가 아니기 때문에 당연히 사용할 수 없는 것이다.
(이 때문에 java가 완전한 객체지향이 아니라고 불린다고 한다.)
결국, integer와 Integer의 차이는 객체냐 아니냐, 이게 다인 것이다.
위에서 말한 NULL 문제도 아래 stackoverflow에 명쾌하게 설명되어있다.
예전에 C++ 공부할 때 공부한 포인터개념으로 이해하면 될 것 같다. 객체 자료형은 결국 포인터고, 결국 객체는 어떤 value를 가리키는 주소이다. NULL은 어떤 포인터가 어떤 메모리 주소도 참조하지 않은 상태이다. 그런데 기본 자료형은 그냥 값 자체이다. 그렇기 때문에 NULL이 아니라 그냥 기본 값을 가지고 초기화된다. 이해한 게 맞는지 모르겠지만 대충 감이 온다.
객체 자료형을 이용해야 할 때는 wrapper class를 사용해야 하는 불편함이 있지만, 일반적으로 자주 사용되는 자료구조이기 때문에 성능 저하를 막기 위해서!
2진수를 16진수로 변경하는 문제를 풀 때, 2진수는 작은 비트부터 왼쪽으로 만들어두어서 16진수로 변경해서 출력하려면 반대로 뒤집어야 했다. 파이썬에서는 문자열을 뒤집는게 쉬운 일이지만 java로 찾아보니 굉장히 귀찮아보였다. 그래서 그냥 insert로 특정 위치에만 계속 넣는 식으로 구현하려고 했더니 String 객체에서는 이를 지원하지 않았다.
그래서 찾은 것은 StringBuffer 클래스이다. 해당 클래스에서는 insert 함수를 지원한다.
그래서 특정 index에 문자열을 삽입할 수 있었다. String이든 char든 obj의 값이든 모두 가능하게 되어있다.
python이라면 string[::-1] 로 해결되겠지만 ... java에선 어떻게 해야 할까?
역시나 StringBuffer의 도움을 받으면 된다. 필요하면 다시 toString으로 변환하면 되니까!
오늘도 꽤나 많은 것을 배웠다. 이런 식으로 사소한 것 하나도 계속 조사해보면서 기록해둬야겠다.
대충 아는 내용이라고 넘어가지 말기!