[클린코드] 출력인수를 가급적 피하라 ( this의 존재 이유 )
함수는 매개변수를 갖는다. 매개변수로 들어 온 값을 '인수'라고 한다.
인수에는 두 가지가 있다.
1. 입력인수
2. 출력인수
함수는 특정 목적에 맞게 인수를 '처리'해야 한다. 인수는 처리대상이 된다.
boolean fileExists("Myfile"){
// 생략...
}
위 함수는 Myfile이라는 이름을 가진 파일이 존재하는지 조회하는 함수이다. 매개변수에 조회하고 싶은 대상을 인수로 입력해야한다. 이 때의 인수를 '입력인수'라고 한다.
public void appendFooter(StringBuffer report) {
// 생략...
}
위 함수는 StringBuffer 객체에 Footer를 추가(append)하는 함수이다. 이 때의 인수를 '출력인수'라고 한다. 출력인수를 피해야하는 이유는 '인지적인 이유'로 가독성을 떨어트리기 때문이다.
일단 함수가 인수를 입력 받으면 인수는 두 가지 목적으로 처리된다.
1. 조회
2. 변환
조회는 X(입력인수) → f → Y (boolean; 참 혹은 거짓) 이다.
변환은 X(입력인수) → f → Y (다른객체) 이다.
X를 처리(f)하고 Y라는 결과를 return해야한다. boolean fileExists("Myfile")는 String객체(X)를 처리(f)하여 boolean 값(Y)으로 반환한다. 자연스러운 함수 처리 과정이다.
그러나
void appendFooter(report)는 StringBuffer 객체를 입력받아서 footer가 추가된 StringBuffer를 만드는 함수이다.
그러므로 X → f → X이다.
그러나 StringBuffer appendFooter(StringBuffer report)라고 표현하지 않는다. 같은 객체이기 때문에 굳이 반환 안해줘도 된다. void appendFooter(StringBuffer report)로 표현한다.
이와같이 출력인수는 함수의 통념에 위배된다.
그래서 개발자가 코드 상에서 appendFooter(report)라는 함수를 보면 인지적으로 혼란이 생긴다. 함수는 인수를 받으면 조회하거나 변환해야 하는데 appendFooter(report)는 report 객체를 인수로 받아서 Footer를 append하고 무엇으로 반환한다는 말인지 감을 잡지 못한다.
함수는 X → f → X이고 인수는 변환되지 않는다. 조회도 아니고 변환도 아니므로 굳이 X를 인수로 받을 필요가 없다. 그러므로 X → f → X의 형태의 함수는 인수를 가지지 않아야 자연스럽다.
변경 전 : appendFooter(report)
변경 후 : report.appendFooter();
report를 메소드의 인수로 넣는게 아니라 report 안에 메소드를 넣어야 한다. 그래야 report 객체에 Footer를 append한다고 직관적으로 파악할 수 있다. 출력인수가 만들어 내는 혼란을 피하기 위해 자주 사용하는 대표적인 변수가 'this'이다. this를 사용하면 인수를 사용하지 않고도 함수의 처리 대상이 자기 자신임을 명시할 수 있다.