프로그램에서 가장 기본적인 단위가 함수다.
함수를 잘 만드는 방법을 알아보자
작게 만들어라
작게 더 작게!
책의 저자는 근거를 대기는 어렵지만 40년간 경험과 시행착오를 바탕으로 작은 함수가 좋다고 주장한다.
블록과 들여 쓰기
함축적으로 말하면 제어문이나 반복문 등에 들어가는 블록 속 코드는 한 줄이여야 한다는 의미다.
따라서 그 안에서 함수를 호출하게 된다. 그리고 그 함수 이름을 잘 짓는다면 코드를 이해하기도 쉬워진다.
public class Ex01 {
public static void main(String[] args) {
int number = 31;
if(isEvenNumber(number) ) {
reportEvenNumber();
} else {
reportOldNumber();
}
}
private static void reportOldNumber() {
System.out.println("홀수에요!!");
}
private static void reportEvenNumber() {
System.out.println("짝수에요!!");
}
private static boolean isEvenNumber(int number) {
return number%2 == 0 ? true : false;
}
}
블록과 들여 쓰기는 1단이나 2단을 넘어서면 안 된다. 중첩 구조가 생길만큼 커지면 안된다.
함수 당 추상화 수준은 하나로
한 함수내에 추상화 수준을 섞으면 코드를 읽는 사람이 헷갈린다.
특정 표현이 근본 개념인지 세부사항인지 구분하기 어렵고 섞이기 시작하면 깨진 창문 효과 처럼 사람들이 함수에 세부사항을 점점 더 추가한다.
위에서 아래로 코드 읽기: 내려가기 규칙
코드는 위에서 아래로 잘 쓴 글처럼 읽혀야 된다.
위에 함수는 추상화 수준이 높다.
아래 함수는 추상화 수준이 낮다.
위에서 아래로 갈수록 추상화 수준이 한 단계 씩 낮아진다.
Switch 문은 작게 만들기 어렵다. ( if/else 포함)
public Money calculatePay(Employee e) throws InvalidEmployeeType {
switch (e.type){
case COMMISSIONED:
return calculateCommissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type);
}
}
위 함수의 문제점
- 함수가 길다. 새 직원 유형 추가 시 더 길어진다
- 함수는 한 가지 작업을 잘해야 한다. 위 함수는 한 작업만 수행하지 않는다.
- SRP(Single Responsibility Principle) 위반한다. 코드를 변경할 이유가 여럿이다.
- OCP(Open Closed Principle) 위반한다. 새 직원 유형 추가 때마다 코드를 변경한다.
public abstract class Employee {
public abstract boolean isPayday();
public abstract Money calculatePay();
public abstract void deliverPay(Money pay);
}
#########################
interface EmployeeFactory {
public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}
#########################
public class EmployeeFactoryImpl implements EmployeeFactory {
@Override
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);
}
}
}
switch문을 추상 팩토리에 숨겼다. 팩토리에서 적절한 Employee 구현체 인스턴스를 반환한다.
반환된 객체는 다형성을 통해 서로 다른 동작을 하게 된다.
'IT책, 강의 > 클린코드(Clean Code)' 카테고리의 다른 글
4장 주석 - 나쁜 주석 (1) | 2022.10.01 |
---|---|
4장 주석 - 좋은 주석 (0) | 2022.09.28 |
3장 함수 - 2 (2) | 2022.09.25 |
2장 의미 있는 이름 (0) | 2022.07.01 |
1장 깨끗한 코드 (0) | 2022.06.27 |