Comment 주석 - Comment juseog

일전에 애자일 개발에서의 문서화 작업에 대한 블로깅에서도 밝힌바와 같이 도큐멘테이션은 프로젝트의 목적(납품물)이 아닌 커뮤니케이션을 위한 수단이 되어야 한다. 올바른 문서화을 위한 원칙을 다시한번 간략히 살펴보자.

Comment 주석 - Comment juseog

정보의 중복 금지: 같은 내용을 여러군데 적지 말라. 쓸데없는 노력이 들어갈 뿐만 아니라 결국에는 서로 다른 내용을 지닌 문서/코드를 보게될 것이다. 

코드에 포함 가능한 정보는 코드에 포함하라: 동일한 내용이 여러 장소에 적힐 수 있다면 코드가 우선시 되어야 한다. 코드에 표현하기 어려운 정보라면 그 다음 순위는 유지모델이 될 것이다.

라이프 사이클을 구분하여 사용하라: 프로젝트 내내 지속적으로 유지해야만 하는 유지모델과 특정 단계에서만 구성원들의 의식 통일을 위해 사용하는 임시모델을 구분하여 사용한다. 아키텍처 정의나 ER다이어그램과 같은 문서는 프로젝트가 끝난 후라 할 지라도 유지보수를 위해 여전히 유용한 반면, 특정 기능 구현을 위한 시퀀스 다이어그램이나 클래스 다이어그램과 같은 임시 모델은 회의를 진행하면서 화이트보드에 적은 내용을 디지털사진으로 남기는 것 만으로도 충분한 경우가 많다. 

주석을 달지 말아야 하는 이유

코드에 주석을 달지 말아야 하는 이유는 정보의 중복을 피하기 위해서입니다. 주석을 열심히 달기 보다는 읽기쉬운 코드를 만든는데 집중하세요. 메소드 내의 처리를 단일 기능 단위로 분할 하고 하고 각종 네이밍에 주의를 기울이십시오. 프로그램 사양에 대한 기술은 코드의 주석보다는 테스트 케이스의 Javadoc에 기대하는 동작을 기술하세요. 이렇게 작성된 Javadoc은 그 자체로서 훌륭한 상세설계서가 됩니다. - 나가사토(나가사토씨는 필자와 같은 Mamezou소속의 애자일 컨설턴트 이며 Disciplined Agile의 일본어판 번역을 비롯해 다수의 기술서적을 번역하였다.)

필자는 사실 테스트케이스의 Javadoc조차도 최소한의 내용만을 적는것이 좋다고 생각한다. 테스트 코드도 실행코드와 마찬가지로 코드 자체의 가독성을 최대화 하는것에 집중하는것이 좋다고 생각하기 때문이다.

잘 작성된 주석은 프로그램의 가독성을 매우 향상시킬 수 있는 반면, 잘못 작성된 주석은 프로그램의 가독성을 해칠 수 있다. 

코드 컴플리트(스티브 맥코넬, 2005)

주석을 달지 않는 코딩 유형은 자바의 코어 라이브러리 소스 코드를 비롯해 대부분의 오픈소스 코드에서 쉽게 확인 할 수 있다.

예제1) 스프링 소스코드

     @Override  
     public void initialize(  
             Servlet servlet, ServletRequest request, ServletResponse response,  
             String errorPageURL, boolean needsSession, int bufferSize, boolean autoFlush) {  
         throw new UnsupportedOperationException("Use appropriate constructor");  
     }  
     @Override  
     public void release() {  
     }  
     @Override  
     public void setAttribute(String name, Object value) {  
         Assert.notNull(name, "Attribute name must not be null");  
         if (value != null) {  
             this.attributes.put(name, value);  
         }  
         else {  
             this.attributes.remove(name);  
         }  
     }  
     @Override  
     public void setAttribute(String name, Object value, int scope) {  
         Assert.notNull(name, "Attribute name must not be null");  
         switch (scope) {  
             case PAGE_SCOPE:  
                 setAttribute(name, value);  
                 break;  
             case REQUEST_SCOPE:  
                 this.request.setAttribute(name, value);  
                 break;  
             case SESSION_SCOPE:  
                 this.request.getSession().setAttribute(name, value);  
                 break;  
             case APPLICATION_SCOPE:  
                 this.servletContext.setAttribute(name, value);  
                 break;  
             default:  
                 throw new IllegalArgumentException("Invalid scope: " + scope);  
         }  
     }  

예제로 제시한 코드는 주석이 필요 없을정도로 간결하다. 이번엔 테스트코드를 살펴보자.

예제2) 테스트코드

 /**  
  * Unit tests for the {@code MockPageContext} class.  
  *  
  * @author Rick Evans  
  */  
 public final class MockPageContextTests extends TestCase {  
     public void testSetAttributeWithNoScopeUsesPageScope() throws Exception {  
         String key = "foo";  
         String value = "bar";  
         MockPageContext ctx = new MockPageContext();  
         ctx.setAttribute(key, value);  
         assertEquals(value, ctx.getAttribute(key, PageContext.PAGE_SCOPE));  
         assertNull(ctx.getAttribute(key, PageContext.APPLICATION_SCOPE));  
         assertNull(ctx.getAttribute(key, PageContext.REQUEST_SCOPE));  
         assertNull(ctx.getAttribute(key, PageContext.SESSION_SCOPE));  
     }  
     public void testRemoveAttributeWithNoScopeSpecifiedRemovesValueFromAllScopes() throws Exception {  
         String key = "foo";  
         String value = "bar";  
         MockPageContext ctx = new MockPageContext();  
         ctx.setAttribute(key, value, PageContext.APPLICATION_SCOPE);  
         ctx.removeAttribute(key);  
         assertNull(ctx.getAttribute(key, PageContext.PAGE_SCOPE));  
         assertNull(ctx.getAttribute(key, PageContext.APPLICATION_SCOPE));  
         assertNull(ctx.getAttribute(key, PageContext.REQUEST_SCOPE));  
         assertNull(ctx.getAttribute(key, PageContext.SESSION_SCOPE));  
     }  
 }  

