ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • '오브젝트' 책 보고 공부하기 - ⑧ 의존성 관리하기
    JAVA공부/JAVA 2023. 6. 13. 09:09

    1) 의존성 이해하기


    어떤 객체가 협력하기 위해 다른 객체를 필요로 할 때 두 객체 사이에 의존성이 존재하게 된다.

    의존성은 단방향성으로 되어있다.

    의존하고 있는 클래스가 변경된다면 주체도 내부 속성도 같이 변경되어야한다.

     

    UML의 의존관계와 의존성은 다르다.

    UML은 두 요소 사이에 존재할 수 있는 다양한 관계의 하나로 의존 관계를 정의한다.

    의존성은 두 요소 사이에 변경에 의해 영향을 주고 받는 힘의 역학관계가 존재한다는 사실에 초점을 맞춘다.

     

     

    의존성 전이

     

    Movie라는 클래스를 Customer가 의존할 경우, 자연적으로 Movie가 의존하는 대상에 대해서 Customer도 의존한다는 것을

    의미한다. 모든 의존성이 전이되지는 않으며, 이는 캡슐화 정도에 따라 달라진다.

     

     

    런타임과 컴파일 타임

     

    런타임은 애플리케이션이 실행되는 시점을 가리킨다.

    컴파일 타임은 컴파일이 수행되는 시점이 될수도 있고, 코드를 작성을 하는 시점이 될 수 있다.

     

    중요한 것은 런타임과 컴파일타임의 의존성이 다를 수 있다는 것이다.

    예를 들자면, 추상화된 클래스를 의존받는 경우, 런타임 시점에 구현 클래스가 달라질 수 있을 것이다.

    이와같이 설계를 진행할 수록 조금 더 유연해지고 재사용 가능해지는 장점이 있다.

     

    클래스가 문맥에 결합되는 정도에 따라 재사용성이 달라질 수 있는데, 특정한 문맥에 대해 최소한의 가정만으로

    이루어져 있다면 컨텍스트 독립성이라고 한다.

     

    컴파일 타임 의존성은 런타임 의존성으로 대체되어야 한다. 이렇게 교체하는 것을 의존성 해결이라고 하며

    다음과 같은 세가지 방법을 사용할 수 있다.

    1. 객체를 생성하는 시점에 생성자를 통해 의존성 해결

    2. 객체 생성 후 setter 메서드를 통해 의존성 해결 

    3. 메서드 실행 시 인자를 이용해 의존성 해결

    위 세가지를 혼합하여 사용하면  안정적이면서도 유연하게 해결할 수 있다.

     

     


     

    2) 유연한 설계

     

    바람직한 의존성재사용성에 달려있다. 바람직한 의존성 느슨한 결합을 가진다.

    (객체지향에서 말하는 재사용성은 중복 코드 제거만이 아닌 추상화를 통한 다형성 활용을 이야기 하는 것 같다.)

     

    의존하고 있는 객체에 대해 많이 알 수록 결합도가 강해진다. 서로에 대해서 숨기고, 최소한의 메시지만 주고받도록 하자.

    이를 이루기 위한 방법은 추상화이다. 
    구체 클래스 의존성 -> 추상 클래스 의존성 -> 인터페이스 의존성 순으로 결합도가 느슨해진다.

    해당 순으로 알 수 있는 지식의 양도 적어진다.

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

     

    명시적인 의존성 = new AmountPolicy()와 같은 것은 피하고 런타임에 주입(파라미터를 인터페이스로 받자)받도록 해보자.

     

    하나의 객체가 다른 객체에 의존한다는 사실을 퍼블릭인터페이스에 명시적으로 노출하는 경우 명시적인  의존성이라하며,

    객체가 내부에서 다른객체를 직접 생성하는 방식은 의존 사실을 감추므로 숨겨진 의존성이라고 한다.

     

    의존성이 명시적이지 않으면 내부 구현을 모두 살펴보아야 한다. 따라서 의존성을 명시적으로 표현하자.

     

    new 연산자는  결합도를 높인다. new연산자를 사용하면 구체 클래스를 직접 생성하게 됨으로 위에서 말한 숨겨진 의존성

    생기게 된다. 이에따라 겹할도가 높아진다.

    해결 방법은 외부로부터 생성된 인스턴스를 전달 받는 방법으로 해결 할 수 있다.

    사용과 생성의 책임을 분리해서 사용만 해야하는 곳의 결합도를 낮추도록 하자.

     

    가끔, 기본 인스턴스를 넣어주어야 하는 곳에는 사용해도 괜찮지만, 결국에 유연한 설계는 명시적인 의존성을 따르는 것이다.

     

    표준 클래스에 대한 의존은 해롭지 않지만, 되도록이면 추상화에 의존하여 의존성을 명시적으로 드러내자

    ex) List<> = new ArrayList<>();

     

    책에서 중복 할인 정책에 대해서 나오는데, 나는 다른 패턴을 사용하지 않을까 생각했었지만,

    중복 정책을 정의하고, 다른 정책들을 파라미터로 받는 방식으로 처리하는것이 인상 깊었다.
    추상화도 중요하지만, 기존의 유연한 설계를 어떻게 이용하는 지도 매우 중요한 것 같다.

     

    객체 구성을 변경해 시스템의 작동 방식(인스턴스 추가나 제거 또는 조합 변경으로)을 바꿀 수 있도록 하자.

    객체 구성을 관리할 목적으로 작성하는 코드를 객체 네트워크 행위에 대한 선언적인 정의라 한다.

    이렇게 구축하면 목적에 더 집중할 수 있어 시스템 행위를 변경하기가 더 쉽다.

     

     

     

     

     

     

     

     

Designed by Tistory.