Table of contents
Open Table of contents
의존성 이해하기
변경과 의존성
- 실행 시점: 의존하는 객체가 정상적으로 동작하기 위해서는 실행 시에 의존 대상 객체가 반드시 존재해야 한다.
- 구현 시점: 의존 대상 객체가 변경될 경우 의존하는 객체도 함께 변경된다.
의존성을 방향성을 가지며 항상 단반향이다.
의존성과 전이
의존성 전이 (transitive dependency) 가 의미하는 것은 의존 대상 객체가 의존하는 객체를 의존하게 되는 것을 의미한다.
예를 들어 A
가 B
를 의존하고, B
가 C
를 의존하면 A
는 C
에 대한 의존성을 갖게 된다.
의존성은 함께 변경될 수 있는 가능성을 의미하기 때문에 모든 경우에 의존성이 전이되는 것은 아니다.
런타임 의존성과 컴파일타임 의존성
어떤 차이가 있을까?
Movie, DiscountPolicy, AmountDiscountPolicy, PercentDiscountPolicy 사이의 의존 관계를 런타임과 컴파일타임을 비교해서 살펴보자.
- 런타임 의존성: 객체 사이의 의존성
- 컴파일타임 의존성: 클래스 사이의 의존성
컨텍스트 독립성
클래스가 특정한 문맥에 강하게 결함될수록 다른 문맥에서 사용하기는 더 어려워진다. 클래스가 사용 될 특정한 문맥에 대해 최소한의 가정만으로 이뤄져 있다면 다른 문맥에서 재사용하기가 더 수월해진다. 이를 컨텍스트 독립성 이라고 부른다.
의존성 해결하기
컴파일타임 의존성을 실행 컨텍스트에 맞는 적절한 런타임 의존성으로 교체하는 것을 의존성 해결 이라고 한다.
- 객체를 생성하는 시점에 의존 대상 객체를 전달하는 방법
- 객체 생성 후 setter 메서드를 이용해 의존 대상 객체를 전달하는 방법
- 메서드 실행 시 인자로 의존 대상 객체를 전달하는 방법
의존성 해결을 위해 가장 선호 되는 방법?
생성자 방식과 setter
방식을 혼합하는 것.
항상 객체를 생성할 때 의존성을 해결해서 완전한 객체를 생성한 후, 필요에 따라 의존 대상을 변경할수 있게 한다.
유연한 설계
의존성과 결합도
바람직한 의존성이란 무엇인가?
=> 재사용성 과 관련이 있다. 어떤 의존성이 다양한 환경에서 클래스를 재사용할 수 없도록 제한한다면 그 의존성은 바람직하지 못한 것이다.
- 의존성: 두 요소 사이의 관계 유무
- 결합도: 두 요소 사이에 존재하는 의존성의 정도를 상대적으로 표현
추상화의 의존하라
- 구체 클래스 의존성(Concrete Class Dependency)
- 추상 클래스 의존성(Abstract Class Dependency)
- 인터페이스 의존성(Interface Dependency)
목록에서 아래쪽으로 갈수록 결합도가 느슨해진다.
명시적인 의존성
의존성의 대상을 생성자의 인자로 전달받는 방법과 생성자 안에서 직접 생성하는 방법의 가장 큰 차이는 퍼블릭 인터페이스를 통해 의존성을 명시적으로 드러내느냐이다.
new는 해롭다.
new
클래스를 잘못 사용하면 클래스 사이의 결합도가 극단적으로 높아진다.
new
연산자를 사용하기 위해서는 구체 클래스의 이름을 직접 기술해야 한다. 따라서new
를 사용하는 클라이언트는 추상화가 아닌 구체 클래스에 의존할 수밖에 없기 때문에 결합도가 높아진다.new
연산자는 생성하려는 구체 클래스뿐만 아니라 어떤 인자를 이용해 클래스의 생성자를 호출해야 하는지도 알아야 한다. 따라서new
를 사용하면 클라이언트가 알아야 하는 지식의 양이 늘어나기 때몬에 결합도가 높아진다.
해결 방법은 인스턴스를 생성하는 로직과 생성된 인스턴스를 사용하는 로직을 분리하는 것이다.
가끔은 생성해도 무방하다.
주료 협력하고 싶은 기본 객체를 설정하고 싶은 경우엔 클래스 안에서 객체의 인스턴스를 직접 생성하는 방식이 유용하다.