나쁜 코드 지우기 7
* 일반
G17. 잘못 지운 책임
- 소프트웨어 개발자가 내리는 가장 중요한 결정 중 하나가 코드를 배치하는 위치다
예를 들어, PI 상수는 어디에 들어갈까? Math 클래스에? 아니면 Trigonometry 클래스에? 아니면 Circle 클래스에?
여기서도 최소 놀람의 원칙을 적용한다 코드는 독자가 자연스럽게 기대할 위치에 배치한다
PI 함수는 삼각함수를 선언한 클래스에 넣어야 맞다
OVERTIME_RATE 상수는 HourlyPayCalculator 클래스에 선언해야 맞다
때로는 개발자가 '영리하게' 기능을 배치한다 독자에게 직관적인 위치가 아니라 개발자에게 편한 함수를 배치한다
예를 들어, 직원이 근무한 총 시간을 보고서로 출력함는 함수가 필요하다 가정하자
보고서를 출력하는 함수에서 총계를 계산하는 방법이 있다 아니면 근무 시간을 입력 받는 코드에서 총계를 보관하는 방법이 있다
결정을 내리는 한 가지 방법으로, 함수 이름을 살펴본다
예를 들어, 보고서 모듈에 getTotalHours 라는 함수가 있다고 가정하자
근무 시간을 입력 받는 모듈에 saveTimeCard 라는 함수가 있다고 가정하자
이름만 보았을 때 두 함수 중 어느 쪽이 총계를 계산해야 옳을까? 답은 명백하다
때로는 성능을 높이고자 근무 시간을 입력 받는 모듈에서 총계를 계산하는 편이 좋다고 판단할 수도 있다
그래도 괜찮지만, 그러려면 이런 사실을 반영해 함수 이름을 제대로 지어야 한다
예를 들어, 근무 시간을 입력 받는 모듈에 computeRunningTotalOfHours 함수를 만든다
G18. 부적절한 static 함수
- Math.max(double a, double b)는 좋은 static 메서드다 특정 인스턴스와 관련된 기능이 아니다
new Math().max(a, b)나 a.max(b) 라 하면 오히려 우습다 max 메서드가 사용하는 정보는 두 인수가 전부다
메서드를 소유하는 객체에서 가져오는 정보가 아니다 결정적으로 Math.max 메서드를 재정의할 가능성은 거의 아니 전혀 없다
그런데 간혹 우리는 static으로 정의하면 안 되는 함수를 static으로 정의한다
다음 예를 살펴보자
HourlyPayCalculator.calculatePay(employee, overtimeRate);
언뜻 보면 static 함수로 여겨도 적당하다 특정 객체와 관련이 없으면서 모든 정보를 인수에서 가져오니까
하지만 함수를 재정의할 가능성이 존재한다 수당을 계산하는 알고리즘이 여러 개일지도 모른다
예를 들어, OvertimeHourlyPayCalculator와 StraightTimeHourlyPayCalculator를 분리하고 싶을지도 모른다
그러므로 위 함수는 static 함수로 정의하면 안 된다 Employee 클래스에 속하는 인스턴스 함수여야 한다
일반적으로 static 함수보다 인스턴스 함수가 더 좋다 조금이라도 의심스럽다면 인스턴스 함수로 정의한다
반드시 static 함수로 정의해야겠다면 재정의할 가능성은 없는지 꼼꼼히 따져본다
G19. 서술적 변수
- 프로그램 가독성을 높이는 가장 효과적인 방법 중 하나가 계산을 여러 단계로 나누고 중간 값으로 서술적인 변수 이름을 사용하는 방법이다
FitNesse에서 가져온 다음 예제를 살펴보자
Matcher match = headerPattern.matcher(line);
if(match.find())
{
String key = match.group(1);
String value = match.group(2);
headers.put(key.toLowerCase(), value);
}
서술적인 변수 이름을 사용한 탓에 첫 번째로 일치하는 그룹이 key이고 두 번째로 일치하는 그룹이 value라는 사실이 명확히 드러난다
서술적인 변수 이름은 많이 써도 괜찮다 일반적으로는 많을수록 더 좋다
계산을 몇 단계로 나누고 중간값에 좋은 변수 이름만 붙여도 해독하기 어렵던 모듈이 순식간에 읽기 쉬운 모듈로 탈바꿈한다
G20. 이름과 기능이 일치하는 함수
- 다음 코드를 살펴보자
Data newDate = date.add(5);
5일은 더하는 함수인가? 아니면 5주? 5시간? date 인스턴스를 변경하는 함수인가?
아니면 예전 date 인스턴스는 그대로 두고 새로운 Date를 반환하는 함수인가? 코드만 봐서는 알 수가 없다
date 인스턴스에 5일을 더해 date 인스턴스를 변경하는 함수라면 addDaysTo 혹은 increaseByDays라는 이름이 좋다
반면, date 인스턴스는 변경하지 않으면서 5일 뒤인 새 날짜를 반환한다면 daysLater나 daysSince라는 이름이 좋다
이름만으로 분명하지 않기에 구현을 살피거나 문서를 뒤적여야 한다면 더 좋은 이름으로 바꾸거나 아니면 더 좋은 이름을 붙이기 쉽도록 기능을 정리해야 한다