본문으로 바로가기

[CleanCode]4, 5장 주석 / 형식 맞추기

category BackEnd/CleanCode 2022. 8. 15. 14:23
728x90
반응형

CleanCode - 로버트 C.마틴

 

▷ 4. 주석

들어가며

  • 잘 달린 주석은 그 어떤 정보보다 유용하다. 하지만 근거 없고 경솔한 주석은 코드를 이해하기 어렵게 만든다.
  • 우리는 코드로 의도를 표현하지 못해, 즉 실패를 만회하기 위해 주석을 사용한다.
  • 주석은 오래될수록 코드에서 멀어진다. 주석을 유지보수하기란 현실적으로 쉽지 않다.

코드로 의도를 표현하라.

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

if (employee.isEligibleForFullBenefits()) {}
  • 몇 초만 더 생각하면 아래 코드처럼 의도를 명확하게 드러낼 수 있다.

좋은 주석

  • 법적인 주석
  • 결과를 경고하는 주석 - 아래 코드는 정적 초기화 함수를 사용하려면 프로그래머가 주석을 보고 실수를 면할 수 있다.
public static SimpleDateFormat makeStandardHttpDateFormat() {
    // SimpleDateFormat은 스레드에 안전하지 못하다.
    // 따라서 각 인스턴스를 독립적으로 생성해야 한다.
    SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
    df.setTimeZone(TimeZone.getTimeZone("GMT"));
    return df;
}
  • TODO 주석

나쁜 주석

  • 주절거리는 주석
  • 같은 이야길 반복하는 주석
  • 오해의 여지가 있는 주석
  • 의무적으로 다는 주석 - 모든 함수에 javadocs를 달거나 모든 변수에 주석을 달아야한다는 규칙
  • 닫는 괄호에 다는 주석
  • 주석으로 처리한 코드
  • HTML 주석

좋은 주석을 사용한 소스

/**
 * 이 클래스는 사용자가 지정한 최대 값까지 소수를 구한다.
 * 알고리즘은 에라스토테네스의 체이다.
 * 2에서 시작하는 정수 배열을 대상으로 작업한다.
 * 처음으로 남아 있는 정수를 찾아 배수를 모두 제거한다.
 * 배열에 더 이상 배수가 없을 때까지 반복한다.
 */
public class PrimeGenerator {
    private static boolean[] crossedOut;
    private static int[] result;

    public static int[] generatePrimes(int maxValue) {
        if (maxValue < 2) {
            return new int[0];
        } else {
            uncrossIntegersUpTo(maxValue);
            crossOutMultiples();
            putUncrossedIntegerIntoResult();
            return result;
        }
    }

    private static void uncrossIntegersUpTo(int maxValue) {
        crossedOut = new boolean[maxValue + 1];
        for (int i = 2; i < crossedOut.length; i++) {
            crossedOut[i] = false;
        }
    }

    private static void crossOutMultiples() {
        int limit = determineIterationLimit();
        for (int i = 2; i <= limit; i++) {
            if (notCrossed(i)) {
                crossOutMultiplesOf(i);
            }
        }
    }

    private static int determineIterationLimit() {
        // 배열에 있는 모든 배수는 배열 크기의 제곱근보다 작은 소수의 인수이다.
        // 따라서 이 제곱근보다 더 큰 숫자의 배수는 제거할 필요가 없다.
        double iterationLimit = Math.sqrt(crossedOut.length);
        return (int) iterationLimit;
    }

    private static void crossOutMultiplesOf(int i) {
        for (int multiple = 2 * i; multiple < crossedOut.length; multiple += i) {
            crossedOut[multiple] = true;
        }
    }

    private static boolean notCrossed(int i) {
        return crossedOut[i] == false;
    }

    private static void putUncrossedIntegerIntoResult() {
        result = new int[numberOfUncrossedIntegers()];
        for (int j = 0, i = 2; i < crossedOut.length; i++) {
            if (notCrossed(i)) {
                result[j++] = i;
            }
        }
    }

    private static int numberOfUncrossedIntegers() {
        int count = 0;
        for (int i = 2; i < crossedOut.length; i++) {
            if (notCrossed(i)) {
                count++;
            }
        }
        return count;
    }

    public static void main(String[] args) {
        int[] resultArr = generatePrimes(10);
        for (int each : resultArr) {
            System.out.println(each);
        }
    }
}
  • 첫 번째 주석은 알고리즘 자체를 이해하기 쉽도록 만들어 준다.
  • 두 번째 주석은 루프 한계값으로 제곱근을 사용한 이유를 설명한다.

▷ 5. 형식 맞추기

형식을 맞추는 목적

  • 코드 형식은 의사소통의 일환이며 의사소통은 전문 개발자의 일차적인 의무이다. 때문에 매우 중요하다.

적절한 행 길이를 유지하라

  • JUnit, FitNesse, Time and Money 등의 프로젝트는 500줄이 넘어가는 파일이 없으며 대부분 200줄 미만이다.
  • 작은 파일들을 통해서 커다란 시스템을 구축할 수 있다.

신문기사처럼 작성하라

  • 독자는 위에서 아래로 기사를 읽는다. 최상단에 기사를 몇 마디로 요약하는 표제가 나온다.
  • 소스 파일도 비슷하다. 소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명한다. 아래로 내려갈수록 세세하게, 마지막에는 가장 저차원 함수와 세부내역이 나온다.

세로 밀집도

  • 서로 밀접한 코드 행은 세로로 가까이 놓아야 한다.

수직 거리

  • 지역 변수는 각 함수 맨 처음에 선언한다.
  • 인스턴스 변수는 클래스 맨 처음에 선언한다.
반응형

'BackEnd > CleanCode' 카테고리의 다른 글

[CleanCode]6장 객체와 자료구조  (1) 2022.08.19
[CleanCode]3장 함수  (0) 2022.08.02
[CleanCode]1, 2장 깨끗한 코드 / 의미있는 이름  (0) 2022.08.01