2023.08.23 WED
261p ~ 276p
20일차 내용⬇️
2023.08.22 - [개발 서적 기록/오브젝트_조영호] - 20일차 - 런타임과 컴파일 시점의 의존성을 위해 컨텍스트는 독립되어야한다
20일차 - 런타임과 컴파일 시점의 의존성을 위해 컨텍스트는 독립되어야한다
2023.08.22 TUE 247p ~ 263p 19일차 내용 ⬇️ 2023.08.21 - [개발 서적 기록] - 19일차 - 모듈로 정보 은닉하기 19일차 - 모듈로 정보 은닉하기 2023.08.21 MON 234p ~ 249p 18일차 내용 ⬇️ 2023.08.21 - [개발 서적 기록/
magenta-ming.tistory.com
의존성 해결
컴파일 타임 의존성을 실행 컨텍스트에 맞는 적절한 의존성으로 교체해야한다.
아래 방법을 사용해서 의존성을 해결할 수 있다.
- 객체를 생성하는 시점에 생성자를 통해 의존성 해결
- 객체 생성 후 setter 메서드를 통해 의존성 해결
- 메서드 실행 시 인자를 이용해 의존성 해결
바람직한 의존성
느슨하고 약한 결합도를 가지는 설계에서 우리는 의존성이 바람직하다고 말할 수 있다.
바람직한 의존성을 가진 설계는 이 의존성에 대해 재사용하기 쉽게 허용한다.
이러한 결합도의 정도는 한 요소가 자신이 의존하고 있는 다른 요소에 대해 알고 있는 정보의 양으로 결정된다.
한 요소가 다른 요소에 대해 더 많은 정보를 알고 있을 수록 두 요소는 강하게 결합된다.
그래서 결합도를 느슨하게 유지하려면 협력하는 대상에 대해 더 적게 알아야하고, 가장 효과정인 방법이 추상화다.
추상화를 통해 불필요한 정보 감추기
어떤 양상, 세부 사항, 구조를 좀 더 명확하게 이해하기 위해서 특정 절차나 물체를 의도적으로 생략하거나 감춰서 복잡도를 극복할 수 있고, 이 것이 추상화다.
추상화가 어떤 의존 대상에게 정보를 감춰야하는지는 3가지로 구분할 수 있다.
- 구체 클래스 의존성 concrete class dependency : 의존하는 대상이 구체 클래스인가?
- 추상 클래스 의존성 abstract class dependency : 의존하는 대상이 추상 클래스인가?
- 인터페이스 의존성 interface dependency : 의존하는 대상이 인터페이스인가?
추상 클래스는 내부 구현과 자식 클래스의 종류에 대한 정보를 숨길 수 있어 더욱 결합도 낮은 추상화를 수행할 수 있다.
인터페이스에 의존한다면, 상속 계층을 모르더라도 협력이 가능해, 어떤 메시지를 수신할 수 있는지만 알 수 있어 추상 클래스 보다도 더 결합도가 낮은 추상화를 수행할 수 있다.
의존성은 명시적이어야한다.
의존성이 명시적이지 않으면, 의존성을 파악하기 위해서 내부 구현을 직접 살펴볼 수 밖에 없다.
또, 이 클래스를 다른 컨텍스트에서 재사용하기 위해 내부 구현을 직접 변경해야한다.
따라서, 의존성을 구현 내부에 숨기지 말고, 명시적으로 표현해서 실행 컨텍스트에 적절한 의존성을 선택할 수 있도록 해야한다.
이를 통해서 퍼블릭 인터페이스로써 의존성을 명시하게되고, 컴파일 타임 의존성을 적절한 런타임 의존성으로 교체할 수 있다.
new로 객체를 생성하는 행위가 결합도를 높일 수 있다.
new 연산자를 사용할 때는 구체 클래스의 이름을 직접 기술하게 되므로, 추상화가 아닌 구체 클래스에 의존해야한다.
그리고, 객체를 생성할 때 어떤 생성자를 호출해야하는지도 알아야하므로, 클라이언트가 알아야하는 지식의 양이 늘어난다.
그래서 new로 객체를 생성하게되면 구체 클래스에 의존하게 되면서 결합도가 높아진다.
물론 이런 객체의 인스턴스를 직접 생성하는 방식이 항상 나쁜 것은 아니다.
default 협력 객체를 설정하고 싶다면 적절하다.
만약, Fruit 인터페이스의 구현 클래스 인스턴스를 선언하는 예제가 있다고 하자.
이 Fruit 인터페이스를 구현하는 클래스는 Apple과 Peach가 있다. 이 중, Fruit 인터페이스에 대한 인스턴스를 협력 객체로 가지고 싶은 클래스가 항상 기본적으로 Apple 객체를 가지고 싶다면 이러한 직접생성하는 방식이 유용한 것이다.
이렇게 주로 협력하는 기본 객체를 설정하고 싶은 경우에는 직접 객체의 인스턴스를 생성하는 방식이 유용하다.
이 경우에 직접 객체의 인스턴스를 생성하면서도 결합도를 비교적 낮추고 싶다면, 기본 객체를 생성하는 생성자를 추가하고, 이 생성자에서 기본 객체로 설정하고싶은 인스턴스의 추상화 타입을 인자로 받는 생성자를 체이닝해야한다.
public class Movie {
private DiscountPolicy discountPolicy;
// 새롭게 추가된 기본 생성자
public Movie(String title, Duration runningTime) {
...
// 체이닝
return this(title, runningTime, fee, new AmountDiscountPolicy(...));
}
// 기존의 생성자
public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy) {
...
this.discountPolicy = discountPolicy;
}
}
생성자가 체인처럼 연결되면서, 클래스의 사용성을 향상시키면서도 유연하게 사용할 수 있다.
'개발 서적 기록 > 오브젝트_조영호' 카테고리의 다른 글
23일차 - 의존성 주입 (0) | 2023.08.25 |
---|---|
22일차 - OCP 적용하기 (0) | 2023.08.24 |
20일차 - 런타임과 컴파일 시점의 의존성을 위해 컨텍스트는 독립되어야한다 (0) | 2023.08.22 |
18일차 - 하향식 기능 분해 설계 (0) | 2023.08.21 |
17일차 - 프로시저 추상화와 데이터 추상화 (0) | 2023.08.19 |