Clean Code_5장. 형식 맞추기
#노마드코더 #북클럽 #노개북
TIL (Today I Learned)
코드의 가독성을 올리기 위해서 어떤 방법과 규칙을 사용해야 하는지 배웠다.
오늘 읽은 범위
5장. 형식 맞추기
책에서 기억하고 싶은 내용을 써보세요.
코드 형식은 의사소통의 일환이다. 의사 소통은 전문 개발자의 일차적인 의무다.
적절한 행 길이를 유지하라
파일 크기는 어느 정도가 적당할까?
통계에 따르면 대부분 200줄 정도인 파일로도 커다란 시스템을 구축할 수 있다.
몇 줄 미만으로 작성하라는 엄격한 규칙은 없지만 일반적으로 큰 파일보다 작은 파일이 이해하기 쉽다.
신문 기사처럼 작성하라
잘 쓰여진 신문을 떠올려보자.
- 독자는 위에서 아래로 기사를 읽는다
- 최상단에 기사를 몇 마디로 요약하는 표제가 나온다
- 독자는 표제를 보고서 기사를 읽을지 말지 결정한다
- 첫 문단은 전체 기사 내용을 요약한다
- 세세한 사실은 숨기고 커다란 그림을 보여준다
- 쭉 읽으며 내려가면 세세한 사실이 조금씩 드러난다
- 날짜, 이름, 발언, 주장, 기타 세부 사항
소스 파일과 신문 기사를 비교해보자.
- 이름은 간단하면서도 설명이 가능하게 짓는다
- 이름만 보고도 올바른 모듈을 살펴보고 있는지 아닌지를 판단할 정도로 신경 써서 짓는다
- 소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명한다
- 아래로 내려갈수록 의도를 세세하게 묘사한다.
- 마지막에는 가장 저차원 함수와 세부 내역이 나온다
개념은 빈 행으로 분리하라
줄바꿈은 개념을 분리한다.
세로 밀집도
- 서로 밀접한 코드 행은 세로로 가까이 놓아야 한다
- 변수는 사용하는 위치에 최대한 가까이 선언한다
- 인스턴스 변수는 클래스 맨 처음에 선언한다
- C++은 인스턴스 변수를 마지막에 선언하는 관습이 있는데, 맨 처음이든 마지막이든 잘 알려진 위치에 인스턴스 변수를 모아야 한다
- 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치한다
- 가능하다면 호출하는 함수를 호출되는 함수보다 먼저 배치한다
-
친화도가 높은 코드는 가까이 배치한다
- 한 함수가 다른 함수를 호출해 생기는 직접적인 종속성
- 변수와 그 변수를 사용하는 함수
- 비슷한 동작을 수행하는 일군의 함수
public class Assert { static public void assertTrue(String message, boolean condition) { if (!condition) fail(message); } static public void assertTrue(boolean condition) { assertTrue(null, condition); } static public void assertFalse(boolean condition) { assertFalse(null, condition); } // ... }
세로 순서
-
일반적으로 함수 호출 종속성은 아래 방향으로 유지한다
-
호출되는 함수를 호출하는 함수보다 나중에 배치한다
단, 파스칼/C/C++에서 함수를 호출하려면 먼저 정의하거나 미리 선언해야 한다
-
-
가장 중요한 개념을 가장 먼저 표현한다
- 중요한 개념을 표현할 때는 세세한 사항을 최대한 베재한다
- 세세한 사항은 가장 마지막에 표현한다
가로 형식 맞추기
통계에 따르면 프로그래머는 짧은 행을 선호한다. 저자는 120자 이하의 행을 선호한다.
가로 공백과 밀집도
공백을 사용해 밀접한 개념과 느슨한 개념을 표현한다.
예제1
private void measureLine(String line) { // 함수와 인수는 서로 밀접하기에 공백 미사용
lineCount++;
int lineSize = line.length(); // 할당 연산자를 강조하기 위해 공백 사용
totalChars += lineSize;
lineWidthHistogram.addLine(lineSize, lineCount); // 쉼표를 강조해 인수가 별개라는 사실을 표현
recordWidestLine(lineSize);
}
예제2
public class Quadratic {
public static double root1(double a, double b, double c) {
double determinant = determinant(a, b, c);
return (-b + Math.sqrt(determinant)) / (2*a);
}
public static double root2(int a, int b, int c) {
double determinant = determinant(a, b, c);
return (-b - Math.sqrt(determinant) / (2*a));
}
private static double determinant(double a, double b, double c) {
return b*b - 4*a*c;
}
}
연산자 우선순위를 공백으로 표현했다.
가로 정렬
어셈블리에서 주로 위와 같은 가로 정렬을 사용했지만 별로 유용하지 못하다.
변수 타입은 무시하고, 변수 이름부터 읽게 되는 등 엉뚱한 부분이 강조된다.
들여쓰기
- 우리는 범위로 이뤄진 계층을 표현하기 위해 코드를 들여 쓴다
- 들여 쓰는 정도는 계층에서 코드가 자리 잡은 수준에 비례한다
- 클래스 정의처럼 파일 수준인 문장은 들여 쓰지 않는다
- 클래스 내 메서드는 클래스보다 한 수준 들여 쓴다
- 메서드 코드는 메서드 선언보다 한 수준 들여 쓴다
- 블록 코드는 블록을 포함하는 코드보다 한 수준 들여 쓴다
가짜 범위
가끔 빈 while문이나 for문이 존재하는 경우가 있다.
이 경우 세미콜론(;)은 새 행에 넣는다.
while (dis.read(buf, 0, readBufferSize) != -1)
;
팀 규칙
- 팀은 한 가지 규칙에 합의해야 한다
- 모든 팀원은 그 규칙을 따라야 한다
- 어디에 괄호를 넣을지
- 들여쓰기는 몇 자로 할 지
- 클래스와 변수와 메서드 이름은 어떻게 지을지…
- 정한 규칙은 IDE 코드 형식기로 설정한다
오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요
이번 챕터에서는 코드를 예쁘게 작성하는 방법을 배운 것 같다.
띄어쓰기를 잘 하거나 줄을 잘 분리하거나 관련된 개념을 한 곳으로 모으는 등의 작업은 컴퓨터 입장에서는 딱히 의미 있는 행동은 아니다. 그러나 사람들이 서로 협업하며 코드를 작성하는 데에 있어서는 아주 의미 있는 작업이다.
나 역시 코드를 딱 봤을 때 눈에 잘 들어오도록 비슷한 내용을 모으고, 빈 줄로 구분하고, 공백을 잘 활용하는 편이다.
가끔 프로젝트를 하다 보면 그렇지 못한 코드를 작성하는 팀원의 코드를 보면 답답함이 느껴진다.
궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.
위 두 코드는 세로밀집도에 대한 설명으로 등장한 두 예제이다. 5-3 예제보다 5-4 예제가 세로 밀집도가 더 좋다는 내용을 설명한 부분이다.
그러나 위의 예제가 코드 간의 밀접함을 설명하는 예제로 적절한지 의문이다. 저자는 단순히 주석으로 공간을 띄워놨을 뿐이다.
내 생각에는 밀집도에 관련된 설명을 하려면 중간에 얼마나 띄어져 있는가가 아닌 메서드의 내용이 비슷한 것끼리 묶어 놓은 예제와 그렇지 못한 예제를 보여주는 것이 더 좋은 설명이 되지 않았을까 하는 생각이 든다.