본문 바로가기

Programming/ETC

주석 (feat.Clean Code, 읽기 좋은 코드가 좋은 코드다)

반응형
서론

 


재밌게 읽었던 두 책(Clean Code, 읽기 좋은 코드가 좋은 코드다)에서 주석에 대해 조금은 상이한 의견을 말하고 있어
나는 주석에 대해 어떤 태도를 가지면 좋을지 정리를 해보고 싶어 남기는 기록

 

 

 

본론

 

 

Clean Code 

주석은 나쁜 코드를 보완하지 못한다.
코드에 주석을 추가하는 일반적인 이유는 코드 품질이 나쁘기 때문이다.
주석으로 설명하려고 애쓸 시간을 코드 품질 개선에 시간을 투자하라.
의도는 코드로 표현하라.

 

그럼에도 써야 한다면 아래와 같이 좋은 주석의 예시를 참고하자.

더보기
  • 법적인 주석 
// Copyright (C) 2021 by hyolog, All right reserved.
  • 결과를 경고하는 주석
// 여유 시간이 충분하지 않다면 실행하지 마십시오.
public void DoSomethingThatTakesALongTime
{
	..
}
  • TODO 주석 
  • 정보를 제공하는 주석
// 테스트 중인 Responder 인스턴스를 반환
protected abstract Responder responderInstance();
  • 의도를 설명하는 주석
// 스레드를 대량 생성하는 방법으로 경쟁 조건을 만든다.
for (int i = 0; i < 25000; i++)
{
	new Thread(widgetBuilderThread).start();
}​
  • 의미를 명료하게 밝히는 주석
// a == a
a.compareTo(a) == 0
  • 중요성을 강조하는 주석
 // 여기서 trim으로 시작공백을 제거함으로써 다른 문자열로 인식될 위험을 제거합니다.
 String listItemContent = match.group(3).trim();

 

아래는 주석의 대부분인 나쁜 주석의 예시이다.

더보기
  • 오해할 여지가 있는 주석
  • 함수나 변수로 표현할 수 있는 주석
  • HTML 주석
  • 모호한 관계를 나타내는 주석
  • 이제는 불필요한 주석 (feat. 버전관리시스템)
    • 이력을 기록하는 주석
    • 주석으로 처리한 코드
    • 공로를 돌리거나 저자를 표시하는 주석
  • 있으나 마나 한 주석
  • 주절거리는 주석
  • 같은 이야기를 중복하는 주석
  • 의무적으로 다는 주석
/// <param name="number">비교할 첫번째 숫자</param>
/// <param name="secondNumber">비교할 두번째 숫자</param>
public string Compare(int firstNumber, int secondNumber)
  • 위치를 표시하는 주석
///////////////// 초기화 시작 ///////////////////
  • 괄호에 다는 주석
  • 전역 정보 주석
  • 너무 많은 정보를 담은 주석

 

읽기 좋은 코드가 좋은 코드다 

주석의 목적은 코드를 읽는 사람이 코드를 작성한 사람만큼 코드를 잘 이해하게 돕는 데 있다.
코드를 작성할 때 우리 머릿속에는 많은 귀중한 정보가 있지만 다른 사람이 그 코드를 읽을 때 그러한 정보는 사라진다.

 

주석을 읽는 것은 실제 코드를 읽는 시간을 갉아먹고 화면의 일정 부분을 차지한다.
즉, 주석을 단다면 반드시 달아야 하는 이유도 있어야 한다.
아래 예시를 통해 가치 있는 주석과 그렇지 않은 주석을 구분해 달도록 해보자.

가치 있는 주석

// 접은글 기능에 버그가 있어 알수 없는 개행이 들어간다

더보기
  • 코드가 특정한 방식으로 작성된 이유를 설명해주는 주석(감독의 설명)
// 이 데이터에서 이진트리는 해시테이블보다 40%정도 빠르다.
  • 코드에 담긴 결함을 설명하는 주석 (TODO 등)
// TODO : 추후 JPEG 포맷말고 다른 포맷도 처리할 수 있어야 한다.
  • 어떤 상수가 특정한 값을 갖게 된 사연을 설명하는 주석
// 이 값은 프로세서수 * 2보다 크거나 같아야 한다.
public const CountOfThreads = 8;
  • 보통은 예상하지 못할 특이한 동작을 기록한 주석
  • 파일이나 클래스 수준에서 큰그림을 설명하는 주석
