Development/Spring Boot
[Spring Boot] AppConfig 리팩토링
sky Jeong
2022. 8. 4. 00:02
1- 리팩토링 대상 코드
package hello.core;
import hello.core.discount.FixDiscountPolicy;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
/**
* Application 전체를 구성하고 설정하는 역할
* - 로미오 줄리엣 공연 예시 중 기획자
* - 어플리케이션에 대한 환경 구성을 모두 이곳에서 함
*/
public class AppConfig {
// 생성자 주입: 생성자를 통해서 객체가 주입되는 것
public MemberService memberService() {
return new MemberServiceImpl(new MemoryMemberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy());
}
}
- 하늘이가 예상 해보는 리팩토링!
package hello.core;
import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.member.MemberRepository;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
/**
* Application 전체를 구성하고 설정하는 역할
* - 로미오 줄리엣 공연 예시 중 기획자
* - 어플리케이션에 대한 환경 구성을 모두 이곳에서 함
*/
public class AppConfig {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
public AppConfig() {
this.memberRepository = new MemoryMemberRepository();
this.discountPolicy = new FixDiscountPolicy();
}
// 생성자 주입: 생성자를 통해서 객체 주입
public MemberService memberService() {
if (this.memberRepository == null)
this.memberRepository = new MemoryMemberRepository();
return new MemberServiceImpl(this.memberRepository);
}
public OrderService orderService() {
if (this.discountPolicy == null)
this.discountPolicy = new FixDiscountPolicy();
return new OrderServiceImpl(this.memberRepository, this.discountPolicy);
}
}
(1) 메모리 관점
- 인스턴스가 생성될때마다 기존에는 생성자 안에서 의존성 주입되는 인스턴스를 생성하여 넘겼었음
- 어차피 동일한 역할을 하는 것이기에 AppConfig 생성자를 통해 인스턴스 생성시, 주입되는 객체의 인스턴스를 생성해여 공통적으로 사용하면 메모리의 불필요한 낭비 필요 없이 가능할 것이라 생각.
(2) 유지보수 관점 (중복 코드)
- 덧붙여 이전 코드의 경우 MemberServiceImpl과 OrderServiceImpl 인스턴스 생성시, MemoryMemberRepository를 공통적으로 생성했는데,
- 만약 회원 저장소를 메모리가 아니라 자체 DB 혹은 외부 무언가로 변경하게 될 경우 각 구현체를 변경해야함.
- 하지만 만약 하늘쓰가 리팩토링한 것처럼 AppConfig 생성자에서만 MemberRepository의 구현체 생성을 수행한다면, 이후 다른 회원 저장소로 변경된다할 경우 해당 코드 한 줄만 변경하면 됨.
--> 생각 변화! 메모리 관점에서 오히려 저게 더 악수임. 필요할때만 생성하는 것이 오히려 메모리 낭비가 없기에 아래 강의 필기의 예시 코드처럼 리팩터링 하는 것이 장점이 더 강함.
2- 강의 필기
- 기존 코드 내에 중복이 존재하며, 역할에 따른 구현이 안보임
- IntelliJ는 자동으로 중복된 코드를 바꿀 수 있음
Extract / Introduce -> Extract Method
--> Mac 단축키: 옵션 + 커멘드 + M
- 리팩토링 코드
package hello.core;
import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
/**
* Application 전체를 구성하고 설정하는 역할
* - 로미오 줄리엣 공연 예시 중 기획자
* - 어플리케이션에 대한 환경 구성을 모두 이곳에서 함
*/
public class AppConfig {
// 생성자 주입: 생성자를 통해서 객체가 주입되는 것
// 중복된 코드 잡아주는 단축키 (맥 기준) : 옵션 + 커맨드 + M
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
private MemoryMemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(),discountPolicy());
}
public DiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
}
}
- 장점
- 메서드 역할을 명확히 알 수 있음
- 구현체가 변경될 경우 코드 수정이 용이함
- 어플리케이션 구성을 수비게 파악할 수 있음