강의를 들으며 생각 정리
객체 지향 설계
앞서 개발한 회원 서비스에서 다형성을 활용하여, 인터페이스(역할)와 구현 객체(구현)를 분리했다. 그러나 OCP, DIP와 같은 객체 지향 설계 원칙을 충실히 준수하지는 못했다.
서비스 클라이언트는 인터페이스와 구현 클래스 둘 다 의존하고 있고 기능을 확장해서 변경하려면 클라이언트 코드에 영향을 주기 때문이다.
기대했던 의존관계
서비스 클라이언트는 할인 정책의 인터페이스만을 의존하길 원한다.
실제 의존관계
실제로는 할인 정채의 인터페이스 뿐만 아니라 구체 클래스도 함께 의존하고 있다.(DIP 위반)
정리하면 클라이언트 코드인 OerServiceImpl은 DiscountPolicy의 인터페이스 뿐만 아니라 구체 클래스도 함께 의존하고 있다. 그래서 구체 클래스를 변경할 때 클라이언트 코드도 함께 변경해야 한다.
-> 인터페이스에만 의존하도록 설계를 변경하자. -> 누군가가 클라이언트에 DiscountPolicy의 구현 객체를 대신 생성하고 주입해 주어야 한다.
관심사의 분리
애플리케이션을 하나의 공연이라고 생각해보자. 각각의 인터페이스를 배역(역할)이라고 생각하자. 로미오 역할을 맡은(인터페이스) 디카프리오(구현체, 배우)는 배우 연기에만 집중해야하는데 줄리엣 역할(인터페이스)을 하는 여자 주인공(구현체, 배우)을 직접 초빙하는 상황이 되면 안된다. 즉, 디카프리오는 공연도 해야하고 동시에 여자 주인공도 공연에 직접 초빙해야 하는 다양한 책임을 갖게 되는 것을 방지해야 한다.
배우는 본인의 역할인 배역을 수행하는 것에만 집중해야 한다. 여기서 공연을 구성하고, 담당 배우를 섭회하고, 역할에 맞는 배우를 지정하는 책임을 담당하는 별도의 공연 기획자가 있어야 한다.
이를 AppConfig.java에서 담당하며 AppConfig는 애플리케이션의 실제 동작에 필요한 구현 객체를 생성하고 동시에 생성자를 통해서 구현체들을 각 구현 객체들에게 주입해준다.
이제 회원 서비스 구현체는 의존관계에 대한 고민은 외부(AppConfig)에 맡기고 본인의 서비스 실행에만 집중하면 된다.
이제 할인 정책을 FixDiscountPolicy에서 RateDiscountPolicy로 변경해도 구성영역만을 변경하고, 사용영역은 전혀 영향을 받지 않는다.(OCP,DIP 구현)
이는 의존관계를 마치 외부에서 주입해주는 것과 같다고 해서 DI(dependency injection) 혹은 의존관계 주입이라고 한다.
<AppConfig.java>
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
public MemoryMemberRepository memberRepository() {
return new MemoryMemberRepository(); # 메모리 저장소 사용
}
public OrderService orderService(){
return new OrderServiceimpl(memberRepository(),discountPolicy());
}
public DiscountPolicy discountPolicy(){
return new RateDicountPolicy(); # 정률 할인 정책 사용
}
}
정리
새로운 할인 정책 개발
다형성 덕분에 새로운 할인 정책을 추가로 개발하는 것 자체는 문제 없다.
새로운 할인 정책 문제점
새로운 할인 정책을 적용하려고 하니 클라이언트 코드인 주문 서비스 구현체도 함께 변경해야 한다.
(DIP 위반)
관심사의 분리
공연 기획자 역할을 하는 AppConfig를 추가해 애플리케이션의 동작 방식을 구성하기 위해, 구현 객체를 생성하고, 연결하는 책임을 가지게 한다.
새로운 구조와 할인 정책 적용
AppConfig의 등장으로 애플리케이션이 크기 사용 영역과, 객체를 생성하고 구성하는 구성 영역으로 분리된다.
할인 정책을 변경해도 AppConfig가 있는 구성 영역만 변경하고, 사용 영역은 변경할 필요가 없다.
앞서 객체 지향 원리를 적용시킴으로써 더 효율적인 로직을 개발해 보았다. 그러나 순수자바코드로만 개발을 진행했기 때문에 이를 스프링으로 변환하는 과정이 필요하다. 지금도 안정적인 코드로 보이는데 그렇다면 스프링을 사용하면 어떤 장점이 있을까? 다음 포스팅부터 이에 대한 내용을 알아본다.
'java > spring' 카테고리의 다른 글
[Spring] 컴포넌트 스캔 (0) | 2021.01.08 |
---|---|
[Spring] 싱글톤 컨테이너 (0) | 2021.01.08 |
[Spring] 스프링 설정하기, 스프링 컨테이너와 스프링 빈 (0) | 2021.01.08 |
[Spring] 스프링 핵심 원리 이해 1 - 예제 만들기 (0) | 2021.01.06 |
[Spring] 객체 지향 설계와 스프링 (0) | 2021.01.03 |