Chapter 03. 함수
1. Solid
객체 지향 설계의 5가지 원칙
- SRP : 단일 책임 원칙(한 클래스는 하나의 책임만 가져야한다)
- 클래스는 하나의 기능만 가지며, 어떤 변화에 의해 클래스를 변경해야하는 이유는 오직 하나뿐이어야한다.
- SRP 책임이 분명해지기 때문에, 변경에 의한 연쇄 작용에 자유로워질 수 있다.
- 가독성 향상과 유지보수가 용이해진다.
- OCP : 개방-폐쇄 원칙(소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀있어야한다)
- 변경을 위한 비용은 가능한 줄이고, 확장을 위한 비용은 가능한 극대화해야한다.
- 요구사항의 변경이나 추가 사항이 발생하더라도, 기존 구성요소에는 수정이 일어나지 않고,
기존 구성 요소를 쉽게 확장해서 재사용한다. - 객체 지향의 추상화와 다형성을 활용한다.
- LSP : 리스크프 치환 원칙(서브 타입은 언제나 기반 타입으로 교체할 수 있어야한다)
- 서브 타입은 기반 타입이 약속한 규약(접근제한자, 예외 포함)을 지켜야한다.
- 클래스 상속, 인터페이스 상속을 이용해 확장성을 획득한다.
- 다형성과 확장성을 극대화하기 위해 인터페이스를 사용하는 것이 좋다.
- 합성(composition)을 이용할 수도 있다.
- ISP : 인터페이스 분리 원칙(자신이 사용하지 않는 인터페이스는 구현하지 말아야한다)
- 가능한 최소한의 인터페이스만 구현한다.
- 만약 어떤 클래스를 이용하는 클라이언트가 여러 개이고, 이들이 클래스의 특정 부분만 이용한다면,
여러 인터페이스로 분류하여 클라이언트가 필요한 기능만 전달한다. - SRP가 클래스 단일 책임이라면, ISP는 인터페이스의 단일 책임이다.
- DIP : 의존성 역전 원칙(상위 모델은 하위 모델에 의존하면 안된다. 둘 다 추상화에 의존해야한다.
추상화는 세부사항에 의존해서는 안된다. 세부 사항은 추상화에 따라 달라진다) -
- 하위 모델의 변경이 상위 모듈의 변경을 요구하는 위계 관계를 끊는다.
- 실제 사용 관계는 그대로지만, 추상화를 매개로 메시지를 주고 받으면서 관계를 느슨하게 만든다.

class PaymentController {
@RequestMapping(value = "/payment", method = RequestMethod.POST)
public void pay (@RequestBody CardPaymentDto.PaymentRequest req) {
final CardPaymentService cardPaymentService =
cardPaymentFactory.getType(req.getType());
cardPaymentService.pay(req);
}
}
public interface CardPaymentService {
void pay(CardPaymentDto.PaymentRequest req);
}
public class ShinhanCardPaymentService implements CardPaymentService {
@Override
public void pay(CardPaymentDto.PaymentRequest req) {
shinhanCardApt.pay(req);
}
}
2. 간결한 함수 작성하기
public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite)
throws Exception {
if (isTestPage(pageData)) {
includeSetupAndTeardownPages (pageData, isSuite);
}
return pageData.getHtml();
}
- 함수를 작게 쪼갠다
- 함수 내 추상화 수준을 동일하게 맞춘다.
- private 메서드로 분리화 해서 추상화 수준이 비슷한 메서드끼리 묶어서 분류해준다.
public abstract class Employee {
public abstract boolean isPayday();
public abstract Money calculatePay();
public abstract void deliverPay(Money pay);
}
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);
case HOURLY:
return new HourlyEmployee(r);
case SALARIED:
return new SalariedEmploye(r);
default:
throw new InvalidEmployeeType(r.type);
}
}
}
- 계산의 타입 관리를 분리한다.
- 타입에 대한 처리는 최대한 Factory 내에서만 진행한다.
함수 인수
- 인수의 갯수는 0 ~ 2개가 적당하다.
// 객체를 인자로 넘기기 👍
Circle makeCircle(double x, double y, double radius); //👎
Circle makeCircle(point center, double radius); //👍
// 가변 인자를 넘기기 -> 특별한 경우가 아니면
String.format(String format, Object... args);
3. 안전한 함수 작성하기
부수효과(Side Effect) 없는 함수
- 부수효과 : 값을 반환하는 함수가 외부 상태를 변경하는 경우이다.
- 함수 기능과 상관없는 다른 외부 상태를 변경시키는 동작을 하는 경우가 있어서는 안 된다.
4. 함수 리팩터링
본 포스트는 작성자가 공부한 내용을 바탕으로 작성한 글입니다.
잘못된 내용이 있을 시 언제든 댓글로 피드백 부탁드리겠습니다.
항상 정확한 내용을 포스팅하도록 노력하겠습니다.
반응형
'Book > Clean Code' 카테고리의 다른 글
Clean Code - 깨끗한 코드와 의미 있는 이름 (0) | 2024.03.21 |
---|
댓글