본문 바로가기

Design/Architecture

[Clean Architecture] 컴포넌트 사이의 관계와 원칙(2) : SDP

SDP(안정된 의존성 원칙)란?

안정성의 방향으로(더 안정된 쪽에) 의존하라

즉, 변경하기 어려운 모듈이 변경하기 쉽게 만들어진 모듈에 의존하지 않도록 만들어야한다.

 

 

그렇다면 안전성이란?

  • 사전적으로는 ‘쉽게 움직이지 않는’으로 정의.
  • 안정성은 변경을 위해 필요한 작업량과 관련된다.
  • 안정성이 높으면 상당한 작업량이 필요함.
    (탁자를 뒤집는 것과 옆으로 세워진 동전을 넘어뜨리는 것을 생각해보자)

 

소프트웨어 관점에서의 안정성

  • 컴포넌트 변경이 어려운 요인에는 크기, 복잡도, 간결함 등이 있음.
  • 컴포넌트 변경이 어려운 가장 확실한 방법은 “수많은 컴포넌트가 해당 컴포넌트에 의존하게 만드는 것이다.” 
  • 안정적인 컴포넌트
    - X는 안정된 컴포넌트.
    - 세 컴포넌트가 x에 의존함에 따라 X컴포넌트는 변경하지 말아야할 이유가 세 가지나 된다.
    - "X는 세 컴포넌트를 책임진다"
    - X가 변경되도록 만들 수 있는 외적인 영향은 전혀 없다. => 독립적이다.(independent)

[Clean Architecture] X는 안정된 컴포넌트

  • 불안정한 컴포넌트
    - Y는 상당히 불안정한 컴포넌트.
    - 어떤 컴포넌트도 Y에 의존하지 않는다.
    - "Y는 책임성이 없다."
    - Y는 세 컴포넌트에 의존함에 따라 변경이 발생할 수 있는 외부 요인이 세 가지다.
    - Y는 의존적이다.

[Clean Architecture] Y는 상당히 불안정한 컴포넌트

 

안정성 지표

의존성은 컴포넌트로 들어오고(Fan-in) 나가는(Fan-out) 의존성의 개수를 세어보는 방법으로 측정할 수 있다.

 

  • Fan-in : 안으로 들어오는 의존성. 내부의 클래스에 의존하는 컴포넌트 외부의 클래스 개수.
  • Fan-out : 바깥으로 나가는 의존성. 컴포넌트 외부의 클래스에 의존하는 내부의 클래스 개수.
  • I(불안정성) : I Fan-out / (Fan-in + Fan-out)
    - I는 [0,1] 범위를 가짐
    - I가 0이면 최고로 안정된 컴포넌트
    - I가 1이면 최고로 불안정한 컴포넌트
  • 자바의 경우 I는 import 구문과 완전한 클래스 이름(fully qualified name)의 개수를 세어서 계산할 수 있음.
  • 의존성 방향으로 갈수록 I 지표 값이 감소해야 한다. (안정적인 컴포넌트에 의존)

 

I값이 1이면..

- 어떤 컴포넌트도 해당 컴포넌트에 의존하지 않음 (Fan-in = 0)

- 해당 컴포넌트는 다른 컴포넌트에 의존함 (Fan-out > 0)

- 최고로 불안정한 컴포넌트.

- 다른 컴포넌트에 의존한다는 사실은 언젠가는 해당 컴포넌트를 변경해야 할 이유가 있다는 뜻.

 

I값이 0이면...

- 해당 컴포넌트에 의존하는 다른 컴포넌트가 있음 (Fan-in > 0)

- 해당 컴포넌트는 다른 컴포넌트에 의존하지 않음 (Fan-out = 0)

- 최고로 안정된 상태의 컴포넌트.

- 의존하는 컴포넌트로 인해 변경이 어려우나 해당 컴포넌트의 변경을 강제하는 컴포넌트는 없음.

 

 

SDP를 위반할 경우, 해결책

의존성 방향으로 갈수록 I 값은 감소해야하지만, 그렇지 못할 경우에는 DIP를 도입하면 된다.

 

[Clean Architecture] Stable이 Flexible에 의존하는 상황

  • 위 case에서 Stable의 I가 Flexible의 I 보다 작다고 가정한다.
  • 따라서 Stable은 상대적으로 안정적이고 Flexible은 상대적으로 불안정한 컴포넌트.
  • Stable이 Flexible에 의존하는 것은 SDP를 위배한 케이스이다.(Stable의 U클래스가 Flexible의 C클래스를 사용중)
  • 이 문제 해결을 위해 DIP를 활용.

[Clean Architecture] DIP를 이용하여 의존성을 해결

  • UServer컴포넌트에 US라는 이름으로 Stable그리고 Flexible 양쪽에 의존하는 interface를 만든다.
  • US에는 U가 사용하는 모든 메서드가 반드시 선언되어야함.
  • 클래스 U는 US를 사용하고, C는 US를 implement한다.
  • UServer는 I=0으로 매우 안정된 상태.
  • 이제 모든 의존성은 I가 감소하는 방향을 향한다.