4 minute read

이 장에서는 주석에 대한 내용을 다룬다. 가끔은 필요한 주석도 있지만 가능한 주석을 안쓰는게 좋은 이유를 설명한다.

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

코드에 주석을 추가하는 이유는 코드 품질이 나쁘기 때문이다. 주석을 달 시간에 코드 품질을 개선하자

코드로 의도를 표현하라

위 내용의 확장되는 내용같다. 조금만 더 생각해서 코드로 의도를 표현하자.

//직원에게 복지 혜택을 받을 자격이 있는지 검사한다.
if((employee.flags & HOURLY_FLAG) && (employee.age > 65))
  • 주석이 달린 코드 예제
if(employee.isEligibleForFullBenefits())
  • 주석을 없애고 코드로 표현한 예제

좋은 주석

어떤 주석은 필요하거나 유익하다. 하지만 정말 좋은 주석은, 주석을 달지 않을 방법을 찾아내는 주석이다.

1. 법적인 주석
  • 회사가 정립한 구현 표준에 맞춰 법적인 이유로 특정 주석을 넣는것은 필요하며 타당하다.
    // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. ALL rights reserved.
    // GNU General Public License 버전 2 이상을 따르는 조건으로 배포한다.
    
2. 정보를 제공하는 주석
  • 때로는 기본적인 정보를 주석으로 제공하면 편리하다.
    //kk:mm:ss EEE, MMM dd, yyyy형식이다.
    Pattern timeMatcher = 
      Pattern.complie(
          "\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
    
  • SimpleDateFormat.format에서 반환하는 시각과 날짜를 뜻한다.
  • 이왕이면 시각과 날짜를 변환하는 클래스를 만들어 코드를 옮겨주면 더 좋고 깔끔해진다.
3. 의도를 설명하는 주석
  • 때때로 주석은 구현을 이해하게 도와주는 선을 넘어 결정에 깔린 의도까지 설명한다.
public void testConcurrentAddWidgets() throws Exception {
    WidgetBuilder widgetBuilder = 
        new WidgetBuilder(new Class[]{BoldWidget.class});
    String text = "'''bold text'''";
    ParentWidget parent = 
        new BoldWidget(new MockWidgetRoot(), "'''bold text'''");
    AtomicBoolean failFlag = new AtomicBoolean();
    failFlag = false; 
    
    //스레드를 대량 생성하는 방법으로 어떻게든 경쟁 조건을 만들려 시도한다.
    for(int i= 0; i< 2500; i++) {
        WidgetBuilderThread widgetBuilderThread =
            new WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
        Thread thread = new Thread(widgetBuilderThread);
        thread.start();
    }
    assertEquals(false, failFlag.get());
}
  • 저자의 의도를 나타내는 예제
4. 의미를 명료하게 밝히는 주석
  • 때때로 모호한 인수나 반환갑은 그 의미를 읽기 좋게 표현하면 이해하기 쉬워진다.
  • 그릇된 주석은 달지 않도록 주의하자
5. 결과를 경고하는 주석
  • 다른 프로그래머에게 결과를 경고할 목적으로 주석을 사용한다.
public static SimpleDateFormat makeStandardHttpDateFormat() {
    // SimpleDataFormat은 스레드에 안전하지 못하다.
    // 따라서 각 인스턴스를 독립적으로 생산해야한다.
    SimpleDataFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
    df.setTimeZone(TimeZone.getTimeZone("GMT"));
    
    return df
}
  • 결과를 경고하는 주석 예제
6. TODO 주석
  • ‘앞으로 해야할 일’ 을 TODO로 남겨두면 편하다.
  • 그러나 주기적으로 TODO 주석을 점검해 없애도 괜찮은 주석은 없애라.
7. 중요성을 강조하는 주석
  • 대수롭지 않다고 여겨질 뭔가의 중요성을 강조하기 위해서도 주석을 사용한다.
String listItemContent = match.group(3).trim();
// 여기서 trim은 중요하다. trim함수는 문자열에서 시작 공백을 제거한다.
// 문자열에 시작 공백이 있으면 다른 문자열로 인식되기 때문이다.

나쁜주석

대다수 주석이 이 범주에 속한다. 일반적으로 주석을 다는 이유는 허술한 코드를 지탱하거나, 엉성한 코드를 변명하거나, 미숙한 결정을 합리화한다.

주절거리는 주석
  • 특별한 이유없이 의무감으로 혹은 프로세스에서 하라고 하니깐 다는 주석은 시간낭비다.
  • 이왕 주석을 달기로 결정했다면, 충분한 시간을 들여 최고의 주석을 달자
  • 추가로 주석을 이해하기 위해 다른 코드를 뒤져보는 주석은 바이트만 낭비할 뿐이다.
같은 이야기를 중복하는 주석
  • 한눈에 보이는 간단한 함수는 중복해서 주석을 달 필요가 없다.
  • 자칫하면 코드보다 주석을 읽는 시간이 더 오래 걸린다.
// this.closed가 true일 때 반환되는 유틸리티 메서드다.
// 타임아웃에 도달하면 예외를 던진다.
public synchronized void waitForClode(final long timeoutMillis) 
    throw Exception {
    if(!closed) {
        wait(timeoutMillis);
        if(!closed)
            throw new Exception("MockResponseSender could not be closed");
    }
}
  • 함수와 주석이 같은 이야기를 하는 예제
오해할 여지가 있는 주석
  • 잘못된 정보를 제공하는 주석을 달지 말아라
  • 위 코드 주석에서또한 wait의 대한 정보가 주석에 안담겨 있으므로 오해할 수 있는 정보이다.
의무적으로 다는 주석
  • 모든 함수에 javadocs를 달거나 모든 변수에 주석을 달아야 한다는 규칙은 어리석다.
이력을 기록하는 주석
  • 이전에는 바람직 했으나, 코드관리 시스템(Git, SVN)과 같은 툴이 있기에 기록하지 않아도 된다.
있으나 마나 한 주석
  • 너무 당연한 사실을 언급하는 주석은 불필요하다.
public class User {
    /**
    * 기본 생성자
    */
    protected User() {
    
    }
    private String userName;
    
    /**
    * 사용자의 이름을 반환한다
    * @return userName
    */
    public String getUserName() {
        return userName;
    }
}

  • 당연한 사실을 언급하는 주석 예제
함수나 변수로 표현할 수 있다면 주석을 달지 마라
// 전역 목록<smodule>에 속하는 모듈이 우리가 속한 하위의 시스템이 의존하는가?
if(smodile.getDependSubsystems().contains(subSysMod.getSubSystem()))
    
  • 주석으로 표현한 case
ArrayList moduleDependees = smodule.getDependSubSystem();
String ourSubSystem = subSysMod.getSubSystem();
if(modileDependees.contains(ourSubSystem))
  • 함수나 변수로 표현한 case
위치를 표시하는 주석
  • 특정 위치를 표시하려는 주석을 가능한 사용하지 말아라. 주의를 환기할 뿐이다.
  • 반드시 필요할때만 드물게 사용해라
 // Actions ////////////////////////////////////////////
  • 위치를 표현하는 주석 예시
닫는 괄호에 다는 주석
  • 중첩이 심하고 장황한 함수라면 의미가 있을지도 모르지만, 작고 캡슐화된 함수를 짜도록 선호하면 잡음일 뿐이다.
공로를 돌리거나 저자를 표시하는 주석
  • 누가 작성했는지 알 수 있으나 소스관리 시스템에는 누가 언제 무엇을 추가했는지 알 수 있다.
  • 시간이 지나면 부정확한 정보로 변할 뿐이다.
주석으로 처리한 코드
  • 이유가 있어서 남겨놓았으리라고 둘 수 있지만 그렇게 점점 쌓여간다.
  • 소스 코드 관리 시스템이 기억해준다. 지우자
HTML주석
  • 주석을 뽑아 웹 페이지에 올릴 작정이라면 도구가 해야한다.
  • 프로그래머는 작성하지 않아야 한다.
전역 정보
  • 주석을 달아야 한다면 주변 코드만 기술하라
  • 시스템의 전반인 코드를 기술하지 말아라
너무 많은 정보
  • 주석에다 관련 없는 정보를 장황하게 늘어놓지 마라. 불필요하다.
모호한 관계
  • 주석과 주석이 설명하는 코드는 둘 사이 관계가 명확해야 한다.
/**
* 모든 픽셀을 담을 만큼 충분한 배열로 시작한다(여기에 필터 바이트를 더한다).
* 그리고 헤더 정보를 위해 200바이트를 더한다.
*/
this.pngByte = new byte[((this.width + 1) * this.height * 3) + 200];

  • Apaache commons에 존재하는 주석이지만, 주석으로 알아보기 힘들다.
함수 헤더
  • 짧은 함수를 작성하면 설명은 의미가 없다.
비공개 코드에서 javadocs
  • 공개 API에서는 javadocs가 유용하지만 공개 하지 않을 코드라면 javadocs는 쓸모가 없다.

주석을 마치며..

내용을 읽으며 당연한 내용도 있었지만 스스로를 되돌아 보는 내용들도 많이있었다.. 누군가가 읽기 위해 주석을 달았지만 결국 관리가 되지 않아 잘못된 정보를 주는 주석들을 달았던 기억이 나면서 앞으로는 주석을 달지 않을 수준의 코드를 짤 수 있도록 고민 해봐야겠다.

Categories:

Updated:

Leave a comment