함수는 작을수록 좋다.
첫째 규칙은 '작게!', 둘째 규칙은 '더 작게!'다.
if 문, else 문, while 문 등에 들어가는 블록은 한 줄이면 좋다. (대부분 한 줄은 함수 호출)
바깥을 감싸는 함수가 작아질 뿐 아니라, 호출하는 함수의 이름을 적절히 지으면 코드를 이해하기 쉬워진다.
중첩 구조가 생길만큼 함수가 커져서는 안 된다. 들여쓰기 수준은 1단, 2단을 넘어서면 안 된다.
함수는 다음을 지켜야한다.
함수가 여러 단계를 처리하는지 확인해보자. 만약 여러 단계를 처리한다면 여러 작업을 한다는 것이다.
높은 추상화 수준 : 어떤 것과 연관되어 있는지 알기 힘들다.
낮은 추상화 수준 : 어떤 의미인지 알아보기 쉽다.
한 함수 내에 추상화 수준을 섞으면 코드를 읽는 사람이 헷갈린다. 근본 개념인지, 세부사항인지 구분하기 어려운 탓이다.
따라서 하나의 함수에는 하나의 추상화 수준만 사용하는 것이 좋다.
switch 문은 작게 만들기 어렵다.
switch 문은 다형적 객체를 생성하는 코드에서 추상 팩토리 패턴으로 사용하자.
public calss EmployeeFactory implements EmployeeFactory {
public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {
switch(r.type) {
case COMMISSIONED:
return new CommissionedEmployee(r);
case HOURLY:
return new HourlyEmployee(r);
case SALARIED:
return new SalariedEmployee(r);
default:
throw new InvalidEmployeeType(r.type);
}
}
}
좋은 이름이 주는 가치는 아무리 강조해도 지나치지 않다.
한 가지만 하는 작은 함수에 좋은 이름을 붙인다면 매우 훌륭하다. 또한 함수가 작고 단순할수록 서술적인 이름을 고르기도 쉬워진다.
길고 서술적인 이름이 짧고 어려운 이름보다 좋으니, 겁먹지 말자.
추가적으로 이름을 붙일 때는 일관성이 있어야 한다.
함수에서 이상적인 인수 개수는 0개다. 그 다음으로 1개... 2개...
인수는 적을수록 좋다. 또한 4개 이상이면 특별한 이유가 필요하고 특별한 이유가 있어도 사용하면 안 된다.
테스트 관점에서 봐도, 갖가지 인수 조합으로 함수를 검증하는 테스트 케이스 작성은 어렵다.
플래그 인수는 추하다. render(boolean isSuite)
라는 함수는 안에서 분기 처리하는 것이 아닌, renderForSuite()
와 renderForSingleTest()
로 나눠야 한다.
또한 인수를 함수 이름에 포함하는 경우 인수 순서와 함수 이름에 들어가는 순서를 맞추자.
부수 효과는 거짓말이다. 함수에서 한 가지를 하겠다고 약속하고선 남몰래 다른 짓도 하는 것이다.
어쩔 수 없이 부수 효과를 포함하는 경우에는 함수 이름에 포함하는 것이 좋다.
출력 인수의 경우에는 함수의 인자로 전달하는 방법보다 객체에 출력 메소드를 만들어야 한다. (appendFooter(StringBuffer report)
-> report.appendFooter()
)
함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야 한다.
객체 상태를 변경하거나 아니면 객체 정보를 반환하거나 둘 중 하나다.
만약 둘 다 하게 된다면,
if(setUsernmae(username)){...}
위와 같이 괴상한 코드가 나온다.
명령 함수에서 오류 코드를 반환하는 방식은 명령과 조회를 분리하라는 규칙을 미묘하게 위반한다.
앞서 설명한 것처럼 괴상한 코드가 나올 것이다.
따라서 오류 코드를 반환하는 것보다는 예외를 발생시키자.
try-catch 블록도 추할 수 있으니 별도 함수로 뽑아내는 편이 좋자. 그리고 오류 처리도 한 가지 작업이라는걸 잊지 말자.
만약 동일한 알고리즘이 반복되어 사용한다면 코드 길이가 늘어날 뿐 아니라 알고리즘이 변하면 모든 곳을 손봐야한다.
따라서 반복되는 부분은 하나의 메소드로 리팩토링하자.
소프트웨어를 짜는 행위는 여느 글짓기와 비슷하다. 먼저 생각을 기록한 후 읽기 좋게 다듬으면 된다.
초안은 서투르고 어수선하므로 원하는 대로 읽힐 때까지 말을 다듬고 문장을 고치고 문단을 정리한다.
지속적인 리팩토링을 통하여 더 가독성 있는 코드를 만들자.
하지만 모든 과정에서 테스트는 항상 통과해야 한다.