Spring 관심사의 분리

김두현·2023년 5월 18일
1

Spring

목록 보기
4/13
post-thumbnail

DIP, OCP 위반

아래 Client가 접근할 코드를 살펴보자.

package spring_basic.core.order;

import spring_basic.core.discount.DiscountPolicy;
import spring_basic.core.discount.FixDiscountPolicy;
import spring_basic.core.discount.RateDiscountPolicy;
import spring_basic.core.member.MemberRepository;
import spring_basic.core.member.MemoryMemberRepository;


public class OrderServiceImpl implements OrderService
{
    //===========OOP 원칙 위반==========//
    private MemberRepository memberRepository = new MemoryMemberRepository();
    
    // FixDiscountPolicy에서 RateDiscountPolicy로 변경
    //private DiscountPolicy discountPolicy = new FixDiscountPolicy();
    private DiscountPolicy discountPolicy = new RateDiscountPolicy();


	//내부 로직
}

위 코드의 문제점은 무엇일까?

DIP 위반 : Client가 Interface(DiscountPolicy)를 의존함과 동시에 Class(FixDiscountPolicy,RateDiscountPolicy)에도 의존한다.

마치 공연에서 로미오를 연기할 배우가 줄리엣을 연기할 배우까지 지정하는 셈이다.
배우는 단지 배정받은 역할에 대한 연기(구현)만 하면 된다.

OCP 위반 : Class를 확장하고자 했으나, Client 코드를 변경해야한다.

OCP는 확장에는 열려있으나, Client 코드 변경에는 닫혀있어야한다.

이러한 문제점을 어떻게 해결할 수 있을까?


관심사의 분리

구현체는 단지 구현만 해야할 뿐, 의존관계를 스스로 설정하면 원칙을 위배하게 된다.
즉, 배우는 자신의 역할을 연기할 뿐이지, 상대 배우가 누군지에 의존하지 않는다.
배우를 설정하는 것은 공연 기획자가 해야할 일이다.

즉, 구체 Class를 지정해줄 Class를 구현하여 관심사를 분리하자.

공연 기획자를 도입해보자!

  • AppConfig.java
package spring_basic.core;

import spring_basic.core.discount.DiscountPolicy;
import spring_basic.core.discount.FixDiscountPolicy;
import spring_basic.core.discount.RateDiscountPolicy;
import spring_basic.core.member.MemberRepository;
import spring_basic.core.member.MemberService;
import spring_basic.core.member.MemberServiceImpl;
import spring_basic.core.member.MemoryMemberRepository;
import spring_basic.core.order.OrderService;
import spring_basic.core.order.OrderServiceImpl;


public class AppConfig
{

    public MemberService memberService()
    {
        return new MemberServiceImpl(memberRepository());
    }

    public OrderService orderService()
    {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    public DiscountPolicy discountPolicy()
    {
        //return new FixDiscountPolicy();
        return new RateDiscountPolicy();
    }
    
    public MemberRepository memberRepository()
    {
        return new MemoryMemberRepository();
    }
}

  • OrderServiceImpl.java
package spring_basic.core.order;

import spring_basic.core.discount.DiscountPolicy;
import spring_basic.core.discount.FixDiscountPolicy;
import spring_basic.core.discount.RateDiscountPolicy;
import spring_basic.core.member.MemberRepository;
import spring_basic.core.member.MemoryMemberRepository;


public class OrderServiceImpl implements OrderService
{
    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy)
    {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }


	//내부 로직
}

AppConfig.java의 등장으로 인해, Client 코드는 Interface에만 의존하게 되었고 확장에도 영향받지 않는 것을 볼 수 있다.

관심사의 분리를 통해, DIP와 OCP를 준수하게 되었다.


프로그램 동작

지금까지의 과정으로 구현된 프로그램은 아래와 같이 동작한다.

  • OrderApp.java
package spring_basic.core;

import spring_basic.core.member.Grade;
import spring_basic.core.member.Member;
import spring_basic.core.member.MemberService;
import spring_basic.core.member.MemberServiceImpl;
import spring_basic.core.order.Order;
import spring_basic.core.order.OrderService;
import spring_basic.core.order.OrderServiceImpl;

public class OrderApp
{
    public static void main(String[] args)
    {
        AppConfig appConfig = new AppConfig();
        MemberService memberService = appConfig.memberService();
        OrderService orderService = appConfig.orderService();

        //프로그램 로직
    }
}
  • 사용과 구성의 분리

참고 자료

https://www.inflearn.com/course/스프링-핵심-원리-기본편


💕오류 지적 및 피드백은 언제든 환영입니다. 복제시 출처 남겨주세요!💕
💕좋아요와 댓글은 큰 힘이 됩니다.💕
profile
I AM WHO I AM

0개의 댓글