객체지향 설계의 5가지 원칙
1. SRP 단일 책임 원칙 : 한 클래스는 하나의 책임만 가져야 한다
복잡한 클래스는 정체성 파악 어려워서 코드를 다 읽어봐야된다
따라서 클래스는
SRP 원칙을 지키면
변경에 의한 연쇄작용에서 자유로워 가독성 향상, 유지보수가 용이해진다
2. OCP 개발-폐쇄 원칙 : 소프트웨어 요소는 확장엔 열려 있으나 변경엔 닫혀 있어야한다
요구사항의 변경이나 추가사항이 발생해도 기존 구성 요소에는 수정이 일어나지 않고
기존 구성 요소를 쉽게 확장해서 재사용한다
(추상화와 다형성 활용해서 하면 용이)
3. LSP 리스토프 치환 원칙
: 서브 타입은 언제나 기반 타입으로 교체할 수 있어야한다
서브타입은 기반타입이 약속한 규약을 지켜야한다
클래스 상속, 인터페이스 상속을 이용해 확장성 획득한다
다형성과 확장성을 극대화하기 위해 인터페이스를 사용하는 것이 좋다
** 참고
서브타입 : 자식클래스
기반타입 : 부모클래스
4. ISP 인터페이스 분리 원칙
: 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다
가능한 최소한의 인터페이스만 구현 (인터페이스를 뚱뚱하게 만드는 것보단 가능한 작게 여러 개로)
즉, 묶을 수 있는 한가지 기능에 대한 인터페이스식으로 만드는 것이다
5. DIP 의존성 역전 원칙
: 상위 모델은 하위 모델에 의존하면 안 되고 둘 다 추상화에 의존해야 한다, 추상화는 세부사항에 의존해서는 안 되고 세부사항은 추상화에 따라 달라진다
실제 사용 관계는 그대로지만, 추상화를 매개로 메세지를 주고 받으면서 관계를 느슨하게 만든다
1. 작게 쪼갠다 : 함수 내 추상화 수준을 동일하게 맞춘다
2. 한가지만 하기(SRP), 변경에 닫게 만들기(OCP)
//..
swith (employee.type) {
case COMMISSINED :
return calculateCommissionedPay(employee);
case HOURLY :
return calculateHourlyPay(employee);
case SALARIED :
return calculateSakariedPay(employee);
//..
}
계산도 하고 money도 생성하는 2가지 기능이 보이고,
새로운 직원 타입이 추가 된다면 코드 수정해야된다
따라서 계산과 타입관리를 분리해야된다
3. 함수 인수 : 인수 갯수는 0~2개가 적당
// 객체를 인자로 넘기기
Circle makeCircle(double x, double y, double radius); // Bad
Circle makeCircle(Point center, double radius); // Good
// 가변인자를 넘기기 -> 특별한 경우가 아니면 잘 안 쓴다!
String.format(String format. Object ...args);
부수 효과 (Side Effect) 없는 함수
부수효과 : 값을 반환하는 함수가 외부 상태를 변경하는 경우
1. 기능을 구현하는 서투른 함수 작성 : 길고, 복잡하고, 중복이 있을 수 있음
2. 테스트 코드 작성 : 함수 내부의 분기와 엣지 값 마다 빠짐없이 테스트하는 코드를 짬
3. 리팩터링 : 코드 다듬고, 함수 쪼개고, 이름 바꾸고, 중복 제거