수직거리
서로 밀접한 개념은 세로로 가까이 두어야 한다.
같은 파일에 속할 정도로 밀접한 두 개념은 세로 거리로 연관성을 표현한다.
여기서 말하는 연관성이란 한 개념을 이해하는데 다른 개념이 더 중요한 정도이다.
연관성이 깊은 두 개념이 멀리 떨어져 있으면 코드를 읽는 사람이 소스 파일과 클래스를 여기저기 뒤지게 된다.
변수 선언
변수는 사용하는 위치에 최대한 가까이 위치해야 한다
만들어낸 함수가 매우 짧을경우 지역 변수는 각 함수 맨 처음에 선언하는 것도 하나의 방법이겠다.
아래 코드는 JUnit 4.3.1에서 가져온 다소 긴 함수이다.
private static void readPreferences(){
InputStream is = null;
try{
is = new FileInputStream(getPreferencesFile());
setPreferences(new Properties(getPreferences()));
getPreferences().load(is);
} catch (IOException e){
try{
if(is != null)
is.close();
}catch(IOException e1){
}
}
}
루프 제어 변수는 흔히들 루프 문 내부에서 선언한다.
아래 코드 또한 JUnit 4.3.1에서 가져온 함수다.
public int countTestCase(){
int count = 0;
for (Test each: tests)
count += each.countTestCase();
return count;
}
드물지만 다소 긴 함수에서 블록 상단이나 루프 직전에 변수를 선언하는 사례도 있다.
아래 코드는 TestNG에서 가져온 코드이다.
for (XmlTest test: m_suite.getTests()){
TestRunner tr = m_runnerFactory.newTestRunner(this, test);
tr.addListener(m_textReporter);
m_testRunners.add(tr);
invoker =. r.getInvoker();
for (ITestNGMethod m : tr.getBeforeSuiteMethods()){
beforeSuiteMethods.put(m.getMethod(), m);
}
for (ITestNGMethod m : tr.getAfterSuiteMethods()){
afterSuiteMethods.put(m.getMethod(), m);
}
인스턴스 변수
반면 인스턴스 변수는 클래스 맨 처음에 선언해야 한다.
그리고 별도로 변수 간에 세로로 거리를 둘 필요 없다.
잘 설계한 클래스는 대다수 클래스 메서드가 인스턴스 변수를 사용하기 때문이다.
하지만 아직까지도 변수를 선언하는 위치에 대한 논쟁이 있으므로.. 팀원과 상의하여 편한 곳에 쓰도록 하자.
아래 코드는 JUnit 4.3.1에서 가져온 TestSuite 클래스로 코드가 특이하게 짜여 있다.
public class TestSuite implements Test{
static public Test createTest(Class<? extends TestCase> theClass, String name){
...
}
public static Constructor<? extends TestCase>
getTestConstructor(Class<? extends TestCase> theClass) throws NoSuchMethodException{
...
}
public static Test warning(final String message){
...
}
public static String exceptionToString(Throwable t){
...
}
private String fName;
private Vector<Test> fTests = new Vector<Test>(10);
public TestSuite(){
}
public TestSuite(final Class<? extends TestCase> theClass){
...
}
public TestSuite(Class<? extends TextCase> theClass, String name){
...
}
...
}
종속 함수
한 함수가 다른 함수를 호출하면 두 함수는 세로로 가까이 배치한다.
또한 가능하다면 호출하는 함수를 호출되는 함수보다 먼저 배치한다. 그러면 프로그램이 자연스럽게 읽힌다.
규칙을 일관적으로 적용한다면 코드를 읽는 독자는 방금 호출된 함수의 정의를 곧 볼 수 있다고 예측할 수 있다.
그러므로 호출되는 함수를 찾기 쉬워지며, 그만큼 모듈 전체의 가독성도 높아진다.
개념적 유사성
아래 함수들은 개념적인 친화도가 높다.
명칭을 정하는 명명법이 똑같고 기본 기능이 유사하고 심플하다.
서로가 서로를 호출하는 관계는 부차적인 요인이다.
종속적인 관계가 없더라도 가까지 배치할 수 있는 함수들이다.
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);
}
}
'클린 코드' 카테고리의 다른 글
[클린 코드] 객체와 자료구조(2) (0) | 2022.01.26 |
---|---|
[클린 코드] 객체와 자료구조(1) (0) | 2022.01.19 |
[클린 코드] 형식 맞추기(1) (0) | 2022.01.11 |
[클린 코드] 주석(2) (0) | 2022.01.05 |
[클린 코드] 주석(1) (0) | 2022.01.04 |