[클린 코드 (Clean Code)] Ch4. 주석

2021. 1. 22. 19:0004. Archives/독서

728x90
반응형

Ch4. 주석

나쁜 코드에 주석을 달지 마라. 새로 짜라.

  • 브라이언 W. 커니핸, P. J. 플라우거

  • 잘 달린 주석은 그 어떤 정보보다 유용하다. 경솔하고 근거 없는 주석은 코드를 이해하기 어렵게 만든다.

  • 사실상 주석은 기껏해야 필요악이다. 프로그래밍 언어 자체가 표현력이 풍부하다면, 아니 우리에게 프로그래밍 언어를 치밀하게 사용해 의도를 표현할 능력이 있다면, 주석은 거의 필요하지 않으리라. 아니, 전혀 필요하지 않으리라.

  • 우리는 코드로 의도를 표현하지 못해, 그러니까 실패를 만회하기 위해 주석을 사용한다.

  • 그러므로 주석이 필요한 상황에 처하면 곰곰이 생각하기 바란다. 상황을 역전해 코드로 의도를 표현할 방법은 없을까? 코드로 의도를 표현할 때마다 스스로를 칭찬해준다. 주석을 달 때마다 자신에게 표현력이 없다는 사실을 푸념해야 마땅하다.

  • 프로그래머들이 주석을 엄격하게 관리해야 한다고, 그래서 복구성과 관련성과 정확성이 언제나 높아야 한다고 주장할지도 모르겠다. 그 의견에 동의한다. 프로그래머들에게도 절도가 필요하다. 하지만 나라면 코드를 깔끔하게 정리하고 표현력을 강화하는 방향으로, 그래서 애초에 주석이 필요 없는 방향으로 에너지를 쏟겠다.

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

  • 코드에 주석을 추가하는 일반적인 이유는 코드 품질이 나쁘기 때문이다. 모듈을 짜고 보니 짜임새가 엉망이고 알아먹기 어렵다.

    주석을 달아야겠다는 생각말고 코드를 정리해야겠다는 생각을 해야한다.

  • 표현력이 풍부하고 깔끔하며 주석이 거의 없는 코드가, 복잡하고 어수선하며 주석이 많이 달린 코드보다 훨씬 좋다.

코드로 의도를 표현하라

  • 몇 초만 더 생각하면 코드로 대다수 의도를 표현할 수 있다. 많은 경우 주석으로 달려는 설명을 함수로 만들어 표현해도 충분하다.

      // 직원에게 복지 혜택을 받을 자격이 있는지 검사한다.
      if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))
    
      // vs //
    
      if (employee.isEligibleForFullBenefits())

좋은 주석

  • 어떤 주석은 필요하거나 유익하다

    • 법적인 주석

      • 각 소스 파일 첫머리에 주석으로 들어가는 저작권 정보와 소유권 정보는 필요하고도 타당함

          // Copyright (C) ~~~~ . All rights reserved.
    • 정보를 제공하는 주석

      • 때로는 기본적인 정보를 주석으로 제공하면 편하다.
    • 의도를 설명하는 주석

      • 때때로 주석은 구현을 이해하게 도와주는 선을 넘어 결정에 깔린 의도까지 설명함
    • 의미를 명료하게 밝히는 주석

      • 때로는 모호한 인수나 반환값은 그 의미를 읽기 좋게 표현하면 이해하기 쉬워짐
      • 일반적으로 인수나 반환값 자체를 명확하게 만들면 더 좋겠지만, 인수나 반환값이 표준 라이브러리나 변경하지 못하는 코드에 속한다면 의미를 명료하게 밝히는 주석이 유용함
    • 결과를 경고하는 주석

      • 때로 다른 프로그래머에게 결과를 경고할 목적으로 주석을 사용

          // 여유 시간이 충분하지 않다면 실행하지 마십시오.
          public void_testWithReallyBifFile(){
              ...
          }
        
          public static SimpleDataFormat makeStandardHttpDateFormat()
          {
              // SimpleDataFormat은 스레드에 안전하지 못하다.
              // 따라서 각 인스턴스를 독립적으로 생성해야 한다.
              SimpleDataFormat df = ~~~
              ...
              ...
          }
    • TODO 주석

      • 때로는 '앞으로 할 일'을 // TODO 주석으로 남겨두면 편함

        • 함수를 구현하지 않은 이유와 미래 모습을 // TODO 주석으로 설명할 수 있다.

        • 이는 프로그래머가 필요하다 여기지만 당장 구현하기 어려운 업무를 기술함

            // TODO-Mdm 현재 필요하지 않다.
            // 체크아웃 모델을 도입하면 함수가 필요 없다.
            protected VersionInfo makeVersion() throws Exception
            {
                return null;
            }
    • 중요성을 강조하는 주석

      • 자칫 대수롭지 않다고 여겨질 뭔가의 중요성을 강조하기 위해서도 주석을 사용함

          String listItemContent = match.group(3).trim();
          // 여기서 trim은 정말 중요하다. trim 함수는 문자열에서 시작 공백을 제거한다.
          // 문자열에 시작 공백이 있으면 다른 문자열로 인식되기 때문이다.
          new ListItemWidget(this, listItemContent. this.level + 1);
          return buildList(text.substring(match.end()));

