[스프링 핵심원리] - 2.스프링 핵심 원리 이해2(객체지향 원리 적용) (4)

Chooooo·2022년 10월 6일
0
post-thumbnail

이 글은 강의 : 김영한님의 - "스프링 핵심원리 - 기본편"을 듣고 정리한 내용입니다. 😁😁


새로운 구조와 할인 정책 적용

이제 이전에 해보려고 했던 할인 정책을 변경해보자. 기존에는 정액 할인 정책을 사용하여 어떤 주문이 들어오더라도 1000원만큼 할인이 이루어졌는데 바꾸려고 하는 것은 정률 할인 정책으로 주문가격의 10퍼센트를 할인해주는 정책.

FixDiscountPolicy -> RateDiscountPolicy로 변경. 이제 어떤 부분을 바꿔주면 되는지 살펴보자!
이제까지 AppConfig를 만들게 되면서 애플리케이션이 실제 로직이 수행되는 사용 영역객체를 생성하고 구성(Configuration)하는 영역으로 분리되었다.

사용, 구성의 분리

현재 애플리케이션의 구조는 이와 같은 상태. 할인 정책 변경 시에는??

할인 정책의 변경

사용 영역에 있는 코드는 전혀 손대지 않고 구성 영역의 AppConfig만 수정하면 된다.
즉 구성 영역만 영향있고 사용 영역은 영향 없음.

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();    // 정률 할인 정책으로 변경
    }
}

main 메서드를 구행해보면 결과 정상적으로 나옴.
DIP를 지킨 것은 물론, OCP까지 한번에 지키게 된 것. 구성 영역의 코드는 수정이 됐다. 하지만 구성 영역은 당연히 변경된다.(구성 역할을 담당하는 AppConfig는 애플리케이션의 공연 기획자. 즉 공연 기획자는 공연 참여자인 구현 객체를 모두 알아야 하잖아)

전체 흐름 정리

새로운 할인 정책 개발

다형성 덕분에 새로운 정률 할인 정책 코드를 추가로 개발하는 것 자체에 아무 문제가 없었다.
(역할인 인터페이스를 implements한 구현체를 만들어서 개발)

새로운 할인 정책 적용과 문제점

1. OCP 위반

새로 개발한 정률 할인 정책을 적용하기 위해 클라이언트 코드인 주문 서비스 구현체도 함께 변경했어야 했음.

2. DIP 위반

주문 서비스 클라이언트가 역할(인터페이스), 추상화인 DiscountPolicy뿐만 아니라 구현 클래스(FixDiscountPolicy)에도 함께 의존했음

관심사의 분리

AppConfig

애플리케이션의 전체 동작 방식을 구성(Config)하기 위해 구현 객체를 생성, 연결하는 책임을 가짐
이제부터 클라이언트 객체는 자신의 역할을 실행하는 것만 집중, 권한이 줄어든다! --> 책임이 명확해짐.

리팩토링

구성 정보에서 역할과 구현을 명확하게 분리
각 역할에서 구현 객체 생성 및 연결, 중복 제거

새로운 구조와 할인 정책 적용

할인 정책 변경 --> AppConfig 등장으로 애플리케이션의 사용영역, 구성영역으로 분리됨. --> 할인 정책을 변경해도 AppConfig가 있는 구성영역만 변경. 그렇기에 사용영역인 클라이언트 코드는 변경되지 않아.

좋은 객체지향설계의 5가지 원칙 적용

SRP(단일 책임 원칙)

한 클래스는 하나의 책임만 가져야 한다는 원칙

처음에 만들었던 클라이언트 객체는 직접 구현 객체를 생성하고, 연결하고 실행까지 하는 다양한 첵임을 가지고 있었다.
SRP 원칙에 따라서 관심사를 분리하게 된다.
더 이상 클라이언트는 구현 객체를 생성하거나 연결하지 않고, AppConfig 가 해당 역할을 담당하게 된다(구현객체 생성, 연결하는 책임)
클라이언트 객체는 실행하는 책임만 담당한다

객체가 많은 역할을 구행하면 나중에 변경이 일어나면 이 클래스를 이용하는 다른 모든 곳에 영향이 있을 수 있고, 개발자가 파악하기도 어려우니 이 원칙을 잘 지키자!!

DIP(의존관계역전원칙)

추상화에 의존, 구체화에 의존x

정액 할인 정책에서 정률 할인 정책으로 변경을 하려고 했을 때, 클라이언트 코드도 변경해야하는 문제가 있었다. 클라이언트인 OrderServiceImpl 이 DIP를 지키며 DiscountPolicy 인터페이스에 의존하는 것처럼 보였으나 실제로는 구현 클래스인 FixDiscountPolicy에 의존하고 있기 때문이다.
클라이언트가 구현 클래스를 빼고, DiscountPolicy에만 의존하도록 변경했다.
하지만 클라이언트는 인터페이스만으로는 실행이 되지 않았다.
그래서 AppConfig가 구현클래스를 대신 생성해서, 클라이언트 코드에 의존관계를 주입했다.

OCP(개방 폐쇄 원칙)

소프트웨어 요소는 확장에는 열려있고 변경에는 닫혀 있어야 한다.

다형성을 사용하고 클라이언가 DIP를 지키게 되었다
애플리케이션이 사용영역과 구성영역으로 나뉘게 되었다.
AppConfig를 통해서 의존관계가 FixDiscountPolicy -> RateDiscountPolicy로 변경해서 클라이언트 코드에 주입이 되기 때문에 클라이언트 코드는 변경하지 않아도 된다.
소프트웨어 요소를 새롭게 확장해도 사용 영역의 변경은 닫혀있게 된다

profile
back-end, 지속 성장 가능한 개발자를 향하여

0개의 댓글