본문 바로가기

Clean code

Clean Code 4장 - 주석

개발을 하다보면 보통 주석을 잘 달지 않아, 주석 좀 많이 달아라는 얘기를 많이 들었을 것이다. 그러면 주석이 많으면 많을수록 좋은걸까?

 

아니다!

 

중요한 주석이 있지만, 자신의 나쁜 코드를 숨기기 위해서 주석을 사용하는 경우도 있다. 오히려 주석을 많이 달았다면 자신이 코드로 모든 걸 표현하지 못했다고 반성해야 한다! 예시를 살펴보자

 

// 직원에게 복지 혜택을 받을 자격이 있는지 검사한다.
if ((employee.flags & HOURLY_FLAG) && 
	(employee.age > 65))
...
if (employee.isEligibleForFullBenefits())
...

위와 같이 대부분 함수로 표현할 수 있다.

좋은 주석 

1. 정보를 제공하는 주석

// 테스트 중인 Responder 인스턴스를 반환한다.
 protected abstract Responder responderInstance();
 // kk:mm:ss EEE, MMM dd, yyyy 형식이다.
 Pattern timeMatcher = Pattern.compile(
     "\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");

2. 의도를 설명하는 주석 - 구현을 이해하게 도와주고 결정한 의도를 파악할 수 있게 해줌

 public int compareTo(Object o){
     if(o instanceof WikiPagePath){
         ....
     }
     // ~~한 경우에는 우선순위가 높다.
     return 1;
 }
 public void testConcurrentAddWidgets() {
     ...
     // 스레드를 대량 생성하는 방법으로 경쟁 조건을 만든다.
     for (int i = 0; i < 25000; i++){
         new Thread(widgetBuilderThread).start();
     }
     ...
 }

3. 결과를 경고하는 주석

 // 여유 시간이 충분하지 않다면 실행하지 마십시오.
 public void _testWithReallyBigFile() {
     ...
 }
public static SimpleDateFormat makeStanardHttpDateFormat() {
     // SimpleDateFormat은 스레드에 안전하지 못하기 때문에 각 인스턴스를 독립적으로 생성해야 한다.
     SimpleDateFormat df = new SimpleDateFormat(".......");
     return df;
 }

4. 중요성을 강조하는 주석

 String listItemContent = match.group(3).trim();
 // 여기서 trim으로 시작공백을 제거함으로써 다른 문자열로 인식될 위험을 제거합니다.

나쁜 주석

1. 주절 거리는 주석

2. 같은 이야기를 중복하는 주석

// this.closed가 true일 때 반환되는 유틸리티 메서드다.
 // 타임아웃에 도달하면 예외를 던진다.

 public synchronized void waitForClose(final long timeoutMillis) 
     throws Exception{
     if(!closed) {
         wait(timeoutMillis);
         if(!closed)
             throw new Exception("~~~~");
     }
 }

3. 의무적으로 다는 주석

javadocs를 위해 기계적으로 다는 주석은 오히려 코드를 지저분하게 할 수 있다.

/**
  * 이 컴포넌트의 프로세서 지연값
  */
 protected int backgroundProcessorDelay = -1;	
	
 /**
  * 컨테이너와 관련된 Loader 구현
  */
 protected Loader loader = null;

 /**
  * 컨테이너와 관련된 Logger 구현
  */
 protected Log logger = null;

 /**
  * 컨테이너와 관련된 logger 이름
  */
 protected String logName = null;

 /**
  * 컨테이너와 관련된 Manager 구현
  */
 protected Manager manager = null;
 /**
  *
  * @param title CD 제목
  * @param author CD 저자
  */
 public addCD(String title, String author) {
     ...
 }

4.  함수나 변수로 표현할 수 있다면 주석을 달지 말라

// bad
 // 전역 목록 <smodule>에 속하는 모듈이 우리가 속한 하위 시스템에 의존하는가?
 if (smodule.getDependSubsystems().contains(subSysMod.getSubSystem()))
	
 // good
 ArrayList moduleDependees = smodule.getDependSubsystems();
 String ourSubSystem = subSysMod.getSubSystem();
 if (moduleDependees.contains(ourSubSystem))

5. 닫는 괄호에 닫는 주석

중첩이 심하여 해당 주석을 달았다고? 그럼 해당 함수를 쪼개는게 답이다.

package clean.code.chapter04;

 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;

 public class wc {
   public static void main(String[] args) {
     BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
     String line;
     int lineCount = 0;
     int charCount = 0;
     int wordCount = 0;
     try {
       while ((line = in.readLine()) != null) {
         lineCount++;
         charCount += line.length();
         String words[] = line.split("\\W");
         wordCount += words.length;
       } //while
       System.out.println("wordCount = " + wordCount);
       System.out.println("lineCount = " + lineCount);
       System.out.println("charCount = " + charCount);
     } // try
     catch (IOException e) {
       System.err.println("Error:" + e.getMessage());
     } //catch
   } //main
 }

6. 버전 관리에 관한 주석

git이 있는데 이런 주석은 필요없다.

/**
 	 * 변경 이력 (11-Oct-2001부터)
  * -------------------------------
  * 11-Oct-2001 : 클래스를 다시 정리하고 새로운 패키지로 옮김
  * 11.Nov-2001 : getDescription() method를 추가
  */

7. 주석처리된 코드