아이템 5 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다. 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식인 의존 객체 주입 방식을사용해야한다.
예를 들어 unitPrice * usage를 통한 최종 금액에서, 할인율 20%(소수점 내림)를 적용하려고 한다. 아래처럼 코드를 만들 수 있다.
@Override
public long calculateEachCharge(CityGasUser user) {
long unitPrice = user.getUnitPrice();
long usage = user.getUsage();
return unitPrice * usage * 80 / 100;
}
예시에서는 할인율을 80이라는 매직 넘버로 하드코딩하고 있다.
return unitPrice * usage * 80 / 100;
- 매직 넘버의 문제
- 가독성 저하: 코드에서 80이 어떤 의미인지 알기 어렵다. 할인율인지, 다른 값인지 불분명합니다.
- 유지보수 어려움: 할인율을 변경하고 싶다면 소스 코드를 직접 수정해야 하고, 변경된 내용을 추적하기 어려워진다.
- 재사용성 저하: 클라이언트가 할인율을 변경하려고 할 때, 코드 수정이 필요하여 유연성이 떨어진다.
다음과 같이 의존 객체 주입 방식을 사용하여 문제를 해결할 수 있다.
public class VulnerableCityGasChargeService extends CityGasChargeService {
private final int discountRate;
public VulnerableCityGasChargeService(CityGasUserService cityGasUserService, int discountRate) {
super(cityGasUserService);
this.discountRate = discountRate;
}
@Override
public long calculateEachCharge(CityGasUser user) {
long unitPrice = user.getUnitPrice();
long usage = user.getUsage();
return unitPrice * usage * (100 - discountRate) / 100;
}
}
의존 객체 주입의 장점
- 가독성 향상: discountRate가 명시적으로 주입되므로 코드의 의미가 명확해진다.
- 유연성 증가: 클라이언트에서 할인율을 쉽게 변경할 수 있다. 예를 들어, 다른 할인율을 가진 인스턴스를 생성하여 다양한 상황에 대응할 수 있다.
- 테스트 용이성: 테스트 코드에서 다른 할인율로 VulnerableCityGasChargeService를 쉽게 초기화할 수 있어, 단위 테스트를 수행하기 쉬워진다.
- 재사용성 향상: 같은 클래스를 재사용하면서도서로 다른 할인율로 인스턴스를 만들 수 있다.
핵심 정리
클래스가 내부적으로 하나 이상의 자원에 의존하고, 그 자원이 클래스 동작에 영향을 준다면 싱글턴과 정적 유틸리티 클래스는 사용하지 않는 것이 좋다. 이 자원들을 클래스가 직접 만들게 해서도 안 된다. 대신 필요한자원을 생성자에 넘겨주자. 의존 객체 주입이라 하는 이 기법은 클래스의 유연성, 재사용성, 테스트 용이성을 기막히게 개선해준다.
'Java' 카테고리의 다른 글
이펙티브 자바(Effective Java) 2장 - 아이템 7 다 쓴 객체 참조를 해제하라 (0) | 2024.12.03 |
---|---|
이펙티브 자바(Effective Java) 2장 - 아이템 6 불필요한 객체 생성을 피하라 (0) | 2024.12.03 |
이펙티브 자바(Effective Java) 2장 - 아이템 4 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2024.12.03 |
이펙티브 자바(Effective Java) 2장 - 아이템 3 private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2024.12.03 |
이펙티브 자바(Effective Java) 2장 - 아이템 2 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2024.12.03 |