(인프런) 김영한님의 스프링 핵심 원리-기본편을 공부하고 리뷰한 글입니다.
5. 새로운 구조와 할인 정책 적용
정액 할인 정책을 정률 할인 정책으로 변경한다.
FixDiscountPolicy → RateDiscountPolicy
AppConfig의 등장으로 애플리케이션이 크게 사용 영역 & 객체를 생성하고 구성하는 영역으로 분리되었다!
1. 그림 - 사용, 구성의 분리
2. 그림 - 할인 정책의 변경(중요!)
FixDiscountPolicy → RateDiscountPolicy 로 변경해도 구성 영역만 영향O, 사용 영역은 영향X
3. 할인 정책 변경 구성 코드
public class AppConfig {
// MemberService 역할(생성자 주입)
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
// MemberRepository 역할
private MemberRepository memberRepository() {
return new MemoryMemberRepository(); // 메모리 회원 저장소로
}
// OrderService 역할 (생성자 주입)
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
// DiscountPolicy 역할
public DiscountPolicy discountPolicy() {
//return new FixDiscountPolicy(); // 고정 할인 정책으로
return new RateDiscountPolicy(); // 정률 할인 정책으로 변경
}
}
- AppConfig 에서 할인 정책 역햘을 담당하는 구현을 FixDiscountPolicy → RateDiscountPolicy 객체로 변경했다.
- 할인 정책을 변경해도 애플리케이션의 구성 역할을 담당하는 AppConfig만 변경하면 된다.
- 구성 영역은 당연히 변경된다. (구성 역할을 담당하는 AppConfig = 애플리케이션의 공연 기획자, 공연 기획자는 공연 참여자인 구현 객체를 모두 알아야 함)
6. 전체 흐름 정리
1. 새로운 할인 정책 개발
다형성 덕분에 새로운 정률 할인 정책 코드를 추가로 개발하는 것 자체는 아무 문제가 없음
(인터페이스를 implements 한 구현체를 만들어서 개발함)
2. 새로운 할인 정책 적용과 문제점
1) OCP 위반
새로 개발한 정률 할인 정책을 적용하기 위해 클라이언트 코드인 주문 서비스 구현체도 함께 변경해야함
2) DIP 위반
주문 서비스 클라이언트가 인터페이스인 DiscountPolicy 뿐만 아니라, 구체 클래스인 FixDiscountPolicy 도 함께 의존
3. 관심사의 분리
● AppConfig: 애플리케이션의 전체 동작 방식을 구성(config)하기 위해, 구현 객체를 생성, 연결하는 책임
이제부터 클라이언트 객체는 자신의 역할을 실행하는 것만 집중, 권한이 줄어듬(책임이 명확해짐)
4. AppConfig 리팩터링
- 구성 정보에서 역할과 구현을 명확하게 분리
- 각 역할에서 구현 객체 생성 및 연결, 중복 제거
5. 새로운 구조와 할인 정책 적용
- 정액 할인 정책 → 정률 할인 정책으로 변경
- AppConfig 의 등장으로 애플리케이션이 사용 영역 & 구성 영역 으로 분리
- 할인 정책을 변경해도 AppConfig가 있는 구성 영역만 변경, 사용 영역 및 클라이언트 코드 변경X
7. 좋은 객체 지향 설계의 5가지 원칙의 적용
여기서 SRP, DIP, OCP 3가지가 적용되었다.
1. SRP(단일 책임 원칙)
한 클래스는 하나의 책임만 가져야 한다.
1) 기존
- 클라이언트 객체: 직접 구현 객체 생성, 연결, 실행하는 다양한 책임
2) SRP 단일 책임 원칙을 따르면서 관심사를 분리
- AppConfig: 구현 객체 생성, 연결하는 책임
- 클라이언트 객체: 실행하는 책임
2. DIP(의존 관계 역전 원칙)
프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다.” 의존성 주입은 이 원칙을 따르는 방법 중 하나다.
1) 기존
- 새로운 할인 정책을 개발하고 적용할 때 클라이언트 코드를 변경하게 됨
(기존 클라이언트 OrderServiceImpl은 DiscountPolicy 인터페이스 & FixDiscountPolicy 구현체 에도 의존했기 때문에)
2) 변경
- 클라이언트 객체: DiscountPolicy 인터페이스에만 의존
- AppConfig: FixDiscountPolicy 객체 인스턴스를 클라이언트 대신 생성, 클라이언트 코드에 의존 관계 주입
3. OCP(개방 폐쇄 원칙)
소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
1) 애플리케이션을 사용 영역 & 구성 영역으로 분리
- AppConfig가 의존 관계를 FixDiscountPolicy -> RateDiscountPolicy 로 변경해서 클라이언트 코드에 주입하므로 클라이언트 코드는 변경X
소프트웨어 요소를 새롭게 확장해도 사용 영역의 변경은 닫혀 있다!