본문 바로가기
클린아키텍처

[클린아키텍처] 12장~14장 컴포넌트 원칙

by bzerome240 2022. 3. 6.
SOLID 원칙이 벽과 방에 벽돌을 배치하는 방법을 알려준다면
컴포넌트 원칙은 빌딩에 방을 배치하는 방법을 알려준다.

 

 

컴포넌트

: 시스템의 구성 요소로 배포할 수 있는 가장 작은 단위

ex) 자바의 컴포넌트 = jar 파일, 루비의 컴포넌트 = gem 파일. 닷넷의 컴포넌트 = DLL 파일

  • 잘 설계된 컴포넌트는 독립적으로 배포 가능해야한다

 


컴포넌트 응집도 - 어떤 클래스를 어떤 컴포넌트에 포함시켜야할까?

 

1. REP (Reuse/Release Equivalence Principle) : 재사용/릴리스 등가 원칙

: 재사용 단위는 릴리스 단위와 같다

 

릴리스 절차에는 적절한 공지와 함께 문서 작성도 포함되어야 한다.

-> 단일 컴포넌트는 응집성 높은 클래스와 모듈들로 구성돼야한다.

-> 하나의 컴포넌트로 묶인 클래스와 모듈들은 반드시 함께 릴리스할 수 있어야 한다.

 

 

2. CCP (Common Clousure Principle) : 공동 폐쇄 원칙

  • 물리적 또는 개념적으로 강하게 결합되어 항상 함께 변경되는 클래스들은 하나의 컴포넌트에 속해야 한다. -> 소프트웨어 릴리즈, 재검증, 배포 작업량을 최소화할 수 있다.
  • SRP, OCP와 관련이 있다.

 

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

 

 

3. CRP (Common Reuse Principle) : 공통 재사용 원칙

: 컴포넌트 사용자들을 필요하지 않는 것에 의존하지 않게 하기

: 강하게 결함되지 않은 클래스들을 동일한 컴포넌트에 위치시키면 안된다.

  • ex) 컨테이너 클래스, 해당 클래스의 이터레이터 클래스 -> 서로 강하게 결합되어 있어서 함께 재사용된다. -> 반드시 동일한 컴포넌트에 위치해야 한다
  • 각 컴포넌트에 어떤 클래스들을 포함시켜줘야하는지 설명, 동일한 컴포넌트로 묶으면 안되는 클래스가 무엇인지 설명
  • ISP의 포괄적인 버전

 

 

 

균형 다이어그램

  • REP, CCP - 포함원칙 -> 컴포넌트를 더욱 크게 만든다
  • CRP - 배제원칙 -> 컴포넌트를 더욱 작게 만든다.

=> 이 원칙들이 균형을 이뤄야한다.

 

https://velog.io/@geunwoobaek/%ED%81%B4%EB%A6%B0%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%9D%91%EC%A7%91%EB%8F%84

 


 

컴포넌트 결합 - 컴포넌트 사이의 관계

 

1. ADP (Acyclic Dependencies Principle) : 의존성 비순환 원칙

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

 

숙취 증후군 ?

: 많은 개발자가 동일한 소스 파일을 수정하는 환경에서 발생

  • ex) 마지막 수정으로 인해 다시 수정해야하는 상황 
  • 해결책 -> 1. 주단위 빌드, 2. ADP

 

방법1) 주단위 빌드 (weekly build)

  • 중간 규모의 프로젝트에서 흔히 사용됨
  • 방법: 4일동안은 개인 개발 -> 금요일 변경된 코드를 모두 통합하여 시스템 빌드
  • 단점: 하루만에 해결되지 않는다 -> 빌드 일정이 늘어나고, 빌드 주기가 늦어지며, 통합 테스트가 어려워짐

 

방법2) 순환 의존성 제거하기

  • 개발환경을 릴리스 가능한 컴포넌트 단위로 분리 -> 컴포넌트는 개발자 또는 개발팀이 책임질 수 있다
  • 방법: 작업 후 컴포넌트를 릴리스 -> 다른 개발자는 해당 릴리스를 사용할지 말지 정해서 개발
  • 장점: 특정 컴포넌트가 다른 컴포넌트에 영향을 주지 않는다.
  • 주의할점: 컴포넌트 사이의 의존성 구조를 반드시 관리해야한다. 서로 순환이 있어서는 안된다

 

순환 의존성이 발생하면 컴포넌트를 어떤 순서로 빌드해야할지 모른다

 

 

컴포넌트 다이어그램

