모르지 않다는 것은 아는것과 다르다.

Books

클린코드 4장 (주석)

채마스 2022. 4. 23. 21:25

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

  • 코드에 주석을 추가하는 일반적인 이유는 코드 품질이 나쁘기 때문이다.
  • 모듈을 짜고 보니 알아보기 어렵다면 주석을 다는 것이아니라 알아보기 쉽게 다시 코드를 정리해야 한다.

 

코드로 의도를 표현하라

  • 주석으로 코드를 설명하기 전에 코드만으로 의미를 포함할 수 있는 방법이 없는지 생각해봐야한다.
//직원에게 복지 혜택을 받을 자격이 있는지 검사한다.
if((employee.flags & HOURLY_FLAG) && 
   (employee.age>65))
  • 위와 같은 코드는 아래와 같이 바꿀 수 있다.
if(employee.isEligibleForFullBenefits())
  • 위의 코드를 보면 충분히 의도를 파악할 수 있다.

 

좋은 주석

 

법적인 주석

  • 법적인 이유로 특정 주석을 넣으라고 명시하는 경우 주석을 다는 것은 좋은 주석에 속한다.

 

정보를 제공하는 주석

  • 기본적인 정보를 주석으로 제공하면 편리한 경우가 있다.
//테스트 중인 Responder 인스턴스를 반환한다.
protected abstract Responder responderInstance();
  • 물론 위의 경우도 아래와 같이 함수 이름에 정보를 담는 편이 좀더 좋다.
protected abstract Responder responderBeingTested();

 

의도를 설명하는 주석

  • 코드를 짜면서 자신이 결정한 방식에 대해서 그 의도를 설명하는 주석을 말한다.
  • 예를들어, 두 객체를 비교할 때 어떤 객체보다 자기 객체에 높은 우선순위를 주고싶다면, 그 의도를 설명하는 주석을 달아두는 것은 바람직하다.
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();
    }

    //...
}

 

의미를 명료하게 밝히는 주석

  • 때때로 아래와 같이 모호한 인수나 반환값은 그 의미를 읽기 좋게 표현하면 이해하기 쉬운 경우가 있다.
assertTrue(a.compareTo(a) == 0); // a == a

 

결과를 경고하는 주석

  • 다은 프로그래머에게 결과를 경고하는 목적으로 작성된 주석은 유용하게 쓰일 수 있다.
// 여유 시간이 충분하지 않다면 실행하지 마십시오.
public void testWithReallyBigFile() {
    //...
}

 

TODO 주석

  • 더 이상 필요 없는 기능을 삭제하라는 알림의 경우 유용하다.
  • 누군가에게 문제를 봐달라는 요청의 경우 유용하다.
  • 앞으로 발생할 이벤트에 맞춰 코드를 고치라는 주의 표시하는 경우 유용하다.
  • 하지만 나쁜 코드를 남겨 놓는 핑계로 사용해서는 안된다.

 

중요성을 강조하는 주석

  • 자칫 대수롭지 않다고 여겨질 뭔가의 중요성을 강조하기 위한 용도라면 좋은 주석이다.
String listItemContent = match.group(3).trim();
// 여기서 trim으로 시작공백을 제거함으로써 다른 문자열로 인식될 위험을 제거합니다.
new ListItemWidget(this, listItemContent, this.level + 1);

공개 API에서 Javadocs

  • 설명이 잘 된 공개 API는 참으로 유용하다.
  • 표준 자바 라이브러리에서 사용한 javadocs가 좋은 예다.
  • 하지만 반드시 훌륭한 javadocs를 작성해야 한다.

 

나쁜 주석

 

주절거리는 주석

  • 특별한 이유 없이 의무감으로 다는 주석은 바이트 낭비일 뿐이다.
  • 주석을 달기로 결정했다면 충분한 시간을 들여 최고의 주석을 달도록 노력하자.

 

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

  • 이런 주석은 자칫하면 코드보다 주석을 읽는 시간이 더 오래 걸린다.
 // this.closed가 true일 때 반환되는 유틸리티 메서드다.
 // 타임아웃에 도달하면 예외를 던진다.

 public synchronized void waitForClose(final long timeoutMillis) throws Exception{
     if(!closed) {
         wait(timeoutMillis);
         if(!closed)
             throw new Exception("~~");
     }
 }
/**
* 컨테이너와 관련된 Loader 구현
*/
protected Loader loader = null;

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

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

 

오해할 여지가 있는 주석

  • 때때로 의도는 좋았으나 프로그래머가 딱 맞을 정도로 엄밀하게는 주석을 달지 못하는 경우가 있다.
  • 이런경우 오히려 주석으로 인해서 코드를 오해할 수 있다.
  • 그렇기 때문에 주석을 작성할때는 신중하게 의도가 정확히 기술 되었는지 생각해 봐야한다.

 

