SW개발/개발이야기

명확하고 간결한 주석에 대하여 (feat. 읽기 좋은 코드가 좋은 코드다)

지난번 포스팅에 이어 주석에 관련된 책의 내용을 정리해보려고 합니다. 주석 역시 협업을 하다보면 필연적으로 작성하게 됩니다. 없는 것보다는 있는 것이 좋은 주석이지만 때로는 없는 것보다도 못한 존재가 되기도 합니다. 주석을 명확하고 간결하게 다는법을 알아봅시다.

 

지난 포스팅 https://leffept.tistory.com/412

 

좋은 변수명을 짓는 것에 대하여 (feat. 읽기 좋은 코드가 좋은 코드다)

개발자라면 늘 고민하게 되는 부분이 있습니다. 바로 "변수명, 함수명을 어떻게 지어야 할까?" 에 대한 이야기 입니다. 변수명을 짓는 것에 늘 고민이 많은 것은 사실이지만, 대부분은 습관에 의

leffept.tistory.com

 

명확하고 간결한 주석 달기

주석을 간결하게 하라

// 💥 불필요한 주석
// int는 CategoryType이다.
// 내부 페어의 첫 번째 float는 'score'다.
// 두 번째는 'weight'ek.
typedef hash_map<int, pair<float, float> > ScoreMap;

// 🌈 간략한 주석 
// CategoryType -> (score, weight)
typedef hash_map<int, pair<float, float> > ScoreMap;

위의 예시처럼 불필요한 주석은 코드를 읽는데 방해물이 될 뿐입니다. 파이썬의 경우에는 Type Hint를 활용하면 더 좋습니다.

 

모호한 대명사는 피하라

# Insert the data into the cache, but check if it's too big first.
# 데이터를 캐시에 넣어라. 하지만 그것이 너무 큰지 확인하라.

위의 예시에서 'it'은 데이터를 가리킬 수도 있고 캐시를 가리킬 수도 있습니다. 모호한 주석으로 인해 코드의 다른 라인을 살펴보게 되는 경우라면 주석을 작성할 필요가 있을까요? 

 

혼동의 여지가 생기지 않도록 대명사를 명사로 바꾸도록 합니다.

# If the data is small enough, insert it into the cache.
# 데이터가 충분히 작으면, 이를 캐시에 넣어라.

또한, 기존의 'it'을 완전히 명확하게 하기 위하여 문장도 고쳤습니다.

 

엉터리 문장을 다듬어라

# 💥 그럭저럭 괜찮은 주석
# 이 URL을 전에 이미 방문했는지에 따라서 다른 우선순위를 부여한다.

# 🌈 명확한 주석
# 전에 방문하지 않은 URL에 높은 우선순위를 부여하라.

웹 크롤러의 역할을 할 수 있는 곳에 달릴만한 내용입니다. 문장의 표현을 직접적으로 바꿈으로써 명확한 설명이 됩니다.

 

함수의 동작을 명확하게 설명하라

파일에 담긴 줄 수를 세는 함수를 작성하였다고 가정합니다.

# 이 파일에 담긴 줄 수를 반환한다.
def count_lines(filename):
    ...

위의 주석은 명확하지가 않습니다. '줄'을 정의하는 방법은 다음과 같이 여러 가지입니다.

  • ""(빈파일)은 줄 수가 0인가 1인가?
  • "hello"는 줄 수가 0인가 1인가?
  • "hello\n"은 줄 수 가 1인가 2인가?

줄에 대한 명확한 기준을 주석에 담아 수정해봅시다.

# 파일 안에 새 줄을 나타내는 바이트('\n')가 몇 개 있는지 센다.
def count_lines(filename):
    pass

위처럼 주석의 내용을 변경하여 함수의 의도를 명확하게 표현할 수 있습니다.

 

코너케이스를 설명해주는 입/출력 예를 사용하라

주석을 작성하는 데 잘 선택된 입/출력 예시는 정말 위력적입니다.

