[클린아키텍처] 12장. 컴포넌트

4부. 컴포넌트 원칙

SOLID가 벽과 방에 벽돌을 배치하는 방법이라면,
컴포넌트는 빌딩에 방을 배치하는 방법이다. => 더 큰 개념이다..?

목표

12장. 컴포넌트

컴포넌트는 배포 단위이다. 시스템의 구성 요소로 배포할 수 있는 가장 작은 단위이다. => 무슨말이지? 잘 이해가 안된다. 여러 컴포넌트를 링크??? 잘 설계된 컴포넌트라면 반드시 독립적으로 배포 가능한, 따라서 독립적으로 개발 가능한 능력을 갖춰야 한다.

13장. 컴포넌트 응집도

3가지 원칙

1. 재사용/릴리스 등가 원칙(REP)

재사용 단위는 릴리스 단위와 같다. 단일 컴포넌트는 응집성 높은 클래스와 모듈들로 구성되어야 한다. why? 단순히 뒤죽박죽 임의로 선택된 클래스와 모듈은 XX

하나의 컴포넌트로 묶인 클래스와 모듈은 반드시 함께 릴리스 할 수 있어야 한다. ㄴ 버전 번호가 같아야하고, 동일한 릴리스로 추적관리되고, 동일한 릴리스 문서에 포함되어야 한다.

이 원칙을 어기면 쉽게 들통난다.

2. 공동 폐쇄 원칙(CCP)

동일한 이유로 동일한 시점에 변경되는 클래스를 같은 컴포넌트로 묶어라. 서로 다른 시점에 다른 이유로 변경되는 클래스는 다른 컴포넌트로 분리하라.

why? 변경 시 해당 컴포넌트만 재배포하면 되므로. (다른 컴포넌트는 재배포 불필요)

이를 통해 소프트웨어를 릴리스, 재검증, 배포하는 일과 관련된 작업량을 최소화할 수 있다.

CCP와 OOP => CCP에서는 동일한 유형의 변경에 대해 닫혀있는 클래스들을 하나의 컴포넌트로 묶음으로써 OCP에서 얻은 교휸을 확대 적용한다.

CCP와 SRP => 동일한 시점에 동일한 이유로 변경되는 것들을 한데 묶어라. 서로 다른 시점에 다른 이유로 변경되는 것들은 서로 분리하라.

3. 공통 재사용 원칙(CRP)

컴포넌트 사용자들을 필요하지 않는 것에 의존하게 강요하지 말라.

즉, 같이 재사용되는 경향이 있는 클래스와 모듈들은 같은 컴포넌트에 포함해라.

개별클래스들은 다른 클래스들과 상호작용한다. 이런 상호작용하는 클래스들은 동일한 컴포넌트에 포함되어야 한다.

CRP는 어떤 클래스를 하나의 컴포넌트로 묶어도 되는지 보다는, 어떤 클래스를 묶어서는 안 되는지에 대해 이야기한다. 강하게 결합되지 않은 클래스들을 동일한 컴포넌트에 위치시켜서는 안된다. => 사용하는 컴포넌트가 사용되는 컴포넌트에서 단 하나의 클래스만 사용하는 경우. 의존성은 조금도 약해지지 않는다. => 사용되는 컴포넌트의 변경마다 사용하는 컴포넌트도 변경해야 할 가능성이 있다. => 필요 이상으로 많은 컴포넌트를 재배포하는 낭비를 할 수도 있다.

CRP와 ISP => ISP: 사용하지 않는 메서드가 있는 클래스에 의존하지 말라 => CRP: 사용하지 않는 클래스를 가진 컴포넌트에 의존하지 말라

1,2,3

image

균형 삼각형에서 우리 팀에 맞게 포지션을 잡아야 함. eg. 프로젝트초기: CCP보다 REP가 더 중요함. why? 개발가능성이 재사용성보다 중요하기 때문.

일반적으로 프로젝트는 오른쪽에서 시작하며, 점차 왼쪽으로 이동해간다.

프로젝트의 컴포넌트 구조는 시간과 성숙도에 따라 변한다.

14장. 컴포넌트 결합

1. 의존성 비순환 원칙(ADP)

컴포넌트 의존성 그래프에 순환이 있어서는 안된다.

개발 환경을 릴리스 가능한 컴포넌트 단위로 분리

2. 안정된 의존성 원칙(SDP)

의존성은 반드시 안정성의 방향으로 향해야 한다.

