_

Always be tactful

Programming/Insights

[Java] 나를 위해 정리한! 피드백 모음!

funczun 2025. 2. 11. 02:11

개발은 혼자 하는 것이 아니다.

 다른 개발자와의 원활한 소통을 위해서 좋은 이름을 짓는 것은 아주 중요하다. 변수 이름, 메서드 이름, 클래스 이름을 짓는데 시간을 투자하자. 이름을 통해 의도를 드러내자.


 [❗] 변수 이름에 자료형을 사용하지 말자.

 

 변수명에 자료구조 이름을 포함시키면, 나중에 그 자료구조를 변경할 때 변수명을 변경해야 할 수 있다. 변수명을 자료구조에 의존하지 않도록 짓자.

 

 자료형을 드러내는 것보다 의도를 드러내는 것이 중요하다. 예를 들어 carNameList는 해당 변수의 자료형인 리스트에 초점을 맞추고 있다. 차라리 carModels와 같이 구체적인 변수명을 사용하면 해당 변수가 차 모델을 담고 있다는 의도가 명확하게 전달된다.

String carNameList = Console.readLine();
String[] arrayString = carNameList.split(",");

 [❗] 의도를 드러낼 수 있다면 이름이 길어져도 괜찮다.

 

 종종 클래스, 메서드, 변수 이름을 줄이려는 유혹에 빠진다. 하지만 축약은 혼란을 야기할 뿐이다.


 [❗] 클래스와 메서드 이름을 한 두 단어로 유지하려고 노력하자.

 

 의도 전달을 위해 꼭 필요한 부분이라면 제거할 수 없겠지만, 문맥을 중복하는 이름은 자제하자. 클래스 이름이 Order라면, 메서드 이름을 shipOrder()라고 지을 필요가 없다. ship()이라고 해도 클라이언트에서는 order.ship()이라고 호출하며, 간결한 표현이 된다. 연속된 숫자를 덧붙이거나 불용어를 사용하는 것 역시 자제한다.


*불용어 (stop word)


 if, for, while 문 사이 공백도 코딩 컨벤션이다. 문맥을 분리하는 부분에서 적절한 공백 라인을 사용하면 가독성이 향상된다. 그렇다고 하여 공백을 남발하지는 말자. 과도한 공백은 다른 개발자에게 의문을 줄 뿐이다.


 [❗]  space와 tab을 혼용하지 말자.

 

 사실, 들여쓰기를 어떻게 할 것인가는 프로그래머들 사이 꽤나 유명한 논쟁거리다. 하지만 코드 컨벤션에서 가장 중요한 것은 일관성을 갖추는 일이다. 혼용만큼 최악인 습관은 없다.


ㅁ tab

 space와 tab, 둘 다 1byte의 용량을 차지한다. 때문에 용량 절약 관점에서는 tab을 사용하는 것이 우세하다. 적은 입력으로 들여쓰기를 할 수 있어 편리하다.

 

ㅁ space

 tab은 에디터마다 설정값대로 들여쓰기가 되지만, space는 에디터가 달라도 같은 형식으로 보인다. 대부분의 프로그래머들이 space를 사용한다는 것도 중요한 점이다.


 결론은 space다. 그러니 space를 습관화하자.


 [❗] IDE의 코드 자동 정렬 기능을 활용하자.

 

 인텔리제이의 경우 윈도우 사용자는 Ctrl + Alt + L 단축키를 통해 자동 정렬 기능을 사용할 수 있다.


 [❗] 의미 없는 주석은 달지 말자.

 

 좋은 이름을 통해 어떤 의도인지가 충분히 드러난다면, 굳이 주석을 달지 않는 것이 좋다. 모든 것에 주석을 달기보다는 가능한 이름을 통해 의도를 드러내고, 의도를 드러내기 힘든 경우에 주석을 다는 연습을 하자.


 [❗] Java에서 제공하는 API를 적극 활용하자.

 

 메서드를 직접 구현하기 전에, Java API에서 제공하는 기능인지 먼저 검색해 보자. 예를 들어 사용자를 출력할 때, 사용자가 2명 이상이라면 쉼표를 기준으로 출력하기 위한 문자열은 다음과 같이 구현 가능하다.

List<String> members = Arrays.asList("Ace", "Buggy");
String result = String.join(",", members); // Ace, Buggy

 [❗] 배열 대신 Java Collection을 사용하자.

 

 Java Collection 자료구조 (List, Set, Map, 등) 사용 시, 데이터를 조작할 때 다양한 API를 사용할 수 있다. 예를 들어 List<String>에 "Ace"라는 값이 포함되어 있는지는 다음과 같이 확인할 수 있다.

List<String> members = Arrays.asList("Ace", "Buggy");
boolean result = members.contains("Ace"); // true

