Clean Code : 4장(주석)

4장. 주석

주석으로 코드를 표현하는 방식은 좋지 않다고 합니다. 그 이유는 코드는 계속적으로 변화하고 진화하게 되는데 반해, 주석은 코드 작성자가 실수로 업데이트를 하지 못할 가능성이 충분히 존재합니다. 오히려 코드와 다른 부정확한 주석이 원래 코드의 의도를 헤치는 경우도 발생하기 때문에 주석으로 코드를 설명하는 것보다는 주석없이 코드 자체로 정확한 정보를 제공하고 의도를 표현할 수 있게 노력해야 합니다.

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

코드에 주석을 추가하는 일반적인 이유는 코드를 잘 알아보기 힘들기 때문입니다. 표현력이 붕부하고 깔끔하며 주석이 거의 없는 코드가 복잡하고 어수선하며 주석이 많이 달린 코드보다 훨씬 좋습니다. 그래서 주석을 달기 전에 코드를 정리해야하는지 점검하는 시간이 꼭 필요합니다.

4-2. 코드로 의도를 표현하라!

아래의 예제처럼 함수로 만들어서 코드자체로 의도를 표현하는 것이 좋습니다.

// 직원이 복지 혜택을 받을 자격이 있는지 체크
if ((employee.flags & HOURLY_FLAG) &&
	(employee.age >65))
    
// 함수의 이름으로 의미를 파악할 수 있게 변경
if (employee.isEligibleForFullBenefits())

4-3. 좋은 주석

코드로 의도를 표현하는 것이 좋지만 어떤 주석들은 필요하거나 유익할 수 있습니다.

법적인 주석

저작권 정보나 소유권 정보등을 나타내기 위한 주석들은 필수불가결한 요소입니다.

정보를 제공하는 주석

함수에 대한 기본적인 정보를 주석으로 제공하면 편리합니다. 함수 이름에 정보를 담는 편이 더 좋지만 정규표현식 같이 난해할 수 있는 경우는 주석을 유용하게 사용할 수 있습니다.

의도를 설명하는 주석

코드를 보고 작성자의 의도까지 파악하기 힘들기 때문에 주석을 통해 의도를 설명하면 코드 구현에 대한 이해를 도와줄 수 있습니다.

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

모호한 인수나 반환값을 설명하기 위한 주석은 괜찮습니다. 물론 인수나 반환값을 명확하게 만들면 더 좋겠지만, 인수나 반환값을 변경하지 못하는 코드가 있을 수 있기 때문에 의미를 명료하게 밝히는 주석은 유용합니다.

결과를 경고하는 주석

때로는 자신의 코드를 읽는 프로그래머들이 결과를 예측하지 못할 수 있기 때문에 결과에 대한 경고를 위한 주석은 적절히 사용하면 괜찮습니다.

TODO 주석

더 이상 필요 없는 기능을 삭제, 누군가에게 문제를 점검해달라는 요청, 더 좋은 이름을 떠올려달라는 부탁, 앞으로 발생할 이벤트에 맞춘 코드 수정 등 당장 구현하기 어려운 업무를 기술하는 TODO 주석은 유용할 수 있습니다.

하지만 어떤 용도이든 나쁜 코드를 남겨 놓는 핑계가 되어서는 안됩니다.

최근에 대다수의 IDE는 TODO 주석을 전부 찾아 보여주는 기능을 제공하니, 주기적으로 TODO 주석을 점검하여 없애도 괜찮은 주석은 없애는 것이 좋습니다.

중요성을 강조하는 주석

대수롭지 않다고 여겨질 만한 것의 중요성을 강조하기 위한 주석을 사용하기도 합니다.

공개 API에서 Javadocs

공개 API를 구현한다면 docs를 작성하는 것이 좋습니다.

4-4. 나쁜 주석

대다수의 주석이 나쁜 주석에 속합니다. 일반적으로 대다수의 주석은 허술한 코드를 설명하거나 변명, 합리화하는 등의 독백에서 벗어나지 못하기 때문입니다.

주절거리는 주석

특별한 이유 없이 의무감으로 혹은 프로세스에 따라서 마지못해 주석을 다는 것은 시간낭비나 마찬가지입니다. 주석을 달기로 했다면 충분한 시간을 들여 최고의 주석을 달도록 노력하는 것이 좋습니다.

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

아래의 예제처럼 간단한 코드나 코드를 보고 충분히 이해할 수 있을 만한 내용을 그대로 중복해서 설명하는 주석은 좋지 않습니다.

// this.closed가 true일 때 반환되는 유틸리티 메서드다.
// 타임아웃에 도달하면 예외를 던진다.
public synchronized void waitForClose(final long timeoutMillis) throws Exception {
    if (!closed) {
        wait(timeoutmillis);
        if (!closed)
            thorw new Exception("MockResponseSender could not be closed");
    }
}

오해할 여지가 있는 주석

때때로 의도는 좋았으나 오해가 생기는 주석이 생기기도합니다.

위의 예제에서 this.closed가 true일 때 반환되는 유틸리티 메서드다.이 부분은 사실 잘못된 정보입니다. 코드를 보면 true일 때 반환(함수가 끝남)되는 것이 아니라 true여아 반환되기 때문입니다.

이렇게 살짝 잘못된 정보로 인해 사용자가 잘 못 사용하게 될 수도 있기 때문에 충분히 생각해보고 주석이 오해할 만한 여지를 제거해야 합니다.

