Clean Code

[Clean Code] 4장. 주석

개발자 문문 2025. 8. 20. 17:23

안녕하세요 개발자 문문입니다.

오늘은 4장 주석을 공부해보겠습니다.

 

 

  • 프로그래밍 언어를 치밀하게 사용해 의도를 표현할 능력이 있가면, 주석은 전혀 필요하지않다.
  • 주석은 코드로 의도를 표현하지 못해, 실패를 만회하기 위해 사용하는 것이다.
  • 주석을 달 때마다 자신에게 표현력이 없다는 사실을 푸념해야 마땅하다.
  • 그러므로 우리는 주석을 가능한 줄이도록 꾸준히 노력해야 한다.

저는 현업에서 주석을 자주 사용했었는데 이 챕터의 초반부터 혼나는 느낌이었습니다ㅋㅋㅋ

 

  • 주석은 나쁜 코드를 보완하지 못한다.
  • 코드에 주석을 추가하는 일반적인 이유는 코드 품질이 나쁘기 때문이다.

 

  • 코드로 의도를 표현하라!
// 1번 코드
// 직원에게 복지 혜택을 받을 자격이 있는지 검사한다.
if((employee.flags & HOURY_FLAG) && (employee.age > 65))


//2번 코드
if(employee.isEligibleForFullBenefits())
  • 많은 주석으로 달려는 설명을 함수로 만들어 표현해도 충분하다.(2번 코드가 1번 코드보다 좋다.)

 

  • 좋은 주석
  • 법적인 주석
  • 회사가 정립한 구현 표준에 맞춰 법적인 이유로 특정 주석을 넣으라고 명시
  • 저작권 정보, 소유권 정보

 

  • 정보를 제공하는 주석
//테스트 중인 Responder 인스턴스를 반환한다.
protected abstract Responder responderInstance();

// kk:mm:ss EEE, MMM dd, yyyy 형식이다.
Pattern timeMatcher = Pattern.compile(
"\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
  • 저자는 위와 같은 주석이 유용하긴 하지만, 그럼에도 함수이름을 변경하거나, 시각과 날짜를 변경하는 클래스를 따로 만드는 등의 작업을 진행하여 주석을 쓰지 않는 것을 더 추천하네요.

 

  • 의도를 설명하는 주석
  • 주석은 구현을 이해하기 도와주는 선을 넘어 결정에 깔린 의도까지 설명한다.
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());
}
  • 이 로직을 동의하지 않을지도 모르지만 코드를 작성한 사람의 의도는 분명하게 드러나는 주석이다.

 

  • 의미를 명료하게 밝히는 주석
  • 모호한 인수나 반환값은 그 의미를 좋게 표현하면 이해하기 쉬워진다.
assertTrue(a.compareTo(a) == 0); // a == a
assertTrue(a.compareTo(b) == -1); // a < b
assertTrue(ab.compareTo(aa) == 1); // ab > aa

 

 

  • 결과를 경고하는 주석
  • 다른 프로그래머에게 결과를 경고할 목적으로 사용하는 주석
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 주석을 점검해 없애더 괜찮은 주석은 없애는 것이 좋다.

 

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

 

 

  • 나쁜 주석
  • 주절거리는 주석
  • 특별한 이유 없이 의무감으로 혹은 프로세스에서 하라고 하니까 마지못해 주석을 다는 것은 시간낭비다.

 

  • 같은 이야기를 중복하는 주석
// this.closed가 true일 때 반환하는 유틸리티 메서드다.
// 타임아웃에 도달하면 예외를 던진다.
public synchronized void waitForClose(final long timeoutMillis) throws Exception
{
  if(!closed)
  {
    wait(timeoutMillis);
    if(!closed)
      throw new Exception("MockResponseSender could not be closed!");
  }
}
  • 주석이 코드보다 더 많은 정보를 제공하지 못한다.
  • 코드를 정당화하는 주석도 아니고, 의도나 근거를 설명하는 주석도 아니다.
  • 독자가 함수를 대충 이해하고 넘어가게 만든다.
  • 코드만 봐도 알 수 있는 내용을 굳이 주석을 적는것은 좋지 않다는 말인것 같습니다.

 

  • 의무적으로 다는 주석