나쁜 주석

  • 대다수 주석이 이 범주에 속한다.

  • 일반적으로 대다수 주석은 허술한 코드를 지탱하거나, 엉성한 코드를 변명하거나, 미숙한 결정을 합리화하는 등 프로그래머가 주절거리는 독백에서 크게 벗어나지 못한다.

  • 주절거리는 주석

    • 특별한 이유 없이 의무감으로 혹은 프로세스에서 하라고 하니까 마지못해 주석을 단다면 전적으로 시간낭비다. 주석을 달기로 결정했다면 충분한 시간을 들여 최고의 주석을 달도록 노력한다.
  • 같은 이야기를 중복하는 주석

    • 헤더에 달린 주석이 같은 코드 내용을 그대로 중복하는 경우

        public abstract class ContainerBase
            implements Container, LifeCycle, Pipeline,
            MBeanRegistration, Serializable{
      
            /**
             * 이 컴포넌트의 프로세서 지연값
             */
            protected int backgroundProcessorDelay = -1;
      
            /**
             * 이 컴포넌트를 위한 컨테이너 이벤트 Listener
             */
            protected ArrayList listeners = new ArrayList();    
      
            /**
             * 컨테이너와 관련된 Logger 구현
             */
            protected Log logger = null;
      
            ...
        }
  • 오해할 여지가 있는 주석

  • 의무적으로 다는 주석

    • 모든 함수나 모든 변수에 주석을 달아야 한다는 규칙은 어리석기 그지 없다.

    • 이런 주석은 코드를 복잡하게 만든다.

        /**
         *
         * @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);
        }
  • 이력을 기록하는 주석

    • 때때로 사람들은 모듈을 편집할 때마다 모듈 첫머리에 주석을 추가한다.
    • 예전에는 모든 모듈 첫머리에 변경 이력을 기록하고 관리하는 관례가 바람직했다. 당시에는 소스코드 관리 시스템이 없었으니까.
    • 하지만 이제는 혼란만 가중할 뿐이다. 완전히 제거하는 편이 좋다.
  • 있으나 마나 한 주석

    • 너무 당연한 사실을 언급하며 새로운 정보를 제공하지 못하는 주석이다.

        // 기본 생성자
        protected AnnualDateRule(){
      
        }
      
        // 월 중 일자
        private int dayOfMonth:
    • 있으나 마나 한 주석을 달려는 유혹에서 벗어나 코드를 정리하라. 더 낫고 행복한 프로그래머가 되는 지름길이다.

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

      // 전역 목록 <smodule>에 속하는 모듈이 우리가 속한 하위 시스템에 존재하는가?
      if (smodule.getDeependSubsystems().contains(subSysMod.getSubSystem()))
    
      // vs //
    
      ArrayList moduleDependees = smodule.getDependSubsystems();
      String ourSubSystem = subSysMod.getSubSystem();
      if (moduleDependees.contatins(outSubSystem))
  • 위치를 표시하는 주석

    • 특정 위치를 표시하려 주석을 사용한다.
    • 특정 기능을 모아놓으면 유요한 경우도 있지만, 반드시 필요할 때만, 아주 드물게 사용하는 편이 좋다.
  • 공로를 돌리거나 저자를 표시하는 주석

      /* 릭이 추가함 */
    • 소스 코드 관리 시스템은 누가 언제 무엇을 추가했는지 귀신처럼 기억한다.
    • 위와 같은 정보는 소스 코드 관리 시스템에 저장하는 편이 좋다.
  • 주석으로 처리한 코드

    • 소스 코드 관리 시스템이 우리를 대신해 코드를 기억해준다.
    • 이제는 주석으로 처리할 필요가 없다. 그냥 코드를 삭제하라.
반응형