인스턴스 변수를 선언하는 위치에 대한 논쟁이 분분하고, 프로그래밍 언어마다 선호되는 위치가 다르기도 하다. 결론은 "잘 알려진 위치에 인스턴스 변수를 모은다"는 사실이 중요하다. 변수 선언을 어디서 찾을지 모두가 알고 있어야 한다.
종속 함수. 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치한다. 또한 가능하다면 호출하는 함수를 호출되는 함수보다 먼저 배치한다. 규칙을 일관적으로 적용한다면 독자는 방금 호출한 함수가 잠시 후에 정의되리라는 사실을 예측한다. (104p)
개념적 유사성. 친화도가 높을수록 코드를 가까이 배치한다. (106p)
친화도가 높은 요인
1. 한 함수가 다른 함수를 호출해 생기는 직접적인 종속성
2. 변수와 그 변수를 사용하는 함수
3. 비슷한 동작을 수행하는 일군의 함수
일반적으로 함수 호출 종속성은 아래 방향으로 유지한다. 다시 말해, 호출되는 함수를 호출하는 함수보다 나중에 배치한다. 그러면 소스 코드 모듈이 고차원에서 저차원으로 자연스럽게 내려간다. (107p)
프로그래머는 명백하게 짧은 행을 선호한다. (107p)
가로로는 공백을 사용해 밀접한 개념과 느슨한 개념을 표현한다. (108p)
프로그래머는 이런 들여쓰기 체계에 크게 의존한다. 왼쪽으로 코드를 맞춰 코드가 속하는 범위를 시각적으로 표현한다. 그러면 이 범위에서 저 범위로 재빨리 이동하기 쉬워진다. (111p)
팀은 한 가지 규칙에 합의해야 한다. 그리고 모든 팀원은 그 규칙을 따라야 한다. (113p)
좋은 소프트웨어 시스템은 읽기 쉬운 문서로 이뤄진다는 사실을 기억하기바란다. (114p)
줄바꿈이 개념을 분리한다면 세로 밀집도는 연관성을 의미한다. 즉, 서로 밀집한 코드 행은 세로로 가까이 놓여야 한다는 뜻이다.
public class ReporterConfig {
/**
* 리포터 리스너의 클래스 이름
*/
private String m_className;
/**
* 리포터 리스너의 속성
*/
private List<Property> m_properties = new ArrayList<Property>();
public void addProperty(Property property) {
m_properties.add(property);
}
}
위의 코드는 의미 없는 주석으로 두 인스턴스 변수를 떨어뜨려 놓아서 코드가 한눈에 들어오지 않는다. 따라서 불필요한 주석은 삭제하는 것이 좋다. 연관성이 깊은 두 개념이 멀리 떨어져 있으면 코드를 읽는 사람이 소스 파일과 클래스를 여기저기 뒤지게 된다.
어떤 코드는 서로 끌어당긴다. 개념적인 친화도가 높기 때문이다. 친화도가 높을수록 코드를 가까이 배치한다.
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(String message, boolean condition) {
assertTrue(message, !condition);
}
static public void assertFalse(boolean condition) {
assertFalse(null, condition);
}
...
위 함수들은 개념적인 친화도가 매우 높다. 명명법이 똑같고 기본 기능이 유사하고 간단하다. 서로를 호출하는 관계는 부차적인 요인이다. 종속적인 관계가 없더라도 가까이 배치할 함수들이다.
가로로는 공백을 사용해 밀접한 개념과 느슨한 개념을 표현한다.
private void measureLine(String line) {
lineCount++;
int lineSize = line.length();
totalChars += lineSize;
lineWidthHistogram.addLine(lineSize, lineCount);
recordWidestLine(lineSize);
}