ㅁ List.contains()

 같은 contains() 메서드로 성능이 같다고 오해할 수 있지만, List의 contains() 메서드는 내부적으로 순차 탐색을 한다. 따라서 리스트에서 특정 요소를 찾을 때 시간복잡도는 O(n)이다. ArrayList와 같이 순차적으로 접근하는 컬렉션에서 발생하는 특징이다.

 

ㅁ HashSet.contains()

 반면, HashSet은 내부적으로 해시 테이블을 사용하여 요소를 저장하기 때문에, contains() 메서드는 평균적으로 O(1) 시간복잡도를 가진다. 쉽게 말해 요소가 많을수록 List 대비 성능이 상대적으로 빠르다. 순서가 중요하거나 중복을 허용해야 하는 경우라면 List 사용이 불가피하겠지만 그렇지 않다면 HashSet을 사용하자.


P.S. 알고리즘 풀다가 알게 된 사실이라 넣음 ㅎㅎ


 README.md는 소스코드에 앞서 해당 프로젝트가 어떤 프로젝트인지 마크다운으로 작성하여 소개하는 문서이다. 어떤 프로젝트인지, 어떤 기능을 담고 있는지 기술하기 위해 마크다운 문법을 검색해서 학습하고 적용해 보자.


 [❗] 기능 목록을 재검토하자.

 

 기능 목록을 너무 상세하게 작성하지는 말자. 클래스 이름, 메서드 시그니처와 반환값은 언제든 변경될 수 있다. 너무 세세한 부분까지 정리하기보다는 구현해야 할 기능 목록을 정리하는 데 집중하자.

 

 이미 작성한 기능 목록은 기능 구현을 거치며 변경될 수 있다. 시작할 때 너무 완벽하게 모든 기능을 정리하려 하지 말고, 기능을 구현하면서 문서를 계속 업데이트 하자. README.md 파일은 살아있는 문서와 같다.

 

 정상적인 경우도 중요하지만, 예외적인 상황도 기능 목록에 정리해야 한다. 특히 예외 상황은 시작 단계에서 모두 찾기 힘들기 때문에, 기능을 구현하며 계속해서 추가해 나아가야 한다.


 [❗] 값을 하드 코딩하지 말자.

 

 문자열, 숫자 등의 값을 하드 코딩하지 말자. 상수를 만들고 이름을 부여하여, 이 변수의 역할이 무엇인지 의도를 드러내자. (enum을 사용해 실수를 줄일 수도 있을 듯하다.)


 [❗] 한 함수는 한 기능만을 담당하도록 한다.

 

 함수의 길이가 길어진다면 한 함수에서 여러 기능을 하려고 하지는 않는지 의심해 보자. 예를 들어 한 함수에서 안내 문구를 출력하고, 사용자의 입력을 받아 유효성을 검증하는 등 여러 기능을 한다면 적절하게 분리해야 한다.

 

 여러 함수에서 중복되어 사용하는 코드가 있다면 함수 분리를 고민해 보자. 또한, 의식적으로 함수의 길이를 15줄 이하로 구현하도록 노력하자. 충분한 연습이 될 것이다.


 테스트를 작성해 보자. 테스트는 단지 기능을 점검하기 위한 목적으로 작성하는 것이 아니다. 테스트를 작성하는 과정에서 나의 코드에 대해 빠르게 피드백을 받을 수 있고, 이는 훌륭한 학습 도구로 활용할 수 있다. 이런 경험을 누적시켜 어떤 유용함을 느끼는지 알아보자.


 [❗] 처음부터 큰 단위의 테스트를 만들지 말자.

 

 테스트의 중요한 목적 중 하나는 나의 코드에 대해 빠르게 피드백을 받는 것에 있다. 시작부터 너무 큰 단위의 테스트를 만들면 그만큼 오랜 시간이 걸리기 마련이다. 문제를 작게 나누고, 그중 핵심기능에 가까운 부분부터 테스트를 만들어 나아가자.


마지막으로

 

 항상 다른 개발자들과 협업하는 상황을 고려하자. 가장 중요한 것은 언제나 가독성과 일관성이다! 그래야 불필요한 시간 낭비를 예방하고, 코드 유지보수가 용이해진다!

 

 영한 선생님께서 성능 최적화도 좋지만, 모래알 같이 미미한 성능 개선을 위해 가독성을 포기하지 말라고 하셨다. 프로그래밍을 할 때, 성능 최적화를 우선적으로 고려하는 것이 능사는 아니다.


 형한테 테스트 주도 개발 책을 받았다. 여유 생길 때마다 읽어보고 관련 내용도 추후 포스팅하도록 하겠다. 0==(^o^)o