본문 바로가기
개인 공부/Java (이펙티브 자바)

[이펙티브 자바] 아이템 5 : 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

by 희조당 2023. 1. 15.
728x90

✍️ 학습 목표

  • 의존 객체 주입 패턴

📌 의존 객체 주입 패턴

일반적으로 객체는 여러 자원들과 의존한다.

예를 들어, 자동차라는 객체는 부품들에 의존하고 책의 예시는 맞춤법 검사기는 사전에 의존한다.

의존한다는 말은 관계를 가진다, 즉 서로가 서로에게 영향을 주는 것을 말한다.

🤔 왜 필요하지?

책에서 제시된 예시들을 보면 금방 이해할 수 있다.

1️⃣ 정적 클래스를 사용

public class SpellChecker {
    private static final Dictionary dictionary = new Dictionary();

    private SpellChecker() { }

    public static boolean isValid(String word) { return false; };
    public static List<String> suggestions(String typo) { return new ArrayList<>(); }
}

2️⃣ 싱글톤을 사용

public class SpellChecker {
    private final Dictionary dictionary = new Dictionary();

    private SpellChecker() { }
    public static SpellChecker INSTANCE = new SpellChecker(...);

    public boolean isValid(String word) { return false; };
    public List<String> suggestions(String typo) { return new ArrayList<>(); }
}

일반적으로 많이 사용되는 코드들이다. 둘의 단점은 동일하게 유연하지 않고 테스트가 어렵다는 점이다.

🤔 유연하지 않은 코드?

유연하지 않은 코드는 어떤 것을 말하는 것일까?

위의 예시에서 사전을 단 하나만 사용할 때는 문제가 전혀 없는 것처럼 보인다.

하지만 다양한 언어를 지원해야 하거나 잘못된 사전을 사용하는 경우에는 코드를 대폭 수정해야 한다.

따라서 변화에 둔감한 코드를 유연하지 않은 코드라고 한다.

🤔 테스트하기 어려운 코드?

그렇다면 테스트하기 어려운 코드란 무엇일까? 보통 다음 2가지 포함한 경우를 말한다.

1️⃣ 제어할 수 없는 값

시간이나 난수와 같이 매번 다른 결과를 만들어내는 값은 테스트하기 어렵다.

Mocking을 통해서 해결할 수 있지만 추가적인 학습을 요구하고 좋은 테스트라고 하기 어렵다. 

  • 높은 테스트 코드 관리 비용 : 어떻게 내부적으로 작동하는지 알아야 한다. 즉, 테스트 코드에서 내부 로직이 드러나게 되고, 로직이 수정된다면 모두 수정해야 한다.
  • 이해하기 어려운 코드 : 기대하는 동작에 대해서 객체가 어떻게 작동할지 다 명세해야 한다. 이는 테스트 코드를 보기 어렵게 만든다.
  • 떨어지는 신뢰도 : 특정 동작을 기대하면서 작성되기 때문에 실제로 동작하는 것과 다를 수 있다.

2️⃣ 외부에 영향을 주는 코드

데이터베이스, 이메일 발송 등과 같이 외부에 영향을 주는 코드는 테스트하기 어렵다.

특히 데이터베이스가 필요한 경우 느린 테스트의 주범이 된다. 이럴 때는 Slice Test를 고민해 보자!

😎 어떻게 써야 할까?

상황에 맞는 필요한 자원에 의존할 수 있도록 해주면 된다.

가장 쉬운 방법으로 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주면 된다. Setter 방식도 있긴 하다.

public class SpellChecker {
    private final Dictionary dictionary;

    public SpellChecker(Dictionary dictionary) {
        this.dictionary = Objects.requireNonNull(dictionary);
    }

    public boolean isValid(String word) { return false; };
    public List<String> suggestions(String typo) { return new ArrayList<>(); }
}

생성자에게 자원을 넘겨주면 자원이 몇 개든 상관이 없고 불변성을 보장할 수 있다.

추가로, 자원 말고 자원을 생성해 주는 팩토리를 넘겨줄 수도 있다.

 


-Reference

토비의 스프링

https://jojoldu.tistory.com/674

https://medium.com/@chanhyeonglee/mock-%EA%B0%9D%EC%B2%B4-%EB%82%A8%EC%9A%A9%EC%9D%80-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%A5%BC-%EB%A7%9D%EC%B9%9C%EB%8B%A4-f38129e5d40a

 

😋 지극히 개인적인 블로그지만 훈수와 조언은 제 성장에 도움이 됩니다 😋 

댓글