의무적으로 다는 주석

모든 함수에 Javadocs를 달거나 모든 변수에 주석을 다는 것은 오히려 코드를 복잡하고 혼란스럽게 만들 수 있습니다. 아래의 예시처럼 간단히 파악할 수 있는 것은 오히려 주석을 달지 않는 것이 좋을 수 있습니다.

/**
 * @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);
}

이력을 기록하는 주석

때때로 모듈을 편집할 때마다 모듈에 주석을 추가하는 경우가 있습니다. 하지만 요즘은 예전과 달리 Git같은 소스 코드 관리 시스템이 잘 되어있어 혼란만 야기할 뿐입니다.

있으나 마나 한 주석

아래와 같이 너무 당연한 사실을 언급하는 있으나 마나 한 주석은 좋지 않습니다. 이런 당연한 주석은 코드를 읽는 사람으로 하여금 주석을 무시하게 만들 수 있기 때문입니다.

// 기본 생성자
protected CD() {
}

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

계속 이야기했듯이, 아래의 예제처럼 주석을 함수나 변수로 표현할 수 있다면 주석을 다는 것보다 주석이 필요하지 않도록 코드를 개선하는 편이 더 좋습니다.

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

변수에 이름을 붙여 할당함으로써 주석을 제거할 수 있습니다.

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

위치를 표시하는 주석

때로는 프로그래머가 소스 파일에서 특정 위치를 표시하려 주석을 사용하기도 합니다. 아래와 같이 특정 기능을 모아놓는 것을 눈에 띄게 표시할 때 유용한 경우도 있긴 하지만 자주 사용하면 가독성이 떨어지기 때문에 꼭 필요한 경우에만 사용하는 것이 좋습니다.

// Actions /////////////////////

닫는 괄호에 다는 주석

닫는 괄호에 다는 주석은 중첩이 심하고 장황한 함수라면 의미가 있을지도 모르지만 닫는 괄호에 주석을 다는 것보다는 함수를 줄이려는 시도를 하는 게 좋습니다.

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

이것도 마찬가지로 소스 코드 관리 시스템이 있기 때문에 굳이 주석으로 남길 필요가 없습니다. 이런 주석은 오랫동안 방치되다가 부정확하고 쓸모없는 정보로 변하기 쉽습니다.

주석으로 처리한 코드

주석으로 처리한 코드는 다른 사람이 지우기 애매해집니다. 다른 사람이 볼 때는 이유가 있어서 남겨 놓은 것이라고 생각할 수 있기 때문입니다. 마찬가지로 소스 코드 관리 시스템이 있기 때문에 코드를 주석으로 처리하기 보다는 삭제하는 게 낫습니다.

HTML 주석

Javadocs와 같은 도구로 주석을 뽑아 웹 페이지에 올릴 생각으로 HTML 주석을 삽입해야 한다면 이 책임은 프로그래머가 아니라 도구가 가지게 해야합니다.

전역 정보

주석을 달아야 한다면 근처에 있는 코드만 기술해야 합니다. 코드 일부에 주석을 달면서 연관되어 있는 다른 함수나 시스템의 정보를 기술하면 안됩니다.

다른 함수나 시스템의 정보가 변해도 해당 주석이 변한다는 보장이 없기 때문입니다.

너무 많은 정보

주석에다 흥미로운 역사나 관련 없는 정보를 장황하게 늘어놓으면 안됩니다.

모호한 관계

주석과 주석이 설명하는 코드 둘 사이의 관계는 명백해야 합니다. 주석 자체가 다시 설명이 필요한 주석이라면 잘못된 주석입니다.

함수 헤더

짧은 함수는 긴 설명이 필요 없습니다. 짧고 한 가지만 수행하며 이름을 잘 붙인 함수가 주석으로 헤더를 추가한 함수보다 훨씬 좋습니다.

비공개 코드에서 Javadocs

공개 API는 Javadocs가 유용하지만 공개하지 않을 코드나 시스템 내부에 속한 클래스와 함수에 굳이 Javadocs를 생성할 필요는 없습니다.

나의 생각

이 부분은 생각이 좀 다릅니다. 주석의 목적은 코드를 설명하는 것인데, 이 주석을 읽는 사람은 미래의 해당 코드 내용을 잊어버린 내가 될 수도 있기 때문에 코드로 바로 읽히지 않는 코드면 Javadocs를 달아주는 게 좋다고 생각합니다.

4-5. 4장을 마치며

저자는 주석을 일일이 다는 것 보다는 주석으로 밖에 설명할 수 없는 내용이 아니라면 함수명과 변수명을 이용해 잘 읽히는 코드를 작성하는 것을 중요하게 생각하는 것 같습니다.

저도 이 방식에 전적으로 동의하는 바이지만…

저와 제 동료들은 영어권 사람들이 아닙니다. 각자 다른 영어실력을 가지고 긴 함수명과 변수명들을 해석하게 되면 충분히 오해할 소지가 생긴다고 생각합니다.

때문에 영어로 확실히 표현되는 함수나 변수명이 아닌 이상은 오해할 소지가 없게 주석을 달고 신경써서 업데이트 해주는 것이 더 좋을 것 같다고 생각합니다.


참고 : Clean Code - 로버트 C. 마틴

댓글남기기