[오브젝트] 의존성 관리하기

의존성 관리하기

유연하고 재사용 가능한 설계는 객체가 어떻게 하는지를 나열하지 않고도 객체들의 조합을 통해 무엇을 하는지를 표현하는 클래스들로 구성된다. 이런 설계를 위해서는 결합도가 낮은 설계가 필요하다. 결합도가 낮은 설계는 유연하고 확장을 쉽게 할 수 있도록 돕는다. 그리고 이런 설계를 위해서는 런타임 의존성과 컴파일 타임 의존성이 달라야 한다. 즉, 구체 클래스에 대해 의존하는것 보다 클래스가 사용될 특정한 문맥에 대해 최소한의 가정만으로 이루게 한다면 다른 문맥에서 재사용하기가 쉬워진다. 이를 컨텍스트 독립성이라 한다. 그렇다면 클래스가 실행 컨택스트에 독립적이면서 런타임에 실행 컨텍스트에 적절한 객체들과 협력할 수 있게 하는 방법은 무엇일까?

  • 생성자를 통한 의존성 해결
  • setter를 통한 의존성 해결
  • 메서드 실행 시 인자를 이용한 의존성 해결

생성자나 setter를 통한 의존성 해결은 이 전 포스팅에 많이 설명해 두었다. 그렇다면 메서드를 통한 의존성 해결은 어떤걸까? 만약 클래스가 항상 다른 클래스의 존재에 대해 알 필요가 없고 특정 동작을 할 때만 일시적으로 알아도 무방하다면 이를 메소드의 인자로 넘겨 사용할 수 있다.

유연한 설계

유연한 설계를 위해서는 몇 가지 원칙과 기법이 필요하다.

의존성과 결합도

앞에서 말한 컨텍스트 독립성과 이어지는 이야기다. 설계를 할 때 특정 컨텍스트에 강하게 결합되는 상황은 의존성이 바람직하지 않은 경우이다. 이와 반대로 어떤 의존성이 다양한 환경에서 재사용이 가능하다면 바람직한 의존성이다. 즉 의존성은 재사용과 관련이 있다. 그리고 이를 결합도로 표현할 수 있다. 바람직하지 않은 의존성은 결합도가 강한것이고 바람직한 의존성은 결합도가 약한 것이다.

추상화에 의존하라

추상화와 결합도 관점에서는 다음과 같이 구분할 수 있다.

  • 구체 클래스 의존성
  • 추상 클래스 의존성
  • 인터페이스 의존성

구체 클래스에 비해 추상 클래스는 메소드의 내부 구현과 자식 클래스의 종류에 대한 지식을 클라이언트에게 숨길 수 있다. 그렇기 때문에 추상 클래스가 구체 클래스보다 결합도가 낮다. 하지만 추상 클래스의 클라이언트는 여전히 협력하는 대상이 속한 클래스 상속 계층이 무엇인지에 알고 있어야 한다.

인터페이스에 의존하면 상속 계층을 모르더라도 협력이 가능해진다. 인터페이스 의존성은 협력하는 객체가 어떤 메세지를 수신할수 있는지에 대한 정보만 남기 때문에 추상 클래스보다 결합도가 낮다. 이 내용에서 알 수 있는 것은 실행 컨텍스트에 대해 알아야 하는 정보를 줄일수록 결합도가 낮아지는 것이다.

생성자 체이닝

생성자 내부에서 new를 통해 구체 클래스를 생성하는 경우에는 결합도가 높아진다. 이를 숨은 의존성이라 한다. 구체 클래스를 생성하기 위해 구체 클래스가 가진 정보들과 함께 하위 의존성을 다 알아야할 필요가 생길 수 있다. 다만 가끔은 이런 방법이 유용한 경우도 있다. 다음과 같은 코드가 있다고 가정하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public interface Student {
}

public class Junior implements Student{
}

public class Senior implements Student{
}

public class Teacher {
private Student student;

public Teacher() {
this(new Junior());
}

public Teacher(Student student) {
this.student = student;
}
}

위 코드에서 가정을 하자면 선생이라는 주체는 대부분의 경우 주니어를 담당하지만 가끔은 시니어를 담당한다고 가정하자. 이럴 경우에는 생성자 체이닝을 통해 기본적으론 주니어를 생성하되, 다른 학생들도 생성할 수 있도록 연결해 줄 수 있다. 이런 특수한 상황에서 모든 학생 객체의 생성 책임을 클라이언트로 옮긴다면 클라이언트간 중복이 심해지고 선생 객체의 사용성도 나빠질 수 있다.

Author: Song Hayoung
Link: https://songhayoung.github.io/2021/01/16/Object/object8/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.