코드 피드백 / 컨벤션
커밋 메세지 의미있게 작성하기
해당 커밋에서 어떤 작업이 수행되었는 지를 이해할 수 있도록 커밋 메세지를 의미있게 작성하자
이름을 통해 의도를 드러내자
좋은 이름 짓기는 그 코드를 다시 볼 미래의 나와 동료 개발자간의 소통 활동 중 하나이다. 클래스와 메서드, 변수 이름을 시간을 들여 신중하게 짓고, 역할과 책임, 동작에 대해 명확히 의도를 드러내기 위해 노력하자.
같은 맥락으로 의도를 드러낼 수 있다면 이름이 길어지더라도 괜찮다. 이름을 축약하면 당장의 코드는 짧아져도 코드 이해하기는 더 어려워진다. 이름은 축약을 하더라도 의도와 의미가 드러나는 경우에만 축약하자.
공백도 신경쓰자
공백 라인을 의미있게 사용하여 문맥을 분리하는데 사용하면 가독성이 좋아질 수 있다.
공백에 대한 컨벤션도 잘 지키도록 하자. space와 tab을 혼용하지 않으며, if와 for, while 문 사이의 공백도 컨벤션으로 통일하자.
의미 없는 주석을 달지 말자
의도는 변수 이름, 메서드명, 클래스 이름을 통해 드러내고, 그를 통해 의도가 명확히 들어난다면 굳이 주석을 달 필요 없다. 이를 통해서 의도를 드러내기가 힘든 경우에만 주석을 다는 것이 좋다.
라이브러리와 API를 적극 활용하자
메서드나 클래스를 구현하기 전에 Java API에서 해당 기능을 제공하는지 검색해보자. 제공하지 않는 경우에는 직접 구현하고, 제공한다면 API를 잘 사용하자. 이는 Collection도 마찬가지이다.
Git 관련
.class나 .idea 파일과 같이 자동 생성되는 리소스는 git이나 형상관리툴에 올리지말자.
README.md는 상세히 작성하자. 해당 프로젝트의 얼굴과도 같기 때문에 어떤 프로젝트이고 어떤 기능을 담고 있는지 잘 나타내는 것이 좋다. 또 프로젝트를 진행하며 꾸준하게 추가되거나 삭제된 기능을 업데이트 하자. 때문에 너무 세세한 부분까지 정리하게 되면 수정해야하는 부분이 많아지니 기능을 구현하면서 큰 틀 위주로 정리하는 것이 좋다.
하드 코딩 금지
문자열이나 숫자(매직넘버)와 같은 값을 하드 코딩으로 코드 중간에 박아넣지 말자. static final로 상수로 만들고 변수명에 해당 변수의 역할과 의도를 드러내자.
구현 순서도 신경쓰자
클래스는 상수(static final), 멤버 변수, 생성자, 메서드 순으로 작성하자.
변수 이름에 자료형 사용하지 않기
List<String> nameList와 같이 변수 이름에 해당 자료형 혹은 자료구조를 사용하지 말자.
하나의 메서드가 한 가지 기능만 담당하게 하기
함수나 메서드가 길어진다면 해당 메서드에서 너무 많은 일을 처리하려고 할 가능성이 높다. 각 부분을 기능별로 나누어 적절하게 다른 메서드로 분리하자.
이를 통해 메서드 하나에 15라인 언저리로 유지하도록 의식하고 작성하자. 15라인을 넘는다면 함수 분리를 고민해보자. 이는 main 함수도 포함되고, 공백도 15라인에 포함된다.
테스트 작성하기
테스트는 해당 코드를 작성한 개발자의 의도를 드러내기 아주 좋은 수단이다. 뿐만 아니라 회귀 버그도 예방 가능하며, 테스트를 작성하며 스스로의 코드를 리뷰 해볼 수 있는 기회이다.
테스트는 작은 단위부터
테스트는 가급적 작은 단위의 테스트부터 시작하고, 필요하다면 점차 큰 단위의 테스트를 만들자. 가장 좋은 테스트는 순수 Java로 이루어진 테스트이며, 특정 기능에 대해 테스트 코드를 짜기 어렵다면 코드를 잘 못 작성했을 가능성이 높다.
실패 케이스도 테스트하자
테스트는 항상 성공 케이스 뿐만 아니라 예외와 실패 케이스에 대해서도 테스트를 작성해야한다. 특히 경계값에 대해서는 오류가 자주 발생하기 때문에 꼼꼼하게 테스트를 작성하자.
테스트 코드도 리팩토링하자
테스트 코드도 반복되는 로직이나 개선할 점이 있다면 리팩토링을 통해 개선하자.
테스트 코드는 구현과 분리하기
테스트 코드는 구현 코드에서 분리하는 것이 좋다. 테스트 코드를 위해 접근 제어자를 public으로 하거나 테스트 코드에서만 사용되는 메서드를 만들지 말자.
테스트 하기 쉽게 코드 짜기
단위 테스트를 작성하기 어렵다면 코드를 잘못 작성했을 가능성이 높다. 테스트를 작성하기 쉽게 코드를 짜는 것이 더 좋은 코드일 확률이 높다. 테스트 하기 어려운 지점을 클래스나 메서드 외부로 분리하는 시도를 해보자.
private 테스트가 필요하다면 객체 분리 고려하기
private 메서드를 테스트하고 싶다면, 클래스(객체)를 분리하는 것을 고려해보자. 일반적으로 public을 테스트하는 과정에서 private 함수들이 테스트되고, private 메서드를 테스트 하고 싶은 경우라면 해당 메서드가 다른 역할을 수행하는 객체로 분리해야할지를고려해볼 타이밍이다.
예외 상황 고민하기
정상적인 경우를 구현하는 것보다 예외 상황을 모두 고려하여 프로그래밍 하는 것이 훨씬 어려운 일이다. 항상 이를 고려해 프로그래밍 하는 습관을 들이자.
비즈니스 로직과 UI 로직을 분리하자
한 클래스에서 비즈니스 로직과 UI 로직을 담당하지 않도록 하자.
상수 여러 개가 연관성이 있다면 enum을 고려해보자
연관성이 있는 static final 상수가 여러 개가 있다면, 이를 한데 묶어 enum으로 관리하는 것이 더 직관적이고 유지보수에 좋다.
final 키워드를 사용하자
final을 통해 값의 변경을 막고, 이를 명시적으로 나타내어 해당 변수가 메서드 혹은 클래스 내에서 변경되지 않는다는 의도를 드러낼 수 있다.
Intellij에서 파라미터, 변수 생성 시 자동으로 final 붙이기 옵션
객체는 객체스럽게 사용하자
Java는 객체지향 언어로, 객체를 객체스럽게 사용하는 것이 목적이다. 코드의 가독성과 유지보수성을 위해 객체지향을 공부하자.
필드(인스턴스 변수)를 줄이자
필드가 많으면 객체의 복잡도가 높아지고 버그가 발생할 가능성이 늘어난다.
List가 있고 해당 컬렉션의 값을 모두 더한 total이 있다면, 효율을 약간 포기하고 total을 메서드를 통해 그때그때 계산하여 반환하는 식으로 구현하면 total 변수를 사용하지 않아도 된다.
기능 개발과 리팩토링은 PR을 분리하자
기능 개발과 리팩토링을 같은 PR로 올리면 코드 리뷰하기가 너무 어려워진다. 기능을 개발하다가 리팩토링이 하고 싶은 부분을 발견한다면 잘 적어두고 기능 개발이 끝난 후 리팩토링 하자. 혹은 미리 리팩토링하고 나서 기능 개발하는 것도 좋은 방법이다.