728x90
반응형
▷ 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 |