테스트 코드 역시 매우 간결한 모습을 띄고 있다.
코드의 가독석을 높이는 가장 좋은 방법은 코드를 심플하게 유지 하면서 네이밍, 특히 변수의 네이밍에 신경을 써 주는것이 효과적이다.

변수명과 네이밍에 대한 내용은 코드 컴플리트에서 더할나위 없이 훌륭하게 다루어지고 있으므로 아직 읽어보지 않은 분이라면 꼭 읽어들 것을 추천한다.

이번 강의에서는

  • 주석에 대한 확실한 이해

Comment 주석 - Comment juseog

사실, 2 - 1강에서도 다룬 내용이지만 댓글을 통해 질문이 들어 왔기에 정확히 주석이란 놈이 무엇인지 알아 보도록 하겠습니다.

우리가 프로그래밍을 하다 보면 소스 코드가 상당히 길어 지게 됩니다. 우리가 앞서 한 Hello, World! 출력 예제는 소스 코드가 겨우 몇 줄에 불과하였지만 실제론 소스 코드의 길이가 수천 줄에서 수만 줄 가까히 됩니다. 예를 들어서 우리가 지금 사용하는 Windows XP 의 소스 코드가 몇 줄 정도 될 지 추측해 보세요. 한, 십만줄? 50만 줄? 아닙니다. 정확한 자료는 아니지만 대략 4000만 줄 이상 된다고 합니다.

이런 크기로 프로그램을 작성하다 보면 이 소스 코드가 무엇을 뜻하고 또 무슨 일을 하는지 등의 정보를 소스 코드 내에 나타내야 할 필요성이 있게 됩니다. 즉, 컴파일러가 완전히 무시하고 오직 사람의 편의를 위해서만 존재하는 것이 바로 주석 입니다.

종종 지금 코드를 쓰고 있는 시점에서 내용을 잘 안다고 주석을 생략하는 경우가 있습니다. 하지만 주석 없는 코드를 1 달 뒤에 다시 본다면 분명히 아니 이게 지금 뭐하는 코드지? 라고 생각하실 것입니다. 반면에 주석이 잘 작성되어 있는 코드는 몇 년 뒤에서 다시 읽는다 해도 (주석을 잘 달아놨다는 가정 하에) 쉽게 이해할 수 있습니다.

C 언어에서 주석은 두 가지 방법으로 넣을 수 있습니다.

/* 주석이 들어가는 부분 */

// 주석이 들어가는 부분

일단 전자의 경우 /**/ 로 묶인 내부의 모든 내용들이 주석으로 처리 됩니다. 즉,

/*

이 부분은 내가 아무리 생쇼를 해도 컴파일러가 무시
ㅁㄴㅇ러ㅏㅁ니ㅓㄹ먼리;ㅏㄴㅁ어림나러 무시
ㅁ아ㅓㄹ민럼ㄴㄹ ㅁㄴㅇ럼니러
ㅁㄴ라미너럼나러ㅣㅁ너라ㅣㅓㅇ
printf("Hello, World"); <- 이 것도 당연히 무시
*/

와 같이 난리를 쳐도 /**/ 로 묶인 부분은 무시됩니다. 아래 예제를 보면 이해가 더욱 잘 될 것입니다.

#include <stdio.h>
int main() {
  /*
  printf("Hello, World!\n");
  printf("Hi, Human \n");
  */
  printf("Hi, Computer \n");

  return 0;
}

위와 같은 소스코드를 컴파일 하였을 때,

실행 결과

Hi, Computer 

와 같이 Hi, Computer 을 출력하는 부분만 남을 것을 볼 수 있습니다. 이는 앞서 말했듯이 /**/ 로 묶인 부분이 전부다 주석으로 처리되어서 컴파일러가 철저하게 무시하였기 때문 입니다.

반면의 // 형태의 주석의 경우 // 가 쳐진 줄 만이 주석으로 처리가 됩니다. 즉,

// Hello, World! 를 출력한다.
printf("Hello, World!");

로 하면 아래 printf 부분 잘 실행됩니다. 하지만 위 주석은 역시 무시됩니다. 아래 예제를 보면 확실히 알 수 있습니다.

#include <stdio.h>
int main() {
  // printf("Hello, World!\n");
  printf("Hi, Human \n");
  printf("Hi, Computer \n");

  return 0;
}

성공적으로 컴파일 하였다면

실행 결과

Hi, Human 
Hi, Computer 

와 같이 주석으로 감싸진 부분을 제외하고는 나머지 부분이 잘 출력되었음을 알 수 있습니다.

뭘 배웠지?

항상 주석을 다는 습관을 기릅시다. 주석을 잘 달지 않는다면 나중에 자기가 쓴 코드도 못알아보게 됩니다.

강좌를 보다가 조금이라도 궁금한 것이나 이상한 점이 있다면 꼭 댓글을 남겨주시기 바랍니다. 그 외에도 강좌에 관련된 것이라면 어떠한 것도 질문해 주셔도 상관 없습니다. 생각해 볼 문제도 정 모르겠다면 댓글을 달아주세요.

현재 여러분이 보신 강좌는 <씹어먹는 C 언어 - <2 - 2. 주석(Comment)에 대한 이해>> 입니다. 이번 강좌의 모든 예제들의 코드를 보지 않고 짤 수준까지 강좌를 읽어 보시기 전까지 다음 강좌로 넘어가지 말아주세요