오늘 구현한 코드의 가독성은 앞으로 바뀔 코드의 품질에 지대한 영향을 끼친다. 오랜 시간이 지나 원래 코드의 흔적을 더 이상 찾아보기 어려울 정도로 코드가 바뀌어도 맨 처음 잡아놓은 구현 스타일과 가독성 수준은 유지보수 용이성과 확장성에 계속 영향을 끼친다.
독자는 위에서 아래로 기사를 읽는다.
최상단의 표제를 보고서 기사를 읽을지 말지 결정하고, 첫 문단은 전체 기사 내용을 요약한다.
쭉 읽으며 내려가면 세세한 사실이 조금씩 드러난다.
소스 코드도 신문 기사와 비슷하다.
이름은 간단하지만, 이름만 보고도 올바른 모듈을 살펴보고 있는지 아닌지를 판단할 정도로 신경 써서 짓는다.
소스 파일의 첫 부분은 고차원 개념과 알고리즘을 설명한다.
아래로 내려갈수록 의도를 세세하게 묘사하며, 마지막에는 가장 저차원 함수와 세부 내역이 나온다.
각 행은 수식이나 절을 나타내고, 일련의 행 묶음은 완결된 생각 하나를 표현한다. 생각 사이는 빈 행을 넣어 분리해야 마땅하다.
빈 행은 새로운 개념을 시작한다는 시각적 단서이다.
세로 밀집도는 연관성을 의미한다.
서로 밀접한 코드 행은 세로로 가까이 놓아야 한다는 뜻이다.
같은 파일에 속할 정도로 밀접한 두 개념은 세로 거리로 연관성을 표현한다.
여기서 연관성이란 한 개념을 이해하는 데에 다른 개념이 중요한 정도이다.
연관성이 깊은 두 개념이 멀리 떨어져 있으면 코드를 읽는 사람이 소스 파일과 클래스를 여기저기 뒤지게 된다.
변수는 사용하는 위치에서 최대한 가까이에 선언한다.
루프를 제어하는 변수는 흔히 루프 문 내부에 선언한다.
인스턴스 변수는 클래스 맨 처음에 선언한다. 변수 간에 세로로 거리를 두지 않는다.
프로그래밍 언어마다 위치에 대한 규칙이 다르지만, 공통점은 같다.
잘 알려진 위치에 인스턴스 변수를 모아 변수 선언을 어디서 찾을지 모두가 알고 있어야 한다는 것이다.
한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치한다.
가능하다면 호출하는 함수를 호출되는 함수보다 먼저 배치한다.
그러면 프로그램을 읽을 때 자연스럽게 읽힌다.
이러한 규칙을 일관적으로 적용하면 독자는 방금 호출한 함수가 잠시 후에 정의되리라는 사실을 예측한다.
public class WikiPageResponder implements SecureResponder {
protected WikiPage page;
protected PageData pageData;
protected String pageTitle;
protected Request request;
protected PageCrawler crawler;
public Response makeResponse(FitNesseContext context, Request request)
throws Exception {
String pageName = getPageNameOrDefault(request, "FrontPage");
loadPage(pageName, context);
if (page == null)
return notFoundResponse(context, request);
else
return makePageResponse(context);
}
private String getPageNameOrDefault(Request request, String defaultPageName)
{
String pageName = request.getResource();
if (StringUtil.isBlank(pageName))
pageName = defaultPageName;
return pageName;
}
protected void loadPage(String resource, FitNesseContext context)
throws Exception {
WikiPagePath path = PathParser.parse(resource);
crawler = context.root.getPageCrawler();
crawler.setDeadEndStrategy(new VirtualEnabledPageCrawler());
page = crawler.getPage(context.root, path);
if (page != null)
pageData = page.getData();
}
private Response notFoundResponse( ... ) throws Exception { ... }
private SimpleResponse makePageResponse( ... ) thorws Exception { ... }
...
}
개념적인 친화도가 높을수록 코드를 가까이 배치한다.
→ 행 길이는 최대 120자 정도로 제한하는 것이 적당하다.
private void measureLine(String line) {
lineCount++;
int lineSize = line.length();
totalChars += lineSize;
lineWidthHistogram.addLine(lineSize, lineCount);
recordWidestLine(lineSize);
}
공백을 넣으면 두 가지 주요 요소가 확실히 나뉜다는 사실이 명확해진다.
우리는 범위로 이뤄진 계층을 표현하기 위해 코드를 들여쓴다.
들여쓰는 정도는 계층에서 코드가 자리잡은 수준에 비례한다.
스타일은 일관적이고 매끄러워야 한다.
한 소스 파일에서 봤던 형식이 다른 소스 파일에도 쓰이리라는 신뢰감을 독자에게 줘야 한다.