Search
Duplicate

4장 주석

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

개인적 감상평

주절거리는 주석은 작성하지 말자
코드의 문제와 헛점을 주석으로 가리려 하지 말자.
부정확한 주석은 독자를 현혹하고 오도한다.
지금까지 항상 내 코드를 다른사람이 보고 편하게 사용하라고, 이거 내가만든거라고 주석을 길게 작성했다. 누가 만든거거 왜만든거고 어떻게 돌아가고 어떤 파라미터가 어떤 형태인지까지..
심지어 로직의 플로우까지 case 별로 작성하기도 했다. 그리고 그런 내가 꼼꼼하다고 생각을 했었다.
하지만, 책에서는 내 의도를 코드로 설명하지 못해 주석으로 설명한다는 것 자체가 코드가 문제가 있다는 점이라는것을 지적한다.
개발자로써 내가 하고싶은 말은 코드로써만 풀어 나가야하며 코드로 풀 수 없는 내 의도나 정보들에 대해서만 주석을 작성할 수 있도록 하자.

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

: 주석이 길어질수록 자신의 코드가 알아먹기 힘들다는것을 말해주는 것 밖에 되지 않는다.
주석이 길어진다 싶으면 코드를 새로 리팩토링하거나 짜는게 맞지않나 고려하자.

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

서술형의 긴 주석은 충분히 코드로 표현할 수 있다.

3. 좋은 주석

법적인 주석
: 몇몇 회사는 법적인 이유로 특정 주석을 넣으라 명시하는데 소스 첫머리에 저작권&소유권 정보를 주석으로 남긴다.
// Copyright (C) 2003 ,2004 ,2005 by Object Mentor, Inc. All rights reserved. // GNU General Public License 버전 2 이상을 따르는 조건으로 배포한다.
Java
복사
정보를 제공하는 주석
:기본적인 정보를 주석으로 제공하면 편리하다
//테스트 중인 Responder 인스턴스를 반환한다. protected abstract Responder responderInstance();
Java
복사
하지만, 함수 이름에 정보를 담을 수 있다면 함수로 의미를 전달하면 더 좋다.
protected abstract Responder responderBeingTested();
Java
복사
의도를 설명하는 주석
: 구현을 이해하게 도와주는걸 넘어 로직에 깔린 의도까지 설명할 수 있다.
public int compareTo(Object o){ if(o instanceof WikiPagePath){ WikiPagepath p = (WikiPagePath) o; String compressedName = StringUtil.join(names, ""); String complssedArgumentName = StringUtil.join(p.names, ""); return compressedName.compareTo(compressedArgumentName); } return 1;//오른쪽 유형이므로 정렬 순위가 더 높다. }
Java
복사
의미를 명료하게 밝히는 주석
: 인수나 반환값이 표준 라이브러리나 변경하지 못하하는 코드에 속하면 의미를 명료하게 밝히는 주석이 유용하다.
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 }
Java
복사
⇒ 주석이 잘 못된 주석일 위험은 항상 내포하기에 더 나은 방법이 없는지 항상 고려하라.
결과를 경로하는 주석
: 다른 프로그래머에게 결과를 경고할 목적으로 주석을 사용한다.
//여유 시간이 충분하지 않다면 실행하지 마십시오. public void _testWithReallyBigFile(){ ... } public static SimpleDateFormat makeStandardHttpDateFormat(){ //SimpleDateFormat은 스레드에 안전하지 못하다. //따라서 각 인스턴스를 독립적으로 생성해야 한다. SimpleDateFormat df = new SImpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z"); df.setTimeZone(TimeZone.getTImeZone("GMT")); return df; }
Java
복사
TODO 주석
: '앞으로 할 일'을 TODO 주석으로 남겨두면 편하다.
//TODO 현재 기본 전략만 반환하고 있다. //기획팀과 비즈니스로직 성립시 신규 전략 추가가 필요하다. public Strategy makeStrategy() throws Exception { return new DefaultStrategy(); }
Java
복사
중요성을 강조하는 주석
: 독자가 대수롭지 않게 여길 만하지만 중요성을 강조하기 위해 사용한다.
String listltemContent = match.group(3).trim(); // 여기서 trim온 정말 중요하다. trim 합수는 문자열에서 시작 공백을 제거한다. // 문자열에 시작 공백이 있으면 다른 문지열로 인식되기 때문이다. new ListltemWidget(this, listltemContent, this.level + 1); return buildList(text.substring(match.end()));
Java
복사

