13장. 컴포넌트 응집도

2023. 5. 24. 09:12DDD/CleanArchitecture

소개

클린아키텍처: 소프트웨어 구조와 설계의 원칙 책을 읽고 정리하며 소감을 적는 포스트입니다.

컴포넌트 응집도

어떤 클래스를 어느 컴포넌트에 포함시켜야 할까? 이 장에서는 컴포넌트 응집도와 관련된 세 가지 원칙을 논의한다.

  • REF : 재사용/릴리스 등가원칙(Reuse/Release Equivalence Principle)
  • CCP : 공통 폐쇄 원칙(Commom Closure Principle)
  • CRP : 공통 재사용 원칙(Common Reuse Principle)

REP: 재사용/릴리스 등가 원칙

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

우리는 이제 소프트웨어 재사용의 시대에 살고 있다. 객체 지향 모델의 오랜 약속 중 하나가 실현되었다.

돌이켜 보면 재사용/릴리스 등가 원칙(REP)는 너무 당연하다. 릴리스 번호가 없다면 재사용 컴포넌트들이 서로 호환되는지 보증할 방법이 전혀 없다.

이 원칙을 소프트웨어 설계와 아키텍처 관점에서 보면 단일 컴포넌트는 응집성 높은 클래스와 모듈들로 구성되어야 함을 뜻한다. 컴포넌트를 구성하는 모든 모듈은 서로 공유하는 중요한 테마나 목적이 있어야 한다.

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

하지만 이것으로 클래스와 모듈을 단일 컴포넌트로 묶는 방법을 제대로 설명 할 수 없다.

이 원칙의 약점은 다음에 다룰 두 원칙이 지닌 강점을 통해 충분히 보완할 수 있다.

실제로 CCP와 CRP는 REP를 엄격하게, 하지만 제약을 가하는 측면에서 정의한다.

CPP : 공통 폐쇄 원칙

동일한 이유로 동일한 시점에 변경되는 클래스를 같은 컴포넌트로 묶어라

서로 다른 시점에 다른 이유로 변경되는 클래스는 다른 컴포넌트로 분리하라

이 원칙은 단일 책임 원칙(SRP)을 컴포넌트 관점에서 다시 쓴 것이다.

대다수의 애플리케이션에서 유지보수성(maintainability)은 재사용성보다 훨씬 중요하다. 애플리케이션에서 코드가 반드시 변겨오디어야 한다면, 이러한 변경이 여러 컴포넌트 도처에 분산되어 발생하기보다는, 차라리 변경 모두가 단일 컴포넌트에서 발생하는 편이 낫다.

CCP는 같은 이유로 변경될 가능성이 있는 클래스는 모두 한곳으로 묶을 것을 권한다. 이를 통해 소프트웨어를 릴리스, 재검증, 배포하는 일과 관련된 작업량을 최소화 할 수 있다.

이 원칙은 개발 폐쇄 원칙(OCP)와 밀접하게 관련되어 있는데, CCP에서 말하는 폐쇄(closure)는 OCP에서 말하는 폐쇄(closure)와 그 뜻이 같다.

100% 폐쇄란 불가능하므로 전략적으로 폐쇄해야 한다. 우리는 발생할 가능성이 있거나 과거에 발생했던 대대수의 공통적인 변경에 대해서 클래스가 닫혀 있도록 설계한다.

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

SRP와의 유사성

CCP는 컴포넌트 수준의 SRP다. SRP에서는 서로 다른 이유로 변경되는 메서드를 서로 다른 클래스로 분리하라고 말한다.

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

CRP: 공통 재사용 원칙

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

공통 재사용 원칙(CRP)도 클래스와 모듈을 어느 컴포넌트에 위치시킬지 결정할 때 도움되는 원칙이다. CRP에서는 같은 재사용되는 경향이 있는 클래스와 모듈들은 같은 컴포넌트에 포함해야 한다고 말한다.

예를 들어 컨테이너(container) 클래스와 해당 클래스의 이터레이터(iterator) 클래스를 들 수 있다. 이들 클래스는 서로 강하게 결합되어 있기 때문에 함께 재사용된다. 따라서 이들 클래스는 반드시 동일한 컴포넌트에 위치해야 한다.

컴포넌트가 다른 컴포넌트를 사용하면 의존성이 생긴다. 사용되는 컴포넌트가 변경되면 사용하는 컴포넌트 또한 변경 될 가능성이 높다.

따라서 의존하는 컴포넌트가 있다면 해당 컴포넌트의 모든 클래스에 대해 의존함을 확실히 인지해야 한다. 바꿔 말하면, 한 컴포넌트에 속한 클래스들은 더 작게 그룹지을 수 없다. 즉, 일부 클래스에만 의존하고 다른 클래스와는 독립적일 수 없음을 확실히 인지해야 한다.

ISP와의 관계

CRP는 인터페이스 분리 원칙(ISP)의 포괄적인 버전이다.

필요하지 않은 것에 의존하지 말라

컴포넌트 응집도에 대한 균형 다이어그램

아마도 응집도에 관한 세 원칙이 서로 상충된다는 사실을 눈치챘을 거라고 본다.

REP와 CCP는 포함(include)원칙이다. 즉, 두 원칙은 컴포넌트를 더욱 크게 만든다.

CRP는 배제(exclusive)원칙이며, 컴포넌트를 더욱 작게 만든다.

아래의 그림은 균형(tension) 다이어그램으로, 응집도에 관한 세 원칙이 서로 어떻게 상호작용하는지 보여준다.

  • REP와 CRP에만 중점을 두면, 사소한 변경에 너무 많은 컴포넌트에 영향을 미친다.
  • CCP와 REP에만 과도하게 집중하면 불필요한 릴리스가 너무 빈번해진다.
  • CRP와 CCP에만 집중하게 되면 재사용성이 떨어지게 된다.

일반적으로 프로젝트는 삼각형의 오른쪽에서 시작하는 편이며, 이때는 오직 재사용성만 희생하면 된다.

프로젝트가 성숙하고, 그 프로젝트로부터 파생된 또 다른 프로젝트가 시작되면, 프로젝트는 삼각형에서 점차 왼쪽으로 이동해 간다.

결론

과거의 결합도에 대한 우리의 인식 수준이 REP, CCP, CRP가 의미하는 것보다는 훨씬 단순했다.

응집도를 모듈은 단 하나의 기능만 수행해야 한다는 속성 정도로 단순하게 이해한적도 있다.

어느 클래스들을 묶어서 컴포넌트로 만들지를 결정할 때, 재사용성과 개발 가능성이라는 상충하는 힘을 반드시 고려해야 한다. 심지어 이 균형점은 거의 항상 유동적이다.

'DDD > CleanArchitecture' 카테고리의 다른 글

15장. 아키텍처란?  (0) 2023.05.25
14장. 컴포넌트 결합  (0) 2023.05.24
12장. 컴포넌트 원칙  (0) 2023.05.23
11장. DIP, 의존성 역전 원칙  (0) 2023.05.23
10장. ISP, 인터페이스 분리 원칙  (0) 2023.05.22