프로그램에서 가장 기본적인 단위가 함수다.

함수를 잘 만드는 방법을 알아보자

작게 만들어라

작게 더 작게!

책의 저자는 근거를 대기는 어렵지만 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);
	}
}

위 함수의 문제점

  1. 함수가 길다. 새 직원 유형 추가 시 더 길어진다
  2. 함수는 한 가지 작업을 잘해야 한다. 위 함수는 한 작업만 수행하지 않는다.
  3. SRP(Single Responsibility Principle) 위반한다. 코드를 변경할 이유가 여럿이다.
  4. 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

+ Recent posts