Clean Architecture Part 4: Components

tedlim23·2021년 7월 28일
0

컴포넌트란 배포 단위를 뜻한다. 시스템의 구성 요소로 배포할 수 있는 가장 작은 단위를 말한다.

컴포넌트 응집도

Reuse/Release Equivalence Principle

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

소프트웨어 컴포넌트가 릴리즈 절차를 통해 추적 관리되지 않거나 릴리즈 번호가 부여되지 않는다면 컴포넌트를 재사용하고 싶어도 할 수도 없다.

단일 컴포넌트는 응집성 높은 클래스와 모듈들로 구성되어야 한다. 컴포넌트를 구성하는 모든 모듈은 서로 공유하는 중요한 테마나 목적이 있어야 한다.

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

Common Closure Principle

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

단일 컴포넌트는 변경의 이유가 여러개 있어서는 안 된다. 반대로 말하면, 변경이 일어나야 한다면 여러 군데서 발생하기보다 단일 컴포넌트에서 발생하는 편이 낫다. 즉, 같은 이유로 변경될 가능성이 있는 클래스는 모두 한곳으로 묶는 것이 좋다.

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

Common Reuse Principle

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

같이 재사용되는 경향이 있는 클래스와 모듈들은 같은 컴포넌트에 포함해야 한다. 서로 다른 클래스가 강하게 연결되어 있다면 동일한 컴포넌트에 위치해야 한다는 얘기이다.

반대로 말하면, 일부만 의존성이 있는 두 클래스가 있다면 (강하게 결합되지 않은 두 클래스) 동일한 컴포넌트에 위치시켜서는 안 된다.

컴포넌트 결합

Acyclic Dependencies Principle

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

Acyclic 하다는 것은 어느 컴포넌트에서 시작하더라도, 의존성 관계를 따라가면서 최초의 컴포넌트로 되돌아갈 수 없다는 것이다.

  • 수정 사항이 생겼을 때 의존하는 컴포넌트의 개수를 최소화 할 수 있다.
  • 즉, 시스템 구성요소 간 의존성을 파악하고 있으면 빌드하는 방법을 알 수 있다.
  • 의존성 그래프에 순환이 생기면 단위 테스트를 짜기도, 실행하기도 어려워 진다.

의존성 구조 변경하기

순환을 끊기 위해서는 의존성 역전 원칙 (DIP) 를 이용할 수 있다.

출처: http://aeternum.egloos.com/m/2635171

  • PeriodicServiceContractSmsStandardPostingRule 이 cycle 을 이루지 않기 위해 중간에 인터페이스를 생성하여 의존성을 역전시킴

의존성 구조와 관련된 최우선 관심사는 변동성을 격리하는 일이다.

Stable Dependencies Principle

안정성의 방향으로, 즉 더 안정된 쪽에 의존하게 하라. 변경이 쉽지 않은 컴포넌트가 변동이 예상되는 컴포넌트에 의존하게 만들어서는 절대로 안 된다.

안정성은 변경하지 말아야 할 이유가 늘어날 수록 높다고 얘기한다. 이 경우 의존하는 컴포넌트를 책임진다 라고 표현한다. 즉, 변경하기 어렵도록 설계한 컴포넌트는 안정적이어야 한다.

불안정성 계산하기

의존성의 개수를 세어 컴포넌트가 위치상 어느 정도의 안정성을 가지는지 계산할 수 있다.

  • FanIn: 안으로 들어오는 의존성. 컴포넌트 내부의 클래스에 의존하는 외부 클래스의 개수.
  • FanOut: 바깥으로 나가는 의존성. 컴포넌트 외부의 클래스에 의존하는 내부의 클래스의 개수.

I=FanOut/(FanIn+FanOut)I = FanOut / (FanIn+FanOut)

추상 컴포넌트

의존성 역전을 활용하기 위해 인터페이스만을 포함하는 컴포넌트를 만들 수 있다. 이를 추상 컴포넌트라 하는데 자바나 C# 같은 정적 타입 언어를 사용할 때 흔한 전략이다.

파이썬 같은 동적 타입 언어를 사용할 때는 추상 컴포넌트가 존재하지 않기 때문에 추상 컴포넌트로 향하는 의존성도 없다.

Stable Abstractions Principle

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

안정된 컴포넌트는 추상 컴포넌트여야 하며, 불안정한 컴포넌트는 구체 컴포넌트여야 한다.

추상화 정도 측정하기

A = 컴포넌트의 클래스 개수 / 컴포넌트의 추상 클래스와 인터페이스 개수

어떤 컴포넌트에 대해 A, I 를 계산할 수 있다면, main sequence line 에서 떨어진 거리를 측정하여 컴포넌트가 어느정도의 zone 에 위치하는지 파악할 수 있다.

Zone of Pain

컴포넌트는 매우 안정적이며 구체적이다. 추상적이지 않으므로 확장할 수 없고, 안정적이므로 변경하기도 어렵다.

예시로 Database Schema 가 해당될 수 있다. 변동성이 높지만 극단적으로 구체적이며, 엄청 많은 컴포넌트가 여기에 의존한다. 이러한 이유로 스키마가 바뀌면 고통이다 (...)

Zone of Uselessness

컴포넌트는 최고로 추상적이지만, 누구도 그 컴포넌트에 의존하지 않는다.

보통 누구도 구현하지 않은 채 남겨진 추상 클래스인 경우가 많다. 큰 문제를 일으키지는 않지만 이런게 소스코드에 남아있는 게 바람직하지는 않다.

profile
인공지능과 금융생활에 관심이 많은 개발자입니다 ;)

0개의 댓글