if / for / while 안에 들어가는 내용은 함수로 뺄 수 있다면 빼도록 하자. 긴 문장이 저 구문 안에 들어 있다면 이해하기가 어렵다.
함수를 정의하기 전에 우리가 해야할 작업들의 단위를 구분하자.
위의 예시처럼 각 일들을 구분해서 함수를 만드는 것이 좋다.
getHtml() 함수는 render()를 충분히 내장할 수 있다. 이것은 추상화 수준이 높은 것으로 볼 수 있고, append()와 같은 함수는 추상화가 매우 낮다고 볼 수 있다. 우리는 적당한 추상화 수준을 찾고, 그 기준을 통해 함수를 짜야된다.
public class UserValidator {
private Cryptographer cryptographer;
public boolean checkPassword(String userName, String password) {
User user = UserGateway.findByName(userName);
if (user != User.NULL) {
String codePhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if ("Valid Password".equals(phrase)) {
Session.initialize();
return true;
}
}
return false;
}
}
위와 같은 코드가 있다고 생각해보자. 이 코드의 가장 큰 문제는 Session.initialize()를 호출한다는 것이다. 이는 checkPassword와 전혀 연관이 없는 부분이다.
자주 사용되는 명령 함수와 조회 함수를 한 곳에 두지말고 분리해서 호출하도록 하자.
저자는 함수를 만들 때 먼저 서투른 초안을 만들고, 원하는 대로 읽힐 때까지 말을 다듬고 문장을 고친다고 한다.
처음 만든 초안은 길고 복잡하지만, 점점 그것들을 나누고, 단위 테스트 케이스도 만든다. 그런 다음 중복을 제거하고, 이름을 바꾸고, 때로는 전체 클래스를 쪼개기도 하는 등 리팩토링을 진행한다. 이 때 단위 테스트는 항상 통과해야한다고 한다.