함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야한다.
/*
- html을 가져오는 함수 추상화 수준이 매우 높다
- 우리는 getHtml()이 어떻게 진행되는지 모르고 범용적으로 사용될 수 있다
*/
getHtml() // html을 가져오는 함수 추상화 수준이 매우 높다
/*
- pagePath를 인자로 넣어줘야 실행될 수 있는 메소드
- 특정 값에서 사용할 수 있는 메소드로 추상화 수준이 중간
*/
String pagePathName = PathParser.render(pagePath);
/*
- 메소드의 범위가 매우 작고 사용도 제한적
*/
buiffer.append("\n");
서술적이고 이해가 쉬운 긴 이름이 짧고 난해한 이름과 서술적인 주석보다 낫다
// 짧고 난해한 이름
testOrder()
// 서술적이고 이해가 쉬운 긴 이름
isOrderable()
hasAvailableProduct()
// 질문을 던지는 경우
Boolean fileExists("MyFile");
// 인자를 무언가로 변환해 결과로 반환하는 경우
InputStream fileOpen("MyFile");
// 피해야하는 경우
render(true) // 플래그 인자 - 참 거짓에 따라 두가지 일을 하기 때문 헷갈림
// 좌표 경우
Point p = new Point(x,y) // 자연스럽게 읽힌다
// 피해야하는 경우
writeField(outputStream, name) // 인수들이 어떻게 쓰이는지 헷갈린다
// 이렇게 바꾸자
outputStream.writeField(name) // 이름을 쓴다는 의미가 바로 이해된다
함수에서 한 가지 일만 한다 약속하고선 부수효과를 통해 다른 일을 해서는 안된다
public class UserValidator {
private Cryptographer cryptographer;
public boolean checkPasswd(String id, String passwd) {
User user = UserGateway.findById(id);
if (user != null) {
String codedPhrase = user.getPhraseEncodedByPasswd();
String phrase = cryptographer.decrypt(codePhrase, passwd);
if ("Valid Passwd".equals(phrase)) {
Session.init(); // checkPassword안에 세션을 초기화하는 부수효과가 있다
return true;
}
}
return false;
}
}
함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야한다
/*
- attribute에 value를 set해서 성공하면 true 실패시 false를 리턴하는 함수
- set함수를 사용하면 아래와 같은 코드가 발생하는데 set을 한다는건지 되었다는건지 의미를 구분하기 힘들다
*/
public boolean set(String attribute, String value);
if (set("username", "effortguy")) {...}
// 명령과 조회를 분리하니 보기 좋아졌다
if (existsAttribute("username")) {
setAttribute("username", "effortguy");
}
/*
- 명령과 조회를 분리하라는 규칙을 어김
- 여러단꼐로 중첩되는 코드를 야기한다
*/
if (deletePage(page) == E_OK) {
if (registry.deleteRegistry(page.name) == E_OK) {
logger.log("Registry deleted");
} else {
logger.log("delete Registry failed");
}
} else {
logger.log("delete failed")
return E_ERROR;
}
/*
- try catch 사용
*/
try {
deletePage(page);
registry.deleteRegistry(page.name);
} catch (Exception e) {
logger.log(e.getMessage());
}
/*
- try catch 블록내 함수 로직 분리
- 오류도 한 가지 작업
*/
public void delete(Page page) {
try {
deletePageAndRegistry(page);
} catch(Exception e) {
logError(e);
}
}
private void deletePageAndRegistry(Page page) throw Exception {
deletePage(page);
registry.deleteRegistry(page.name);
}
private void logError(Exception e) {
logger.log(e.getMessage());
}
좋은 코드는 한 번에 안나온다.. 그러니 끝없는 리팩토링을 통해 발전시키자