작게 만들어라!
- 함수는 작게 만들수록 이해하기 쉽다
블록과 들여 쓰기
- if 문/else 문/while 문 등에 들어가는 블록은 한 줄인것이 좋다
- 대개 거기서 함수를 호출한다
- 바깥을 감싸는 함수(enclosing function)가 작아진다
한 가지만 해라!
- 함수는 한 가지만 해야한다
- 단순히 다른 표현이 아니라 의미 있는 이름으로 다른 함수를 추출할 수 있다면 그 함수는 여러작업을 하는 것이다
함수 당 추상화 수준은 하나로!
- 함수가 확실히 '한 가지' 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일화 해야 한다
- 추상화 수준이 하나로 맞춰지기 어렵다면 내려가기 규칙에 따라 작성하는것이 권장된다
위에서 아래로 코드 읽기: 내려가기 규칙
- 코드는 위에서 아래로 이야기처럼 읽혀야 한다
- 위에서 아래로 프로그램을 읽으면 함수 추상화 수준이 한 번에 한 단계씩 낮아 지도록 한다
Switch 문
- 본질적으로 switch 문은 N가지를 처리하며, SRP, OCP를 위반한다
- 다형성(polymorphism)과 추상 팩토리를 이용하여 switch 문을 저레벨 클래스에 숨길 수 있다
public abstract class Employee {
public abstract boolean isPayday();
public abstract Money calculatePay();
public abstract void deliverPay();
}
---------------------------------------
public interface EmployeeFactory {
public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}
----------------------------------------
public class EmployeeFactoryImpl implements EmployeeFactory {
public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {
switch(r.type) {
case COMMISSIONED:
return new CommissionedEmployee(r.type);
case HOURLY:
return new HourlyEmployee(r.type);
case SALARIED:
return new SalariedEmployee(r.type);
default:
return new InvalidEmployeeType(r.type);
}
}
}
서술적인 이름을 사용하라!
- 길고 서술적인 이름이라도 함수 기능을 잘 표현하는 이름으로 짓자
- 일관성 있는 이름을 붙이자
- 모듈 내에서 함수 이름은 같은 문구, 명사, 동사를 사용하자
함수 인수
- 함수에서 이상적인 인수 개수는 0개(무항)이다
- 다음은 1개(단항), 다음은 2개(이항)이며, 3개(삼항)는 가능한 피하는 편이 좋다
많이 쓰는 단항 형식
- 함수에 인수 1개를 넘기는 이유는 1) 인수에 질문을 던지는 경우, 2) 인수로 뭔가로 변환해 결과를 반환하는 경우다.
- 위의 경우가 아니라면 단항 함수는 가급적 피해야 한다.
플래그 인수
- 플래그 인수는 함수가 한꺼번에 여러 가지를 처리한다고 대놓고 공표하는 셈이다
이항 함수 & 삼항 함수
- 이항 함수는 단항 함수에 비해 이해하기 어렵기에, 가능하다면 단항 함수로 바꾸도록 하자
- 삼항 함수는 이항 함수에 비해 야기되는 문제가 두 배 이상 늘어난다
인수 객체
- 인수로 primitive 타입이 대신 독자적인 클래스 변수로 선언하여 객체를 넘겨줄 수 있다
- 인수 객체를 사용함으로 줄일 수 있지만, 단순히 사용하는 목적으로 사용하는 것 대신 개념을 표현하는 방향으로 사용하자
Circle makeCircle(double x, double y, double radius);
Circle makeCircle(Point point, double radius);
부수 효과를 일으키지 마라!
- 함수에서 한가지를 하겠다고 약속하고선 남몰라 다른 짓을 하지말자
- 일반적으로 출력 인수는 피하자
명령과 조회를 분리하라!
- 하나의 함수에서 명령과 조회를 분리해라
if (attributeExists("username")) {
setAttribute("username", "ckddn9496");
...
}
오류 코드보다 예외를 사용하라!
- 오류 코드를 반환한다는 것은 어디선가 오류 코드를 정의하며 다른 클래스는 이를
import
한다 - 즉, 오류 코드는 의존성 자석이다. 오류 코드가 변한다면 이를 사용하는 클래스를 전부 다시 컴파일하고 배치해야한다
- 오류 코드 대신 예외를 사용하면 새 예외는 Exception 클래스에서 파생되어 재컴파일/재배치 없이도 새 예외 클래스를 추가할 수 있다
- try/catch 블록을 별도 함수로 뽑아내서 처리하자
반복하지 마라!
- 중복을 없애 가독성을 높여야 한다
- 많은 원칙과 기법이 중복을 없애거나 제어할 목적으로 나왔다