/**
 *
 * @param title CD 제목
 * @param author CD 저자
 * @param tracks CD 트랙 숫자
 * @param durationInMinutes CD 길이(단위: 분)
 */
public void addCD(String title, String author, int tracks, int durationInMinutes) {
  CD cd = new CD();
  cd.title = title;
  cd.author = author;
  cd.tracks = tracks;
  cd.duration = durationInMinutes;
  cdList.add(cd);
}
  • javadocs를 달거나 모든 변수에 주석을 달아야 한다는 규칙은 어리석다.
  • 아무런 가치도 없는 주석이다.

 

  • 이력을 기록하는 주석, 저자를 표시하는 주석
  • 때때로 사람들은 모듈을 편집할 때 마다 모듈 첫 머리에 주석을 추가한다.
  • 지금은 소스 코드 관리 시스템이 있으니 변경 이력을 모듈의 첫 머리에 계속 추가하는 것은 필요없다.
  • 소스 코드 관리 시스템은 누가 언제 무엇을 추가했는지 정확하게 기억하기 때문에 저자를 표시하는 주석도 필요없다.

 

  • 있으나 마나 한 주석
  • 너무 당연한 사실을 언급하며 새로운 정보를 제공하지 못하는 주석
  • ex) 생성자 위에 /*기본 생성자*/ 같은 주석

 

  • 함수나 변수로 표현할 수 있다면 주석을 달지 마라
// 1번 코드
// 전역 목록 <smodule>에 속하는 모듈이 우리가 속한 하위 시스템에 의존하는가?
if (smodule.getDependSubSystems().contains(subSysMod.getSubSystem()))

// 2번 코드
ArrayList moduleDependees = smodules.getDependSubsystems();
String ourSubSystem = subSysMod.getSubSystem();
if (moduleDependees.contains(ourSubSystem))

 

 

  • 위치를 표시하는 주석
  • // Actions ////////////////////////////////////////////////////////////
  • 이런 주석이 유용한 경우도 있지만 일반적으로는 가독성을 낮추기 때문에 제거하는 것이 좋다.

 

  • 닫는 괄호에 다는 주석
  • 중첩이 심하고 장황한 함수라면 의미가 있을지 모르지만 작고 캡슐화된 함수에는 잡음이다.
while(...)
{
...
} //while

 

 

  • 주석으로 처리한 코드
  • 주석으로 처리된 코드는 다른 사람들이 지우기 주저한다.
  • 남겨둔 이유가 있다고 생각하여 지우면 안된다고 생각을 한다.
  • 이전의 코드 또한 소스 코드 관리 시스템에 남아있기 때문에 사용하지 않는 것이 좋다.

 

  • HTML 주석
  • HTML 주석은 혐오 그 자체다.
  • HTML 주석은 편집기/IDE에서도 읽기 어렵고, 도구로 주석을 뽑아 웹 페이지에 올릴 작정이면, 주석에 HTML 태그를 삽입해야 하는 책임은 도구가 져야 하기 때문이다.

 

  • 전역 정보
  • 주석을 달아야 한다면 근처에 있는 코드만 기술하라.
  • 코드 일부에 주석을 달면서 시스템의 전반적인 정보를 기술하지 마라.

 

  • 너무 많은 정보
  • 주석에다 흥미로운 역사나 관련없는 정보를 장황하게 늘어놓지 마라.

 

  • 모호한 관계
  • 주석과 주석이 설명하는 코드는 둘 사이의 관계가 명백해야 한다.
/*
 * 모든 픽셀을 담을 만큼 충분한 배열로 시작한다.(여기에 필터 바이트를 더한다.)
 * 그리고 헤더 정보를 위해 200바이트를 더한다.
 */
this.pngBytes = new byte[((this.width + 1) * this.height * 3) + 200];

 

  • 함수 헤더
  • 함수 헤더는 이름을 잘 붙인 함수가 주석으로 헤더랄 추가한 함수 보다 좋다.

 

'Clean Code' 카테고리의 다른 글

[Clean Code] 5장. 형식 맞추기  (5) 2025.08.26
[Clean Code] 3장. 함수  (0) 2025.08.20
[Clean Code] 2장. 의미 있는 이름  (9) 2025.08.11
[Clean Code] 1장. 깨끗한 코드  (2) 2025.08.09