-
의존성 관리는 미래를 견뎌낼 수 있는 애플리케이션을 만드는 데 핵심적인 요소다.
- 의존성 주입은 느슨한게 결합된 객체, 창의적으로 재사용할 수 있는 객체리를 만들어 준다.
- 의존성 격리는 객체가 예상치 못한 변화에 재빨리 적응할 수 있게 해준다.
- 추상화를 사용하는 것은 이런 변경에 직면해야 하는 경우를 줄여준다.
- 의존성 관리의 핵심은 그 방향을 관리하는 것이다. 평온한 유지보수라는 궁극의 목표를 향한 길은 자기 자신보다 덜 변하는 것에 의존하는 클래스들로 덮여있다.
의존성 이해하기
의존성은 무엇인가? 무엇이 의존성을 만들어 내는가?
- 객체 지향 애플리케이션은 다른 객체와 협업을 통해 기능을 수행한다.
- 객체들이 협업하기 위해서는 자신 이외의 다른 객체들에 대한 지식이 있어야 하고, 이러한 지식은 의존성을 만들어 낸다.
-
다른 객체들에 대한 지식 ( = 의존성)
- 다른 클래스의 이름
- 다른 객체에게 전송할 수 있는 메시지 이름
- 메시지가 필요로 하는 인자들
- 인자들의 순서
-
또 다른 의존성
- 메시지 연쇄에 의한 의존성 - 다른 객체에게 전송할 수 있는 이름을 아는 의존성의 확장된 형태
- 테스트가 코드에 대해 갖는 의존성 - 코드의 수정이 뒤이어 테스트 코드의 수정을 강제하는 의존성
- 불필요한 의존성은 코드를 덜 적절하게 만든다. 그 의존성이 클래스의 수정을 강제하기 때문
- 우리의 도전과제는 각 클래스가 자신이 해야 하는 일을 하기 위한 최소한의 지식만을 알고 그 외에는 아무것도 모르도록 의존성을 관리하는 것
- 의존성이 높은 객체들은 마치 하나인 듯 행동한다.
- 둘 이상의 객체가 강력하게 결합되어 있을 때 이들은 한 덩어리로 움직이고 이들 중 하나만 재사용 하는 것은 불가능하다.
약하게 결합된 코드 작성하기
-
의존성 주입하기
- 중요한 것은 객체의
클래스가 무엇인지
가 아니라우리가 전송하는 메시지가 무엇인지
이다. -
전송하는 메시지를 이해할 수 있는 객체를 필요로 한다.
- 객체의 구체적인 타입은 중요하지 않음.
- 객체가 해당 메서드를 구현하고 있는지가 중요함. -> 루비에서는 오리타입을 사용함.
-
의존성 주입
- 클래스 내부에서 사용하는 객체를 외부에서 생성해서 생성자 또는 다른 무언가를 통해 클래스 내부로 주입해주는 것
- 의존성 주입을 통해 객체를 초기화할 때 넘겨줘야 하는 인자와 인자의 순서에 대해 명식적으로 존하고 있었던 것을 제거할 수 있다.
- 중요한 것은 객체의
-
의존성 격리
- 불필요한 의존성을 제거할 수 없는 경우 클래스 안에서 격리시켜야 한다.
-
의존성은 간결하게 정리되고 명시적으로 드러나고 격리되어 있어야 한다.
-
인스턴스 생성 격리 -> 외부 클래스 이름을 참조하는 지점 격리
- 제약조건이 너무 많아서 인스턴스를 주입할 수 없다면 인스턴스를 생성하는 과정을 내부에서 한 곳으로 격리시켜야 한다.
- 의존성 격리는 의존성을 명시적으로 노출하려는 것.
- 의존하는 것이 클래스의 내부에 스며들지 않도록 하는 것
- 생성하는 프로세스를 래퍼 메서드로 감싸서 사용
-
외부로 전송하는 메시지 중 위험한 것 격리
- 어떤 객체의 메서드 사용 = 객체에 해당 메서드가 있다는 사실을 알고 있다 -> 의존성
- 객체의 메서드를 사용하는 부분은 클래스 내부의 메서드 속에 캡슐화 -> 사용하는 객체의 메서드의 이름과 시그니처가 변경되더라도 클래스에 미치는 영향은 래퍼 메서드에 한정된다.
- 참조 지점을 격리하는 것은 이런 변화의 영향에 대응하기 위한 안전망을 제공한다.
- 모든 외부 메서드 호출에 대해 선제적으로 대응할 필요는 없지만 이런 작업은 시도해 볼 만한 일이다.
-
-
인자 순서에 대한 의존성 제거
-
메서드 시그니처에서 인자의 순서가 변경되면 이를 사용하는 측에서도 변경해줘야 함. -> 인자 순서에 대한 의존성 발생
- 루비에서는 해시로 만들어서 해결함 -> 자바스크립트의 경우 인자를 객체로 받는거랑 비슷한 효과
- 해시를 사용할 경우 인자의 순서에 대한 의존성은 제거했지만 이름에 의존하게 됨 -> 새로운 의존성은 기존의 것보다 훨씬 안정적
- 사용할 상황과 그렇지 않은 상황을 잘 구분해서 의존성을 제거할 것
- 기본값을 제공할 것
-
특정 프레임워크 또는 라이브러리를 사용할 경우도 마찬가지
- 외부 인터페이스에 대한 모든 지식을 한 곳에 고립
- 외부에 대한 의존성이 코드 속으로 스며들게 내버려 두지 말자. 애플리케이션이 직접 통제할 수 있는 래퍼 메서드르 만들어서 애플리케이션을 보호하자.
-
의존성의 방향 관리하기
-
의존성 방향 결정하기
-
객체는 자기 자신보다 덜 변하는 객체에 의존해야 한다.
- 어떤 클래스는 다른 클래스에 비해 요구사항이 더 자주 바뀐다.
- 구체 클래스는 추상 클래스보다 수정해야 하는 경우가 빈번히 발생한다.
- 의존성이 높은 클래스를 변경하는 것은 코드의 여러 곳에 영향을 미친다.
-
의존성 방향 결정을 위해 고려해야 하는 것
-
변경될 가능성이 얼마나 높은지 파악하기
- 애플리케이션에서 사용되는 모든 클래스를 얼마나 변경되지 않는지를 기준으로 정렬
- 이 순위는 의존성의 방향을 결정하는 데 핵심적이다.
-
구체적인 것과 추상적인 것을 인지하기
- 추상화는 구체적인 것들로부터 추출된다.
- 추상화의 훌륭한 점은 일반적이고 안정적인 성질을 지닌다는 점
- 추상화된 인터페이스는 인터페이스가 기반하고 있던 구체 클래스보다 변경될 일이 훨씬 적다. -> 추상화된 결과에 의존하는 것은 구체 클래스에 의존하는 것보다 훨씬 안전하다.
-
-