※ 본 포스팅은 Inflearn - 김영한 강사님의 '스프링 핵심 원리 - 기본편' 을 참고,공부하여 만들었습니다.
AppConfig 리팩터링
AppConfig 리팩터링을 하는 이유는 무엇일까? 먼저 리팩터링을 거치지않은 코드를 살펴보자
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(new MemoryMemberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(
new MemoryMemberRepository(),
new FixDiscountPolicy());
}
}
AppConfig 내에서 '중복' 이 일어나고 있음을 확인할 수 있다.
바로 'new MemoryMemberRepository' 의 중복, 객체를 2번 만드는 현상이 일어나고 있는것이다.
또한 우리는 저장소를 바꿔줄때 일일이 코드를 수정하지 않기 위해서 AppConfig라는 설정 클래스를 만든것이 아닌가?
그렇다면 우리는 저장소를 바꿔줄때 두군데를 전부 일일이 수정해줘야 한다
이를 해결하기 위해서 리팩터링을 해보자
리팩터링을 거쳐준 코드를 확인해보면 다음과 같다.
public class AppConfig {//나의 애플리케이션의 전반적인 구성과 설정을 책임!
public MemberService memberService(){
return new MemberServiceImpl(memberRepository()); // 객체 = Value
}//MemberServiceImpl을 쓸지말지 제어권한은 AppConfig에게 있다. OrderServiceImpl도 마찬가지!
public OrderService orderService(){ // 오더서비스에 저장소와 할인정책을 주입시켜준다.
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
public DiscountPolicy discountPolicy() {
return new FixDiscountPolicy(); // <-- 이제 이 부분만 수정하면 시스템 전체에 적용
}
public MemberRepository memberRepository() {
return new MemoryMemberRepository(); // <-- 이제 이 부분만 수정하면 시스템 전체에 적용
}
}
리팩터링을 거치면 확실히 중복되는 부분을 제거하여준다.
리팩터링을 거치면 역할(DiscountPolicy)와 구현클래스(FixDiscountPolicy)가 한눈에 들어온다.
public MemberService memberService(){ //인터페이스 : 역할
return new MemberServiceImpl(memberRepository()); // Impl : 구현
}
이런식으로 역할과 구현클래스가 한눈에 들어올수 있도록 하는게 가능하다는것,
7월 7일 내용추가,
인프런 질문게시판을 보던중 대수롭지 않게 여기고 지나갔지만 나도 잘 이해하지 못한 부분이 있었어서 내용을 추가한다.
우리는 AppConfig를 리팩터링하여 역할과 구현을 명확히하고 중복을 제거하였다.
하지만 본인은 중복을 제거하면서 new MemoryMemberRepository 를 한번만 생성한거라고 착각했다.
그래서 Singleton 개념에 가서는 Singleton 방식의 이점을 제대로 이해하지 못했던것같다.
그래서 위의 질문게시판의 질문을 보고 다시 공부해보았고 내가 소홀히 한 개념, 놓친개념들을 다시한번 정리해 보았다.
public class AppConfig {//나의 애플리케이션의 전반적인 구성과 설정을 책임!
public MemberService memberService(){
return new MemberServiceImpl(memberRepository()); // 객체 = Value
}//MemberServiceImpl을 쓸지말지 제어권한은 AppConfig에게 있다. OrderServiceImpl도 마찬가지!
public OrderService orderService(){ // 오더서비스에 저장소와 할인정책을 주입시켜준다.
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
public DiscountPolicy discountPolicy() {
return new FixDiscountPolicy(); // <-- 이제 이 부분만 수정하면 시스템 전체에 적용
}
public MemberRepository memberRepository() {
return new MemoryMemberRepository(); // <-- 이제 이 부분만 수정하면 시스템 전체에 적용
}
}
위의 코드에서 memberService() 와 orderService() 코드를 보면 결국은 new MemoryMemberRepository()를 두번 만든다는것은 변함이 없다.
즉 다른 객체 2개를 생성한다는것인데 그럼에도 불구하고 프로그램이 현재 돌아가는 이유는 바로
MemoryMemberRepository의 필드가 static이기 때문이다.
●잠깐 상식●
정적 변수(Static)
-객체 생성에 따라 값이 개별적으로 저장되는 인스턴스 변수와 달리 정적 변수 static은 한 클래스에 관련해 생성된 모든 객체들에 동일한 값을 가지게 한다.
따라서 MemoryMemberRepository 에 저장된 정보들은 새로운 객체를 생성하더라도 저장된 값을 사용이 가능하다.
한마디로 초기화가 일어나지않는것 (사실 스프링 공부가 아니라 static공부..)
하지만 이런식으로 새로운 객체를 계속 생성하게되면 많은 이용자가 생길시 문제들이 발생하는데
이는 Spring의 Singleton 개념을 배우면 해결이 가능하다는것만 알고가자
'Spring > Spring Study' 카테고리의 다른 글
[Inflearn] 싱글톤(Singleton) 컨테이너 (0) | 2021.08.18 |
---|---|
[Inflearn] 스프링 컨테이너와 빈 (0) | 2021.07.01 |
[Inflearn] 좋은 객체 지향 설계 원칙 (0) | 2021.06.29 |
[Inflearn] AppConfig (0) | 2021.06.28 |
[Inflearn] 스프링 핵심 원리 - 기본편 , 중간정리 (7월7일 내용수정) (0) | 2021.06.28 |