1 분 소요


프로젝트의 전체적인 다이어그램

회원 관리 클래스 다이어그램
diagram1


주문 도메인 클래스 다이어그램
diagram2


AppConfig

  • 애플리케이션의 전체 동작 방식을 구성(config)하기 위해, 구현 객체를 생성하고, 연결하는 책임을 가지는 별도의 설정 클래스
  • 기존 코드는 인터페이스 뿐만 아니라 구현 클래스도 함께 의존함
  • 그래서 구현 클래스를 변경할 때 클라이언트 코드도 함께 변경.
  • DIP 위반 -> 추상에만 의존하도록 변경(인터페이스에만 의존)
  • 이를 해결하기 위해 AppConfig를 활용해 클라이언트인 OrderServiceImplDiscountPolicy 구현 객체를 대신 생성하고 주입해주어야 함.

AppConfig

public class AppConfig {
    public MemberService memberService() {
        return new MemberServiceImpl(new MemoryMemberRepository());
    }
    
    public OrderService orderService() {
         return new OrderServiceImpl(
            new MemoryMemberRepository(),
             new FixDiscountPolicy());
    }
}
  • AppConfig는 애플리케이션의 실제 동작에 필요한 구현 객체를 생성
    • MemberServiceImpl
    • MemoryMemberRepository
    • OrderServiceImpl
    • FixDiscountPolicy
  • AppConfig는 생성한 객체 인스턴스의 참조를 생성자를 통해서 주입
    • MemberServiceImpl -> MemoryMemberRepository
    • OrderServiceImpl -> MemoryMemberRepository,FixDiscountPolicy


MemberServiceImpl - 생성자 주입

public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;

    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}
  • 설계 변경으로 MemberServiceImpleMemoryMemberRepository를 의존X
  • 단지 MemberRepository 인터페이스만 의존
  • MemberServiceImpl입장에서 생성자를 통해 어떤 구현 객체가 들어올지 알 수 없다.
  • MemberServiceImpl의 생성자를 통해서 어떤 구현 객체를 주입할지는 오직 외부(AppConfig)에서 결정.
  • MemberServiceImpl의존관계에 대한 고민은 외부에 맡기고 실행에만 집중

diagram3

  • 객체의 생성과 연결은 AppConfig가 담당
  • DIP 완성 : MemberServiceImplMemberRepository인 추상에만 의존.
  • OrderServiceImpl도 동일하게 적용


AppConfig 리팩터링

리팩터링 후

public class AppConfig {

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

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

    public DiscountPolicy discountPolicy() {
        return new FixDiscountPolicy();
    }
}
  • new MemoryMemberRepository()이 중복 제거되어 이제 MemoryMemberRepository를 다른 구현체로 변경할 때 한 부분만 변경하면 된다.
  • FixDiscountPolicy -> RageDiscountPolicyAppConfig만 수정하면 적용된다.

AppConfig 리팩터링 효과

  • 구성 정보에서 역할과 구현을 명확하게 분리
  • 역할이 잘 들어남
  • 중복 제거


<출처 : 인프런 - 스프링 핵심 원리 기본편(김영한)>

댓글남기기