// 고객이 자신을 위해서 구입한 항목을 모두 찾는다.
Foreach (var customer in customers)
{
    Foreach (var sale in customer.sales)
    {
    	if (sale.recipient == customer_id)
        {
        	..

그렇지 않은 주석

더보기
  • 코드 자체에서 재빨리 도출될 수 있는 사실을 써놓은 주석
// 주어진 이름과 깊이를 이용해서 서브트리에 있는 노드를 찾는다.
public Node FindNodeInSubtree(Node subtree, string name, int depth);
  • 나쁜 네이밍을 보완하려고 쓰는 주석
// 해당 키를 위한 핸들을 놓아준다. 실제 레지스트리를 수정하지는 않는다.
void DeleteRegistry(int registryKey);
    • 함수명을 ReleaseRegistryHandle로 바꾸는것이 낫다.

 

 

 

결론

 

 

개인적으로 주석은 어느 정도 필요하다고 생각한다.

모든 것을 코드로 표현하기에 실제로 제법 많은 벽이 있을 수 있기 때문이다.
(할 수 있다면 코드로 표현하고 주석을 안 쓰는 것이 좋다고는 생각한다.)

더보기

예를 들어 외부 API를 사용한 개발을 하는 중 외부 API에서 금액에 대한 네이밍을 Gold, Money를 혼합해서 쓰고 있다고 가정해보자
한참을 헤매다 Gold와 Money가 같은 의미임을 알게 되었다.
이때 이 경험을 한 사람이 주석을 남겨두었다면 이후 다른 개발자(혹은 미래의 나)가 코드를 볼 때 이해하는데 시간을 절약할 수 있을 것이다.

 

개인적으로 잘 쓰고 있던 주석

  • 의도를 설명하는 주석
    • 좋은 네이밍과 잘 짜인 로직으로 충분히 설명할 수 있는 케이스가 많지만 그럼에도 복잡한 로직의 이해를 돕고자 간단히 의도를 남기는 주석
  • TODO 주석
    • A라는 작업 도중 B라는 개선점을 발견한 경우에도 작업 단위의 커밋을 위해 A, B 작업을 의도적으로 분리해서 하는데 A 작업이 길어질 경우 B를 깜박할 수 있다.
      이럴 때 TODO로 남겨둔다면 TODO List만 필요할 때 바로 확인 가능하다. (아래와 같이 Visual Studio [작업 목록] 창에서 TODO 주석으로 남겨진 이력들을 모아볼 수 있다.)

 

나쁘다곤 생각 안 했지만 정리하면서 생각이 바뀐 주석

  • 주절거리는 주석
    • 주절거리듯 써놓은 생각의 변화, 고민한 내용들을 보며 전 작업자의 작업 과정을 요약본으로 미리 보기 할 수 있다는 장점이 있어 나쁘다곤 생각 안 했지만 이 또한 어느 시점에서 썼는지 정확히 알 수 없어 정보보단 데이터에 가까운 주석이라는 생각이 들었고 이러한 내용들은 주석이 아닌 commit message에 남기거나 생각을 정리한 뒤 "의도를 설명하는 주석"으로 남기면 더 좋을 것 같다는 생각이다.

 

앞으로 써볼 주석

  • 결과를 경고하는 주석
    • 하루치만 불러와도 로딩에 몇십 분은 걸리는 작업이 있다고 가정해보자. 이런 특징 때문에 불러올 날짜를 설정할 때 범위가 너무 길면 경고 메시지를 띄우는데 리펙토링 목적으로 UI로직과 실제 불러오는 로직을 구분해두었다고 해보자. 이후 다른 작업자가 로직 부분 유닛 테스트를 위해 해당 함수만(UI로직의 경고를 보지 못한 채) 테스트 코드를 작성해 일주일치 데이터를 테스트 Run 했다면? 언제 끝날지 모르는 테스트를 하염없이 기다려야 할 수 있다. 이런 상황은 "결과를 경고하는 주석"이 있었다면 방지할 수 있을 것이다.

 

개발자마다 주석에 대한 견해 차이가 많이 있을 것 같다.

옳고 그름보단 어떤 게 보다 나은 방법일지 고민해보고 본인만의 기준을 정립해 나가는 것이 더 중요한 것 같다.

근거 있는 판단에 의해 기준을 가지고 주석을 달았다면 적어도 그 개발자는 일관성을 가지고 개발하는 개발자이다.

 

반응형