[Clean Code] 4. 주석

Dayeon myeong·2021년 1월 31일
0

Clean Code

목록 보기
2/5

이 글은 Clean code 책 내용을 정리한 글입니다.

저작권 관련 문제가 있다면 "meme91322367@gmail.com"으로 메일 보내주시면, 바로 삭제하도록 하겠습니다.

주석은 나쁜 코드를 보완하지 못한다

코드에 주석을 추가하는 일반 적인 이유 = 코드 품질이 나쁨

코드를 정리해라,,

코드로 의도를 표현하라!

if ((employee.flags & HOURLY_FLAG) && 
	(employee.age > 65))

보다는

if (employee.isEligibleForFullBenefits())

의도를 표현한 위 코드처럼 사용하자

1. 좋은 주석

1-1. 법적인 주석

// Copyright (c) 2003 ,,,

1-2. 정보를 제공하는 주석

때로는 기본적인 정보를 주석으로 제공할 때 편리하다.

 // 테스트 중인 Responder 인스턴스를 반환한다.
 protected abstract Responder responderInstance();

이 경우 함수 이름을 responderBeingTested 로 수정하면 주석이 필요 없어진다.

 // kk:mm:ss EEE, MMM dd, yyyy 형식이다.
 Pattern timeMatcher = Pattern.compile(
     "\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");

위 주석은 코드에서 사용한 정규표현식이 시각과 날짜를 뜻한다고 설명한다.

1-3. 의도를 설명하는 주석

때때로 주석은 구현을 이해하게 도와줄 뿐만 아니라 결정에 깔린 의도를 설명하기도 한다.

 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();
    }
    ...
}

1-4. 의미를 명료하게 밝히는 주석

때때로 모호한 인수나 반환값은 그 의미를 읽기 좋게 표현하면 이해하기 쉬워진다. 일반적으로는 인수나 반환값 자체를 명확하게 만들면 더 좋겠지만, 인수나 반환값이 표준 라이브러리나 변경하지 못하는 코드에 속한다면 의미를 명료하게 밝히는 주석이 유용하다.
하지만 주석이 틀린 정보를 제공할 위험이 있기 때문에 신중하게 작성하여야 한다.

 assertTrue(a.compareTo(a) == 0); // a == a
 assertTrue(a.compareTo(b) != 0); // a != b

1-5. 결과를 경고하는 주석

다른 프로그래머에게 경고할 목적으로 주석을 사용하는 경우에도 유용하게 쓰일 수 있습니다.

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

1-6. TODO 주석

앞으로 해야 할 일을 // TODO 주석으로 남겨두는 경우에도 유용하게 쓰인다. 하지만 나쁜 코드를 남겨놓는 핑계가 되서는 안된다. 그리고 주기적으로 TODO 주석을 점검해 없애도 괜찮은 주석은 없애라고 권한다.

 // TODO 현재는 필요하지 않다.
 protected VersionInfo makeVersion() {
     return null;
 }

1-7. 중요성을 강조하는 주석

자칫 대수롭지 않다고 여겨질 뭔가의 중요성을 강조하기 위해서도 주석을 사용한다.

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

1-8. 공개 API에서 Javadocs

어느 주석과 마찬가지로 javadocs 또한 잘못된 정보를 제공하거나 잘못 위치할 위험이 있으니 항상 주의깊게 작성해야 한다.

2. 나쁜 주석

대다수의 주석은 나쁜 주석에 속한다.
허술한 코드를 지탱하거나, 엉성한 코드를 변명하거나,미숙한 결정을 합리화하는 등 프로그래머가 주절거리는 독백에서 크게 벗어나지 못한다.

2-1. 주절거리는 주석

특별한 이유 없이 의무감으로 다는 주석은 시간낭비이다. 충분한 시간을 들여 최고의 주석을 달도록 노력한다.

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

헤더에 달린 주석이 같은 코드 내용을 그대로 중복한다. 코드보다 주석 읽는 시간이 더 오래 걸린다.

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

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