문자열의 일부를 제거하는 평범한 함수가 있다고 가정합니다.

# 입력된 'src'의 'chars'라는 접두사와 접미사를 제거한다.
def strip(src, chars):
    ...

위의 주석은 다음과 같은 질문에 답하지 않으므로 명확하지 않습니다.

  • chars가 제거되어야 하는 정확한 부분 문자열을 의미하는가? 아니면 특정한 순서가 정해지지 않은 문자의 집합을 의미하는가?
  • src의 끝에 chars가 여러 번 있으면 어떻게 되는가?

잘 선택된 입/출력 예시를 통해 주석을 변경해봅시다.

# 예: strip("abba/a/ba", "ab")은 "/a/"를 반환한다.
def strip(src, chars):
    ...

잘 설명된 예시가 strip 함수의 전체 기능을 보여줍니다. 다만 너무 간단한 입/출력 예시는 도움이 되지 않으므로 보다 복잡한 예시를 작성하도록 합니다.

 

코드의 의도를 명시하라

주석 달기는 코드를 작성하면서 생각했던 바를 나중에 코드를 읽는 사람에게 전달해주는 것입니다. 하지만 불행하게도 대다수의 주석은 새로운 정보 없이 그냥 코드가 수행하는 동작을 문자 그대로 설명하는데 그칩니다.

아래가 대표적인 예시입니다.

void DisplayProducts(list<Product> products) {
    products.sort(CompareProductByPrice);
    
    // 💥 코드의 묘사만 전달하는 주석
    // 리스트를 역순으로 반복한다.
    for (list<Product>::reverse_iterator it = products.rbegin(); it ! = products.rend();++it)
         DisplayPrice(it->price);
    ...
}

위의 주석은 바로 아래에 존재하는 코드의 묘사만 전달할 뿐입니다. 다음과 같이 더 좋은 주석으로 변경할 수 있습니다.

// 🌈 프로그램이 수행하는 동작을 개략적인 높은 수준에서 설명하는 주석
// 각 가격을 높은 값에서 낮은 값 순으로 나타낸다.
for (list<Product>::reverse_iterator it = products.rbegin(); it ! = products.rend();++it)
     DisplayPrice(it->price);

 

정보 축약형 단어를 사용하라

# 💥 널리 사용되는 특정한 어휘나 문구가 사용되지 않은 주석
""" 
주소값에서 불필요한 빈 칸을 제거한다. 그리고 "Avenue"를 "Ave."로 바꾸는 것과
같은 정리 작업을 수행한다. 이러한 과정으로 사실상 같지만 다르게 입력된
주소는 동일한 방식으로 정리된 값을 갖게 되어 동일한 주소를 가지는지를
값들을 서로 비교해서 확인할 수 있다.
"""

위와 같은 주석은 프로그래밍 경력이 좀 있다면 널리 사용되는 특정한 어휘나 문구로 변경할 수 있습니다.

# 🌈 널리 사용되는 문구나 관용구로 교체한 주석
"""
주소값을 표준화한다(불필요한 빈칸을 제거하고, "Avenue" -> "Ave." 등의 정리 작업을 수행한다.)
"""

길게 늘어지는 주석을 때때로 위와 같이 명확한 단어나 문구로 대체할 수 있습니다. 이를 잘 활용하는 것이 좋습니다.

 


이번에도 책을 읽으며 감명깊게 느꼈던 부분 중 하나인 주석 달기 파트에 대해서 포스팅 해보았습니다. 저 역시도 여태까지 쓴 주석에 많은 정보가 들어있지 않았던 것 같습니다. 프로그래밍 하면서 생각했던 부분들을 적어보고, 조금 더 많은 정보를 담을 수 있는 주석을 작성해볼 예정입니다.

 

해당 책에는 제가 소개한 두 파트 이외에도 정말 다양한 팁들이 많이 있습니다. 개발자라면 한번쯤 읽어보시면 많은 도움이 될 것 같습니다.

 

읽어주셔서 감사합니다 :)

 

728x90