4장 주석

2 minute read

나쁜 코드에 주석을 달지 마라. 새로 짜라 
- 브라이언 W. 커니핸, P. J. 플라우거

개요

  • 주석은 오래될수록 코드에서 멀어짐
    • 프로그래머들이 주석을 유지하고 보수하기는 현실적으로 어려움
  • 부정확한 주석은 아예 없는 것보다 안좋음

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

  • 코드에 주석을 추가하는 이유는 코드 품질이 나쁘기 때문
  • 표현력이 풍부하고 깔끔하며 주석이 없는 코드가, 복잡하고 어수선한데 주석이 많이 달린 코드보다 훨씬 좋음
  • 주석으로 설명할 시간에 난장판이 된 코드를 정리하는 것이 좋음

코드로 의도를 표현하라

  • 아래의 두 예시를 볼 것
// 직원에게 복지 혜택을 받을 자격이 있는지 검사한다.
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
if (employee.isEligibleForFullBenefits())
  • 주석으로 달려고 하는 내용을 함수로 만드는 것도 방법임

좋은 주석

법적인 주석

  • 정립된 구현 표준에 맞춰 넣는 주석
    • 예시
      // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
      // GNU General Public License 버전 2 이상을 따르는 조건으로 배포한다.
    

정보를 제공하는 주석

  • 기본적인 정보를 주석으로 제공하면 편리함
// 테스트 중인 Responder 인스턴스를 반환한다.
protected abstract Responder responderInstance();
// kk:mm:ss EEE, MMM dd, yyyy 형식이다.
Pattern timeMatcher = Pattern.compile(
"\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");

의도를 설명하는 주석

  • 때때로 주석은 구현을 이해하게 도와줄 뿐만 아니라 결정에 깔린 의도까지 설명함
public int compareTo(Object o) {
  if(o instanceof WikiPagePath) {
    WikiPagePath p = (WikiPagePath) o;
    String compressedName = StringUtil.join(names, "");
    String compressedArgumentName = StringUtil.join(p.names, "");
    return compressedName.compareTo(compressedArgumentName);
  }
  return 1; // 오른쪽 유형이므로 정렬 순위가 더 높다.
}
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.set(false);

  // 스레드를 대량 생성하는 방법으로 어떻게든 경쟁 조건을 만들려 시도한다.
  for (int i = 0; i < 25000; i++) {
    WidgetBuilderThread widgetBuilderThread =
    new WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
    Thread thread = new Thread(widgetBuilderThread);
    thread.start();
  }
  assertEquals(false, failFlag.get());
}

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

  • 인수나 반환값 자체를 명확하게 만들면 좋지만, 그렇지 못한 경우에 명료하게 밝히는 주석이 유용함
public void testCompareTo() throws Exception {
  WikiPagePath a = PathParser.parse("PageA");
  WikiPagePath ab = PathParser.parse("PageA.PageB");
  WikiPagePath b = PathParser.parse("PageB");
  WikiPagePath aa = PathParser.parse("PageA.PageA");
  WikiPagePath bb = PathParser.parse("PageB.PageB");
  WikiPagePath ba = PathParser.parse("PageB.PageA");

  assertTrue(a.compareTo(a) == 0); // a == a
  assertTrue(a.compareTo(b) != 0); // a != b
  assertTrue(ab.compareTo(ab) == 0); // ab == ab
  assertTrue(a.compareTo(b) == -1); // a < b
  assertTrue(aa.compareTo(ab) == -1); // aa < ab
  assertTrue(ba.compareTo(bb) == -1); // ba < bb
  assertTrue(b.compareTo(a) == 1); // b > a
  assertTrue(ab.compareTo(aa) == 1); // ab > aa
  assertTrue(bb.compareTo(ba) == 1); // bb > ba
}
  • 단, 그릇된 주석을 달아놓을 경우 상당히 위험

결과를 경고하는 주석

  • 다른 프로그래머에게 결과를 경고할 목적으로 사용하는 주석
// 여유 시간이 충분하지 않다면 실행하지 마십시오.
public void _testWithReallyBigFile() {
  writeLinesToFile(10000000);

  response.setBody(testFile);
  response.readyToSend(this);
  String responseString = output.toString();
  assertSubString("Content-Length: 1000000000", responseString);
  assertTrue(bytesSent > 1000000000);
}
public static SimpleDateFormat makeStandardHttpDateFormat() {
  // SimpleDateFormat은 스레드에 안전하지 못하다.
  // 따라서 각 인스턴스를 독립적으로 생성해야 한다.
  SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
  df.setTimeZone(TimeZone.getTimeZone("GMT"));
  return df;
}

TODO 주석

  • 앞으로 할 일을 TODO 주석으로 남겨두면 편함
// TODO-MdM 현재 필요하지 않다.
// 체크아웃 모델을 도입하면 함수가 필요 없다.
protected VersionInfo makeVersion() throws Exception {
  return null;
}
  • 그렇다고 TODO를 난발하는 코드는 좋지 않음
  • 주기적으로 TODO를 체크하고 없애주도록 해야함

중요성을 강조하는 주석

  • 대수롭지 않다고 생각하는데 중요한 부분에 주석으로 사용하기도 함
String listItemContent = match.group(3).trim();
// 여기서 trim은 정말 중요하다. trim 함수는 문자열에서 시작 공백을 제거한다.
// 문자열에 시작 공백이 있으면 다른 문자열로 인식되기 때문이다.
new ListItemWidget(this, listItemContent, this.level + 1);
return buildList(text.substring(match.end()));

공개 API에서 Javadocs

  • 설명이 잘 된 공개 API는 참으로 유용하고 만족스러음
  • 공개 API를 구현한다면 반드시 훌륭한 docs 를 작성하는 것이 좋음

Leave a comment