객체의 세계에서 협력은 필수적이다. 협력이 존재한다는 것은 객체간의 의존성이 발생한다는 의미이며 (메세지를 보내고 받을) 이러한 의존성은 최소화되어야한다. 즉 무분별한 의존성은 오히려 악영향을 주는 것이다.
충분히 협력적이면서도 유연한 객체를 만들기 위해 의존성을 관리하는 방법
내가 가지고 있는 어떠한 인스턴스나 파라미터를 통해 들어온 값이 변경될 때 나도 같이 변해야한다는 말은 곧 그 객체에 의존하고 있다는 것을 의미한다.
하나의 객체가 다른 객체에 의존하고 있는 경우 의존하고 있는 객체가 변경되는 경우도 변경이 발생할 수 있다. 이런 경우를 의존성이 전이된다 라고 한다.
추상화된 인터페이스와 의존하는 영화 객체는 컴파일시점에서 가격과 퍼센트 할인에 대해서 알지 못한다. 즉 컴파일시점에는 할인이라는 것과 의존하고 있지만 런타임시점에서는 구체적으로 어떠한 할인과 결합하고 있는지 알 수 있게된다.
객체는 자신과 결합할 구체적인 클래스에 대해 아는 것은 좋지 않다. 구체적은 클래스를 알면 알수록 그 클래스가 사용되는 특정한 문맥에 강하게 결합되기 때문이다.
컨텍스트 독립성이란 클래스가 사용될 특정한 문맥에 대해 최소한의 가정만으로 이루어져 있어 다른 문맥에서 재사용하기가 수월해지는 것을 의미한다
설계가 유연해지기 위해서는 가능한 한 자신이 실행될 컨텍스트에 대한 구체적인 정보를 최대한 적게 알아야 한다. 컨텍스트에 대한 정보가 적으면 적을수록 더 다양한 컨텍스트에서 재사용될 수 있기 때문이다. 결과적으로 설계는 유연해지고 변경에 탄력적으로 대응할 수 있게 된다.
클래스가 실행 컨텍스트에 독립적인데도 어떻게 런타임에 실행 컨텍스트에 적절한 객체들과 협력할 수 있을까?
컴파일타임 의존성을 실행 컨텍스트에 맞는 적절한 런타임 의존성으로 교체하는 것을 의존성 해결이라고 부른다 이러한 의존성 해결은 일반적으로 세 가지 방법을 통해서 해결한다.
객체지향 패러다임의 근간은 협력이다. 객체들은 협력을 통해 어플리케이션에 생명력을 불어넣는다. 따라서 객체간의 의존성은 필수적이며 나쁜 것이 아니다. 하지만 잘못된 의존성은 객체지향의 본질을 훼손한다. 그렇다면 바람직한 의존성을 정하는 기준은 무엇인가 ?
아래로 갈수록 결합도가 느슨해진다.
의존성이 명시적이지 않으면 의존성을 파악하기 위해 내부 구현을 직접 살펴볼 수 밖에 없다. 커다란 클래스에 정의된 긴 메서드 내부 어딘가에서 인스턴스를 생성하는 코드를 파악하는 것은 쉽지 않다. 뿐만 아니라 의존성이 명시적이지 않으면 다른 컨텍스트에서 재사용하기 위해 내부 구현을 직접 변경해야 한다.
의존성을 명시적으로 표현해라
new 를 잘못 사용하면 클래스 사이의 결합도가 극단적으로 높아진다. new 가 해로운 이유는 구체클래스에 의존하게 만들기 때문이며 알아야하는 정보의 양을 증가시키기 때문에 궁극적으로 결합도가 높아진다.
물론 그렇지 않다. 변경에 대한 영향을 암시하기 때문에 우리는 추상화를 통해 변경에 유연하게 대처하는 방식을 택하고 있다. 하지만 자바 JDK에 포함된 표준 클래스는 자주 변경되는가? 거의 변경될 일이 없고 변경되더라도 우리가 사용하는 부분에 있어서 큰 변화는 존재하지 않는다.
어떻게 하는 것이 아니라 무엇을 하는지 를 선언적으로 표현하고 드러냄으로써 유연하고 재사용 가능한 설계를 만든다. 객체 네트워크 행위에 대한 선언적인 정의를 통해서. 어떻게가 아닌 무엇에 집중한다.
설계를 유연하게 만들 수 있었던 이유는 추상화에 의존하고 생성자를 통해 의존성을 명시적으로 드러냈으며 new와 같이 구체 클래스를 직접적으로 다뤄야하는 부분을 외부로 옮겼기 때문이다. 우리는 이제 추상화된 곳에 자식 클래스를 추가함으로써 간단하게 영화가 사용될 컨텍스트를 확장할 수 있다. 결합도를 낮춤으로써 얻게되는 컨텍스트 확장이라는 개념이 유연하고 재사용 가능한 설계를 만드는 핵심인 것이다.
같은 말로
사용과 생성의 책임을 분리하고, 의존성을 생성자에 명시적으로 드러내고, 구체 클래스가 아닌 추상 클래스에 의존하게 함으로써 설계를 유연하게 만들 수 있다. 그리고 그 출발은 객체를 생성하는 책임을 객체 내부가 아니라 클라이언트로 옮기는 것에서 시작했다. 즉 객체 내부적으로 강하게 의존하는 설계가 아니라 클라이언트의 요구 및 변화를 수용할 수 있는 형태로 확장성있게 설계되었다.