새소식

반응형
Study/오브젝트

[Object] 8장 : 의존성 관리하기

  • -
반응형

 

객체지향 설계의 핵심은

협력을 위해 필요한 의존성은 유지하면서도 변경을 방해하는 의존성은 제거하는 데 있다

의존성 이해하기

변경과 의존성

의존성은 실행 시점과 구현 시점에 서로 다른 의미를 가진다

의존성은 함께 변경될 수 있는 가능성을 의미, 모든 경우에 의존성이 전이되는 것은 아니다

의존성이 실제로 전이될지 여부는 견경의 방향과 캡슐과의 정도에 따라 달라진다.

 

런타임 의존성과 컴파일타임 의존성

  • 런타임 의존성 : 객체 사이의 의존성 
  • 컴파일타임 의존성 : 클래스 사이의 의존성 

런타임 의존성과 컴파일타임 의존성이 다를 수 있다

 

컨텍스트 독립성

클래스가 사용될 특정한 문맥에 대해 최소한의 가정만으로 이뤄져 있다면

다른 문맥에서 재사용하기가 더 수월해진다.

 

의존성 해결

컴파일타임 의존성을 실행 컨텍스트에 맞는 적절한 런타임 의존성으로 교체하는 것

 

의존성 해결 방법 

  • 객체를 생성하는 시점에 생성자를 통해 의존성 해결
  • 객체 생성 후 setter 메서드를 통해 의존성 해결 
    • 객체를 생성한 이후에도 의존하고 있는 대상을 변경할 수 있다.
    • 의존 대상 설정 전까지는 불완전 상태
  • 메서드 실행 시 인자를 이용해 의존성 해결
    • 협력 대상에 대해 지속적으로 의존 관계를 맺을 필요 없이 메서드가 실행되는 동만만 일시적으로 의존 관계가 존재해도 무방하거나,
    • 메서드가 실행될 때마다 의존 대상이 매번 달라져야 하는 경우에 유용

유연한 설계

의존성과 결합도

  • 의존성은 두 요소 사이의 관계 유무
    • (e.g. "의존성이 존재한다.") 
  • 결합도는 두 요소 사이에 존재하는 의존성의 정도를 상대적으로 표현
    • (e.g. "결합도가 느슨하다")

모든 의존성이 나쁜 것은 아니다. 의존성은 객체들의 협력을 가능하게 만드는 매개체라는 관점에서 바람직하지만, 의존성이 과하면 문제가 될 수 있다

 

지식이 결합을 낳는다

결합도를 느슨하게 만들기 위해서는 협력하는 대상에 대해 필요한 정보 외에는 최대한 감추는 것이 중요 -> 추상화

 

추상화에 의존하라

추상화 : 특정 절차나 물체를 의도적으로 생략하거나 감춤으로써 복잡도를 극복하는 방법 

대상에 대해 알아야 하는 지식의 양을 줄일 수 있기 때문에 결합도를 느슨하게 유지할 수 있다. 

의존하는 대상이 더 추상적일수록 결합도는 더 낮아진다.

 

의존 대상 구분 (아래쪽으로 갈수록 알아야 하는 지식의 양이 적어지기 때문에 결합도가 느슨) 

  • 구체 클래스 의존성 
  • 추상(abstract) 클래스 의존성 
  • 인터페이스(interface) 의존성

 

명시적인 의존성 (explicit dependency)

퍼블릭 인터페이스에 의존성을 명시적으로 노출하는 것

<-> 숨겨진 의존성(hidden dependency)

 

new는 해롭다

  • new 연산자 사용을 위해 구체 클래스의 이름을 직접 기술해야 한다. 
    • new를 사용하는 클라이언트는 추상화가 아닌 구체 클래스에 의존할 수밖에 없기 때문에 결합도가 높아진다. 
  • new 연산자는 생성하려는 구체 클래스뿐만 아니라 어떤 인자를 이용해 클래스의 생성자를 호출해야 하는지도 알아야 한다. 
    • new를 사용하면 클라이언트가 알아야 하는 지식의 양이 늘어나기 때문에 결합도가 높아진다.

new로 인한 결합도 증가 해결 방법 

  • 인스턴스를 생성하는 로직과 생성된 인스턴스를 사용하는 로직을 분리
    • 직접 인스턴스를 생성해서는 안 된다. 단지 해당하는 인스턴스를 전달받아(생성자, setter, 인자를 통해) 사용하기만 해야 한다.
    • 생성하는 책임을 클라이언트로 옮기고, 생성된 인스턴스를 사용하는 책임만 남겨야 한다
      • 사용과 생성의 책임을 분리하고 생성하는 책임을 클라이언트로 옮김
      • 의존성을 생성자에 명시적으로 드러냄
      • 구체 클래스가 아닌 추상 클래스에 의존

 

가끔은 생성해도 무방하다

 

표준 클래스에 대한 의존은 해롭지 않다. 

변경될 확률이 거의 없는 클래스라면 의존성이 문제 되지 않는다

 

컨텍스트 확장하기

public class Movie {
	private DiscountPolicy discountPolicy;
    
    public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy) {
    	this.discountPolicy = discountPolicy;
    }
}

 

생성자에서 받는 타입이 추상화되어 있기 때문에 원하는 대로 바꾸어 적용할 수 있다

Movie avatar = new Movie("아바타", Duration.ofMinutes(120), Money.wons(10000),
            new PercentDiscountPolicy())

Movie avatar = new Movie("아바타", Duration.ofMinutes(120), Money.wons(10000),
            new NoneDiscountPolicy())
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.