4. 나쁜 주석

주절거리는 주석
: 답을 알아내기위해 다른 코드를 봐야하거나 그냥 혼잣말하듯이 주절거리는 주석은 안하니만 못하다.
public void loadProperties() { try{ String propertiesPath = propertiesLocation + "/" + PROPERTIESJILE; FilelnputStream propertiesStream = new FilelnputStream(propertiesPath); loadedProperties. load(propertiesStream); }catch(IOException e){ // 속성 파일이 없다연 기본강올 모두 메모러로 읽어 들였다는 의미다. } }
Java
복사
⇒ IOException이 발생했기에 속성 파일이 없다는 것은 알 수 있지만 이걸 언제 읽어들이고 누가 불러들이는지 주석만 봐서는 알 수 없다. 독자와 소통하지 못하는 주석이다.
같은 이야기를 중복하는 주석
// this.closed가 true일 때 반환되는 유틸리티 메서드다. // 타입아웃에 도달하면 예외를 던진다. public synchronized void waitForClose(final long timeoutMiHis) throws Exception { if( !closed) { wait(timeoutMillis); if(!closed) throw new Exception ("MockResponseSender could not be closed"); } }
Java
복사
⇒ 주석이 같은 이야기를 반복한다.
오해할 여지가 있는 주석
: 주석의 내용이 독자에게 오해를 사게끔 모호해서는 안된다.
// this.closed가 true일 때 반환되는 유틸리티 메서드다. // 타입아웃에 도달하면 예외를 던진다. public synchronized void waitForClose(final long timeoutMiHis) throws Exception { if( !closed) { wait(timeoutMillis); if(!closed) throw new Exception ("MockResponseSender could not be closed"); } }
Java
복사
⇒ 이 코드에서 주석의 내용은 this.closedtrue로 변하는 순간에 반환한다고 하지만 실제로 코드를 보면 그 순간 반환되는게아닌this.closedtrue여야 메소드는 반환된다.
의무적으로 다는 주석
: 누가봐도 다 알 수 있는 내용을 일관성을 유지한다는 미명하에 모든 메소드와 인수에 대해 주석을 다는것은 오히려 코드만 헷갈리게 하며 요구사항 변경으로 메소드변경이 잦을수록 주석과의 괴리감이 커져 불필요해 질 뿐이다.
이력을 기록하는 주석
: 이제는 git이나 svn등 훌륭한 형상관리툴이 있어 모든 이력을 관리하기 때문에 주석을 없애는게 좋다.
무의미한 주석
: 너무나 당연한 내용들을 언급하는 주석들은 없는게 낫다.
//기본 생성자. protected AnnualDateRule(){...}
Java
복사
위치를 표시하는 주석
: 간혹 특정 배너아래 기능들을 모아놓으면 유용한 경우도있지만 대부분 가독성만 낮춘다.
닫는 괄호에 다는 주석
: 조건문이나 반복문으로 블럭이 중첩될수록 닫는 괄호에 //end of while 과 같이 특수한 주석을 달아놓을 수 있지만 이건 좋은 주석이 아니라 코드의 추상화가 부족한 것이다. 괄호가 많아 주석을 달아야겠다면 주석을 다는 대신 추상화를 높혀보자.
주석으로 처리한 코드
:이유가 있어 남겨놓았을거라 추측하며 남겨두게되면서 비슷한 주석 코드들이 쌓여갈 수 있다.
HTML 주석
: 최악의 주석. 편집기/IDE에서조차 읽기 힘들다.
전역 정보
: 코드 일부에 주석을 달면서 시스템의 전반적인 정보(ex: 포트번호)를 기술하지 마라. 코드 일부로는 전역정보를 제어할 수 없기에 다른 어딘가에 있는 전역정보가 변경되더라도 알 수 없고 코드가 변해도 주석이 변하지 않는다.
너무 많은 정보
: 주석에 정보를 너무 많이 담는것은 독자에게 불필요하며 불가사의할 뿐이다.
모호한 관계
: 주석과 주석이 설명하는 코드는 둘 사이가 명확해야 한다. 주석을 보면서 또 해석을 요구하는 상황이 벌어진다면 그것은 나쁜 주석이다.
비공개 코드에서 Javadocs
: 공개 API는 Javadocs가 유용하지만 비공개 코드에서 Javadocs는 불필요하다.