22장 클린 아키텍처
여러 아키텍처들의 목표는 모두 같은데, 바로 관심사의 분리다. 이들은 모두 소프트웨어를 계층으로 분리함으로써 관심사의 분리라는 목표를 달성할 수 있었다. 각 아키텍처는 최소한 업무 규칙을 위한 계층 하나와, 사용자와 시스템 인터페이스를 위한 또 다른 계층 하나를 반드시 포함한다.
이들 아키텍처는 모두 시스템이 다음과 같은 특징을 가지도록 한다.
- 프레임워크 독립성.
- 테스트 용이성.
- UI 독립성.
- 데이터베이스 독립성.
- 모든 외부 에이전시에 대한 독립성
의존성 규칙
- 소스 코드 의존성은 반드시 안쪽으로, 고 수준의 정책을 향해야 한다.
- 내부의 원에 속한 요소는 외부의 원에 속한 어떤 것도 알지 못한다.
- 특히 내부의 원에 속한 코드는 외부의 원에 선언된 어던 것에 대해서도 그 이름을 언급해서는 안 된다.
- 우리는 외부의 원에 위치한 어떤 것도 내부의 원에 영향을 주지 않기를 바란다.
엔티티
- 엔티티는 전사적인 핵심 업무 규칙을 캡슐화한다.
- 메서드를 가지는 객체이거나 일련의 데이터구조와 함수의 집합일 수 있다.
- 기업의 다양한 애플리케이션에서 엔티티를 재사용할 수만 있다면, 그 형태는 그다지 중요하지 않다.
- 외부의 무언가가 변경되더라도 엔티티가 변경될 가능성은 지극히 낮다.
유스 케이스
- 유스 케이스 계층의 소프트웨어는 애플리케이션에 특화된 업무 규칙을 포함한다.
- 유스 케이스는 엔티티로 들어오고 나가는 데이터 흐름을 조정하며, 엔티티가 자신의 핵심 업무 규칙을 사용해서 유스 케이스의 목적을 달성하도록 이끈다.
- 이 계층에서 발생한 변경이 엔티티에 영향을 줘서는 안 된다.
- 또한 데이터베이스, UI, 여타 공통 프레임워크와 같은 외부 요소에서 발생한 변경이 이 계층에 영향을 줘서도 안 된다.
- 유스 케이스 계층은 이러한 관심사로부터 격리되어 있다.
- 하지만 운영 관점에서 애플리케이션이 변경된다면 유스 케이스가 영향을 받으며, 따라서 이 계층의 소프트웨어에도 영향을 줄 것이다.
인터페이스 어댑터
- 어댑터는 데이터를 유스 케이스와 엔티티에게 가장 편리한 형식에서 데이터베이스나 웹 같은 외부 에이전시에게 가장 편리한 형식으로 반환한다.
- 이 계층에는 데이터를 외부 서비스와 같은 외부적인 형식에서 유스 케이스나 엔티티에서 사용되는 내부적인 형식으로 변환하는 또 다른 어댑터가 필요하다.
프레임워크와 드라이버
- 가장 바깥쪽 계층은 일반적으로 데이터베이스나 웹 프레임워크 같은 도구들로 구성된다.
- 일반적으로 이 계층에서는 안쪽 원과 통신하기 위한 접합 코드 외에는 특별히 더 작성해야 할 코드가 그다지 많지 않다.
- 프레임워크와 드라이버 계층은 모든 세부사항이 위치하는 곳이다.
- 웹, 데이터베이스 등은 세부사항이다.
- 우리는 이러한 것들을 모두 외부에 위치시켜서 피해를 최소화한다.
원은 네 개여만 하나?
- 더 많은 원이 필요할 수 있다.
- 어떤 경우에도 의존성 규칙은 적용된다.
- 소스코드의 의존성은 항상 안쪽을 향한다.
- 안쪽으로 이동할수록 추상화와 정책의 수준은 높아진다. 소프트웨어는 점점 추상화되고 더 높은 수준의 정책들을 캡슐화한다.
경계 횡단하기
- 의존성 역전 원칙을 사용하여 해결한다.
결론
- 소프트웨어 계층을 분리하고 의존성 규칙을 준수하면 본질적으로 테스트하기 쉬운 시스템을 만들게 될 것이며, 그에 따른 이점을 누릴 수 있다.
- 데이터베이스나 웹 프레임워크와 같은 시스템의 외부 요소가 구식이 되더라도, 이들 요소를 야단스럽지 않게 교체할 수 있다.