의무적으로 다는 주석

  • 예를들어, 아래와 같이 모든 변수에 주석을 달아야 한다는 규칙은 어리석다.
/*
@param tite CD 제목
@param author CD 저자
@param tracks CD 트랙 숫자
*/
public void addCD(String title, String author, int tracks) {
  CD cd = new CD();
  cd.title = title; 
  cd.author = author;
  cd.tracks = tracks;
}
  • 오히려 이런 주석은 코드를 복잡하게 만들고 혼동과 무질서를 초래한다.

 

이력을 남기는 주석

  • 소스 코드를 관리할 수 있는 시스템이 많은 지금 가장 필요없는 주석중 하나이다.

 

있으나 마나 한 주석

  • 아래와 같이 너무 당연한 사실이기 때문에 전혀 유익한 정보를 제공하지 못하는 주석을 말한다.
/**
* 기본 생성자
*/
protected AnnualDateRule() {
}

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

/** 
* 월 중 일자를 반환한다.
*
* @return 월 중 일자
*/
public int getDayOfMonth() {
    return dayOfMonth;
}
  • 이런 주석은 개발자가 다른 주석까지 무시하는 습관을 만들 수 있다.

 

무서운 잡음

  • 아래와 같이 수행하는 목적이 없이 작성된 주석을 말한다.
//The name
private String name;

//The version
private String version;

 

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

  • 위에서도 언급했듯이 코드로 의미를 표현할 수 있다면, 주석을 달지 않고 의미를 표현하는 것이 좋다.
// 전역 목록 <smodule>에 속하는 모듈이 우리가 속한 하위 시스템에 의존하는가?
if (smodule.getDependSubsystems().contains(subSysMod.getSubSystem()))
  • 위의 코드는 아래와 같이 코드만으로 의미를 표현할 수 있다.
ArrayList moduleDependees = smodule.getDependSubsystems();
String ourSubSystem = subSysMod.getSubSystem();
if (moduleDependees.contains(ourSubSystem))

 

위치를 표시하는 주석

  • 때때로 아래와 같이 소스 파일에서 특정 위치를 표시하려 주석을 사용하는 경우가 있다.
// Actions //////////////////////////////
  • 하지만 반드시 필요한 경우, 아주 드물게 사용하는 편이 좋은 경우가 있다.

 

닫는 괄호에 다는 주석

try {
    while ((line = in.readLine()) != null) {

    } //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
}

 

공로를 돌리거나 저자를 표시하는 주석

  • 이 또한 이력을 남길 수 있는 시스템이 만은 경우 불필요한 주석이다.

 

주석으로 처리한 코드

  • 주석으로 처리된 코드는 다른 사람들이 지우기를 주저한다.
  • 이유가 있어서 남겨놓았으리라고, 중요하니까 지우면 안 된다고 생각한다.
  • 그렇기 때문에 주석으로 남기는 코드는 없는것이 바람직 하다.

 

전역 정보

  • 주석을 달아야 한다면 근처에 있는 코드만 기술하는 것이 좋다.
  • 코드 일부에 주석을 달면서 시스템의 전반적인 정보를 기술하지 않은 것이 좋다.
/*
적합성 테스트가 동작하는 포트 : 기본값은 <b>8082</b>
@param fitnessePort
*/
public void setFitnessePort(int fitnessePort) {
  this.fitnessPort = fitnessePort;
}

 

너무 많은 정보

  • 주석에다 흥미로운 역사나 관련 없는 정보를 장황하게 늘어놓지 않는 것이 좋다.

 

모호한 관계

  • 주석과 주석이 설명하는 코드는 둘 사이 관계가 명백해야 한다.
  • 코드만으로 설명이 부족할 때 주석이 코드의 부족한 설명을 채우는 방식으로 작성되어야 한다.
  • 주석 자체가 다시 설명을 요구해서는 안된다.

 

비공개 코드에서 Javadocs

  • 공개 API는 javadocs가 유용하지만 공개하지 않을 코드라면 쓸모없는 주석에 불가하다.
  • 오히려 코드가 산만해 진다.

 




REFERENCES

  • 클린코드 4장

'Books' 카테고리의 다른 글

클린코드 8장  (0) 2022.04.23
클린코드 6장 (객체와 자료구조)  (0) 2022.04.23
클린코드 3장 (함수)  (0) 2022.04.17
클린코드 1장, 2장  (0) 2022.04.17
템플릿 콜백 패턴 (토비의 스프링 3장)  (0) 2022.02.28