안정성은 변화가 발생하는 빈도와는 직접적인 관련이 없다.
안정성은 변경을 위해 얼마나 리소스가 필요한가와 관련있다. ‘안정’ 의 사전뜻: 쉽게 움직이지 않는

컴포넌트 불안정성(I) 측정

자바에서 불안정성(I) 계산법 import 구문full qualified name 의 개수를 세어서 계산할 수 있다.

모든 컴포넌트가 안정적이어야 하는가? 아니다. 모든 컴포넌트가 최고로 안정적인 시스템은 변경이 불가능하다. 설계에는 불안정한 컴포넌트도 있고 안정된 컴포넌트도 존재한다. 중요한건 불안정한 컴포넌트는 안정된 컴포넌트를 의존해야 하며, 안정된 컴포넌트가 불안정한 컴포넌트를 의존하는 경우가 존재하는 경우 DIP를 이용하여 의존성의 방향을 역전시켜야 한다.

 

3. 안정된 추상화 원칙(SAP)

안정성은 결국 추상화다.

SDP + SAP = 의존성은 추상화의 방향으로 향한다.

 

고수준 정책을 어디에 위치시켜야 하는가?
-> 안정된 컴포넌트. 불안정한 컴포넌트에는 쉽고 빠르게 변경가능한 것을 포함해야 함.

Q) 컴포넌트가 안정된 상태이면서 동시에 변경에 충분히 대응하도록 만드는 법
-> OCP. 추상클래스

안정된 컴포넌트는 추상 컴포넌트여야 한다.
불안정한 컴포넌트는 반드시 구체 컴포넌트여야 한다.

-> 안정적인 컴포넌트를 인터페이스/추상클래스로 구성하여 쉽게 확장할 수 있어야 한다. 안정된 컴포넌트가 확장이 가능해지면 유연성을 얻게 되고 결국 아키텍처를 과도하게 제약하지 않는다.

 

컴포넌트 추상화 정도(A) 측정

추상화 정도(A) (0.0 <= A <= 1.0)

 

주계열 구하기

주계열: 안정성(I)과 추상화 정도(A) 사이의 관계
ㄴ (사전뜻: 관측된 모든 별 중의 90%가 표시되어 있는 좁은 띠)

CleanShot 2021-04-14 at 01 41 10@2x

(여기서는 두개의 축이 있지만,
만약 하나의 축이 추가된다면 변동성 일 것이다.)

 

고통의 구역 (bad)

추상클래스/인터페이스가 거의 없으며, 매우 안정한 컴포넌트.

추상적이지 않다. -> 확장이 어렵다. 안정적이다. -> 변경하기 어렵다.

eg1. DB 스키마 (매우 구체적이며 많은 컴포넌트가 의존함.) ㄴ 예시 이해 안됨.

eg2. 구체적인 유틸리티 라이브러리(String.class)
ㄴ I 지표가 1일지라도, 실제로 변동성이 거의 없다.
ㄴ 굉장히 광범위하게 사용된다.

 

쓸모없는 구역 (bad)

매우 추상적이면서 다른 컴포넌트의 의존성이 없는 컴포넌트

쓸모가 없다. 폐기물과도 같다.

 

주계열 (good)

안정성에 비해 너무 추상적이지 않으며, 추상화정도에 비해 너무 불안정하지도 않은 컴포넌트.

즉, 컴포넌트가 추상화된 수준에 어울릴 정도로만 다른 컴포넌트가 의존하거나, 구체화된 수준에 어울릴 정도로만 다른 컴포넌트에 의존함.

 

측정해보기: 주계열과 얼마나 떨어져있는가?

거리(D) = | A + I - 1 |

활용법 1. 표준편차를 이용

  1. 각 컴포넌트의 거리(D) 를 계산한다.
  2. 모든 거리를 통해 표준편차를 구한다.
  3. 극히 예외적인 컴포넌트를 식별한다.

CleanShot 2021-04-14 at 02 21 40@2x

활용법 2. 임계값 지정

  1. 관리가 필요한 거리 임계값을 정해둔다.
  2. 릴리즈 시에 모든 컴포넌트의 거리(D) 를 계산한다.
  3. 임계값을 초과한 컴포넌트가 있을 경우 원인을 조사한다.

CleanShot 2021-04-14 at 02 20 02@2x

참고. 지표는 신이 아니다. 이러한 지표는 아무리 해도 불안전하다. 하지만 이 지표로부터 무언가 유용한 것을 얻길 바란다(?)