ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [이펙티브 자바] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라_아이템5
    이펙티브 자바 2023. 11. 23. 20:51

    많은 클래스가 하나 이상의 자원에 의존한다.

    [정적 유틸리티 잘못된 예제]

    public class SpellChecker {
        private static final Lexicon dictionary = ...;
        
        private SpellChecker() {} //객체 생성 방지
        
        public static boolean isValid(String word) {...}
        public static List<String> suggestions(String typo) {...}
    }

    [싱글톤 잘못된 예제]

    public class SpellChecker {
        private final Lexicon dictionary = ...;
        
        private SpellChecker(...){}
        public static SpellChecker INSTANCE = new SpellChecker(...);
        
        public boolean isValid(String word) {...}
        public List<String> suggestions(String typo) {...}
    }

    유연하지 않고 테스트하기 어려운 코드로 사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글톤 방식이 적합하지 않다.

    필드에서 final 한정자를 제거하고 교체하는 메서드를 추가하여 사용할 수 있지만, 오류가 나기 쉽고 멀티스레드 환경(하나의 프로세스를 다수의 실행 단위로 구분하여 자원을 공유하고 자원의 생성과 관리의 중복성을 최소화하여 수행 능력을 향상시키는 것)에서는 쓸 수 없다. => 사용하는 자원에 따라 동적이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다.

    대신 클래스(SpellChecker)가 여러 자원 인스턴스를 지원해야하며, 클라이언트가 원하는 자원(dictionary)을 사용해야 한다. => 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식이다.(의존 객체 주입의 형태)

    [의존 객체 주입 예제]

    public class SpellChecker {
        private final Lexicon dictionary;
        
        public SpellChecker(Lexicon dictionary){
            this.dictionary = Objects.requireNonNull(dictionary);
        }
        
        public boolean isValid(String word) {...}
        public List<String> suggestions(String typo) {...}
    }


    dictionary라는 하나의 자원을 사용하지만 자원이 몇개든 의존 관계가 어떻든 상관없이 잘 작동한다. 또한 불변 보장하여 같은 자원을 사용하려는 여러 클라이언트가 의존 객체들을 안심하고 공유할 수 있기도 하다.
    의존 객체 주입은 생성자, 정적 팩터리, 빌더 모두 똑같이 응용할 수 있다.

    또 다른 방법은 생성자에 자원 팩터리를 넘겨주는 방식이다. => 팩터리 메서드 패턴을 구현.
    Supplier<T> 인터페이스가 팩터리를 표현한 예다. 입력으로 받은 메서드는 일반적으로 한정적 와일드카드 타입을 사용해 팩터리의 타입 매개변수를 제한해야 한다. => 이 방식을 사용해 클라이언트는 자신이 명시한 타입의 하위 타입이라면 무엇이든 생성할 수 있는 팩터리를 넘길 수 있다.

    [클라이언트가 제공한 팩터리가 생성한 타일들로 구성된 모자이크를 만드는 메서드 예제]

    Mosaic create(Supplier<? extends Tile> tileFaxtory) {...}


    의존 객체 주입이 유연성과 테스트 용이성을 개선해주지만 큰 프로젝트에서 코드를 어지럽게 만든다. => 의존 객체 주입 프레임워크를 사용하면 직접 주입하도록 설계된 API를 응용해 사용할 수 있다.

    => 클래스 내부에 하나 이상 자원에 의존하면 싱글톤과 정적 유틸리티 클래스는 알맞지 않다. 필요한 자원을 생성자나 빌더에 넘겨주자. 의존 객체 주입은 클래스의 유연성, 재사용성, 테스트 용이성을 개선해준다.

Designed by Tistory.