1. 단일책임원칙
SRP : 하나의 컴포넌트는 오로지 한 가지 일만 해야 하고, 그것을 올바르게 수행해야 한다.(X)
- 좋은 조언이지만 SRP 의 실제의도는 아니다
- 다음이 SRP 의 실제 정의이다.
SRP : 컴포넌트를 변경하는 이유는 오직 하나뿐이어야 한다.(O)
- 책임은 1가지 일만 하는 것 보다 변경할 이유로 해석해야 한다.
- 단일변경 이유 원칙(Single Reson to Change Principle) 이 적절할 수도 있다.
- 변경 이유가 1개일때 1가지 일만 하는 것은 자동으로 따라온다.
컴포넌트를 변경할 이유가 1가지라면 어떤 다른 이유로 소프트웨어를 변경하더라도 이 컴포넌트에 대해서는 전혀 신경 쓸 필요가 없다. 소프트웨어가 변경되더라도 여전히 우리가 기대한 대로 동작할 것이다.
하지만 변경할 이유는 컴포넌트 의존성을 통해 너무 쉽게 전파된다!!!
- 컴포넌트 E 의 경우 의존하는 것이 없으므로 변경할 유일한 이유가 E의 기능이 바뀔때 뿐이다
- 컴포넌트 A 의 경우 모든 컴포넌트를 의존하므로 어떤 컴포넌트가 바뀌어도 같이 바뀌어야 한다.
- SRP 위반시 변경하기가 더 어려워진다. 다른 컴포넌트의 실패요인으로 작용될 수 있다.
2. 부수효과
- 코드의 한 영역을 변경하더라도 다른 영역에서 부수효과가 발생하기 쉽다.
- 변경하기 어려운 코드를 만든다.
3. 의존성 역전 원칙
- 계층형 아키텍처에서는 상위계층들이 하위 계층들에 비해 변경할 이유가 더 많게 된다.
- 즉 영속성 계층을 변경할 때마다 잠재적으로 도메인 계층도 변경해야 한다.
- 도메인 코드는 애플리케이션에서 가장 중요한 코드이다!! 영속성 코드가 바뀐다고 도메인 코드까지 바꾸고 싶지 않다!!
- 의존성 역전 원칙(Dependency Inversuon Principle, DIP) 를 적용해 보자
코드상의 어떤 의존성이라도 그 방향을 바꿀 수 (역전시킬 수) 있다.
- 의존성의 양쪽 코드를 모두 제어할 수 있을 때만 의존성을 역전시킬 수 있다.
- 서드파티의 라이브러리의 의존성이 있다면 해당 라이브러리를 제어할 수 없기 때문에 의존성 역전이 불가하다.
계층형 아키텍처에서 의존성 역전 방법
도메인 코드와 영속성 코드 간의 의존성을 역전시켜서 영속성 코드가 도메인 코드에 의존하고, 도메인 코드를 '변경할 이유' 의 개수를 줄여보자.
- 엔티티를 도메인 계층으로 올린다.
- 영속성 계층의 레포지토리가 도메인 계층에 있는 엔티티에 의존하면서 두 계층 사이에 순환 의존성이 생긴다. 이부분이 DIP 적용 부분이다.
- 도메인 계층에 리포지토리 인터페이스를 만든다.
- 실제 리포지토리는 영속성 계층에서 구현하게 한다.
3. 클린 아키텍처
-
도메인 코드가 바깥으로 향하는 어떤 의존성도 없어야 한다.
-
의존성 역전 원칙의 도움으로 모든 의존성이 도메인 코드를 향해야 한다.
이 아키텍처에서 가장 중요한 규칙은 계층 간의 모든 의존성이 안쪽으로 향해야 한다.
-
엔티티 : 서비스에서 접근하는 도메인 엔티티
-
유스케이스 : 서비스(단일 책임을 갖기 위해 세분화 - 이를 통해 넓은 서비스 문제 회피)
-
도메인 코드는 어떤 영속성 프레임워크나 UI 프레임워크가 사용되는지 알 필요 없다. - 도메인 코드를 자유롭게 모델링가능(도메인 중심)
클린아키텍처의 대가
- 도메인 계층이 영속성등 외부 계층과 철저하게 분리되어야 하므로 애플리케이션의 엔티티에 대한 모델을 각 계층에서 유지보수 해야 한다.
- ORM JPA 사용시 도메인 계층은 영속성 계층을 모르기 때문에 도메인 계층에서 사용할 엔티티와 영속성 계층 엔티티를 각자 만들어야 한다.
- 도메인과 영속성 계층이 데이터를 주고받을 때 두 엔티티를 서로 변환해야 한다는 뜻이다.
4. 육각형 아키텍처(헥사고날 이키텍처)
- 애플리케이션 코어가 각 어댑터와 상호작용하기 위해 특정 포트를 제공하기 때문에 포트와 어댑터(ports and adapters) 아키텍처라고도 불린다.
- 외부로 향하는 의존성이 없다. 모든 의존성이 코어를 향한다.