https://share-factory.tistory.com/22

주의할점: 어느 컴포넌트에서 시작하더라도 의존성 관계를 따라가면서 최초의 컴포넌트로 돌아갈 수 없다!

-> 구조에 순환이 없다 -> 비순환 방향 그래프 (DAG Directed Acyclic Graph)

 

시스템 전체를 릴리스해야한다면 릴리스 절차는 상향식으로 진행된다. (Entities -> Database, Interactors -> Presenters, View, Controllers, Authorizer -> Main 순으로 컴파일, 테스트, 릴리스한다.)

 

흐트러짐 Jitters

: 요구사항이 변경되면 컴포넌트 구조도 변경될 수 있다.

  • 애플리케이션이 성장할수록, 순환이 발생하는지 항상 관찰해야한다. -> 발생하면 어떤식으로든 끊어야 한다.
  • 순환을 끊는 법: 1) 새로운 컴포넌트를 생성 2) 컴포넌트 간의 의존성을 역전시킨다 (DIP)

 

하향식 설계 (top-down)

컴포넌트 구조는 하향식으로 설계될 수 없다, 컴포넌트는 시스템이 성장하고 변경될 때 함께 진화한다.

 

컴포넌트 의존성 다디어그램은 애플리케이션의 빌드가능성, 유지보수성을 보여준다.

-> 컴포넌트 구조는 프로젝트 초기에 설계 불가능 

-> 그래도 숙취 증후군을 겪지 않으려면, 의존성 관리 필요 (SRP, CCP)

 

 

2. SDP (Stable Dependencies Principle) : 안정된 의존성 원칙

: 더 안정된 쪽에 의존하기

 

변경이 쉽지 않은 컴포넌트가 변동이 예상되는 컴포넌트에 의존하게 만들어서는 안된다.

-> SDP를 준수하면 변경하기 어려운 모듈이 변경하기 쉽게 만들어진 모듈에 의존하지 않도록 만들 수 있다.

 

 

안정된 컴포넌트 vs 불안정한 컴포넌트

https://share-factory.tistory.com/25?category=970125

왼쪽 

X는 어디에도 의존하지 않는다. X를 변경이 발생하게 할 수 없음 -> 안정적인 컴포넌트, 독립적

오른쪽

Y는 세개의 컴포넌트에 의존하므로 변경이 발생할 수 있는 외부 요인이 3가지 이다. -> 불안정한 컴포넌트, 의존적

 

 

안정성 지표

1) Fan-in

: 안으로 들어오는 의존성

: 컴포넌트 내부의 클래스에 의존하는 컴포넌트 외부의 클래스의 개수

 

2) Fan-out

: 바깥으로 나가는 의존성

: 컴포넌트 외부의 클래스에 의존하는 컴포넌트 내부의 클래스의 개수

 

3) I (불안정성)

  • I = Fan-out / (Fan-in + Fan-out)
  • I = 0 : 최고로 안정된 컴포넌트 
  • I = 1 : 최고로 불안정한 컴포넌트 

 

모든 컴포넌트가 안정적일 수는 없다.

-> 불안정한 컴포넌트, 안정된 컴포넌트로 구성되는게 이상적인 구조

 

 

* 다이어그램에서 불안정한 컴포넌트를 위에둔다

 

SDP 위반 -> DIP 도입하여 해결하기

https://hwannny.tistory.com/33

 

왼쪽

안정적인 컴포넌트 Stable 가 불안정한 컴포넌트 Flexible 에 의존성을 걸었다 -> SDP 위반

 

오른쪽

DIP 도입하여 해결 -> 추상 컴포넌트를 생성하여 두 컴포넌트가 모두 UServer 컴포넌트를 의존하도록 한다.

-> UServer은 I = 0 이되며, Flexible은 I = 1을 유지

 

 

3. SAP (Stable Abstractions Principle) : 안정된 추상화 원칙

 

컴포넌트는 안정된 만큼만 추상화되어야 한다

 

컴포넌트가 안정된 상태이면서(I=0) 동시에 변경에 충분히 대응할 수 있을까? -> OCP

 

SAP는 의존성이 반드시 안정성의 방향으로 향해야 한다고 말하며, SAP에서는 안정성이 결국 추상화를 의미한다고 말하기 때문에 -> SAP와 SDP를 결합하면 컴포넌트에 대한 DIP가 된다. -> 의존성은 추상화의 방향으로 향하게 된다.

 

클래스는 추상적이거나 아니거나 둘 중 하나다.

 

 

 

728x90
반응형

댓글