2-3. 오해할 여지가 있는 주석

주석에 담긴 '잘못된 정보'는 오해할 여지가 있다.

2-4. 의무적으로 다는 주석

javadocs를 위한 기계적인 주석은 오히려 잘못된 정보를 제공할 여지만 만든다.

2-5. 이력을 기록하는 주석

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

변경 이력을 기록하지 말자.

2-6. 있으나 마나 한 주석

당연한 사실을 언급해서 정보를 제공하지 못하는 주석은 제거하는 것이 좋다.

 /**
  * 기본 생성자
  */
 protected AnnualDateRule() {
 }

 /** 월 중 일자 */
 private int dayOfMonth;

 /** 
  * 월 중 일자를 반환한다.
  *
  * @return 월 중 일자
  */
 public int getDayOfMonth() {
     return dayOfMonth;
 }

2-7. 무서운 잡음

때로는 Javadocs도 잡음이다. 단지 문서를 제공해야 한다는 잘못된 욕심으로 탄생한 잡음일 뿐이다.

2-8. 함수나 변수로 표현할 수 있다면 주석을 달지 마라

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

보다는

 ArrayList moduleDependees = smodule.getDependSubsystems();
 String ourSubSystem = subSysMod.getSubSystem();
 if (moduleDependees.contains(ourSubSystem))

2-9. 닫는 괄호에 다는 주석

때로는 닫는 괄호에 특수한 주석을 달아놓는다. 중첩이 심하고 장황한 함수라면 의미가 있을지도 모르지만 작고 캡슐화된 함수에는 잡음일 뿐이다. 이런 경우 함수를 작게 만들려 노력하는 편이 낫다.

 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
 }

2-10. 공로를 돌리거나 저자를 표시하는 주석

코드에 대해 누구한테 물어볼지 알려줄 수 있어 유용할 거라 생각할 수도 있지만, 이런 주석은 오랫동안 코드에 방치되어 점차 부정확하고 쓸모없는 정보로 변할 것이다. 아래와 같은 정보는 소스 코드 관리 시스템에 저장하는 편이 좋다.

/* 릭이 추가함 */

2-11. 주석으로 처리한 코드

주석으로 처리된 코드는 다른 사람들도 지우기를 주저한다. 하지만 우리는 오래전부터 우수한 소스코드 관리 시스템을 사용해왔다. 이제는 주석으로 처리할 필요가 없다.

2-12. HTML 주석

소스코드에서 HTML 코드를 달지 마라.

2-13. 전역 정보

근처에 있는 코드에 대한 주석만 기술하라. 코드 일부에 주석을 달면서 시스템의 전반적인 정보를 기술하지 마라. 추후에 전역 정보가 변했을 때 주석을 함께 변경하는 것을 보장하기 어렵기 때문이다.

/**
 * 적합성 테스트가 동작하는 포트: 기본값은 8082
 *
 * @param fitnessePort
 */
public void setFitnessePort(int fitnessePort) {
    this.fitnessePort = fitnessePort;
}

2-14. 모호한 관계

주석과 주석이 설명하는 코드는 둘 사이 관계가 명백해야 한다. 주석과 코드를 보고 무슨 소리인지 알도록 해라.

/*
*모든 픽셀을 담을 만큼 충분한 배열로 시작한다(여기에 필터 바이트를 더한다)
*그리고 헤더 정보를 위해 200바이트를 더한다.
*/

2-15. 함수 헤더

짧고 한 가지만 수행하며 이름을 잘 붙인 함수가 주석으로 헤더를 추가한 함수보다 훨씬 좋다.

2-16. 비공개 코드에서 Javadocs

공개 API는 Javadocs가 유용하지만 공개하지 않을 경우에는 쓸모가 없다.
코드가 산만해질 뿐이다.

profile
부족함을 당당히 마주하는 용기

0개의 댓글