단일 책임 원칙

  • 오해의 소지가 있는 해석: 하나의 컴포넌트는 오로지 한 가지 일만 해야 하고, 그것을 올바르게 수행해야 한다.
  • 올바른 해석: 컴포넌트를 변경하는 이유는 오직 하나뿐이어야 한다.
  • 변경할 이유라는 것은 컴포넌트 간의 의존성을 통해 쉽게 전파된다.
    • 어떤 컴포넌트의 의존성 각각은 이 컴포넌트를 변경하는 이유 하나씩에 해당한다.
  • 단일 책임 원칙을 위반하면 시간이 갈수록 변경하기 어려워지고 그로 인해 변경 비용도 증가한다.

부수효과에 관한 이야기

  • 잘못 구조화된 소프트웨어를 변경하는 데는 부수 효과로 인해 더 많은 비용을 지불하도록 만드는 경우가 많다.

의존성 역전 원칙

  • 의존성의 양쪽 코드를 모두 제어할 수 있을 때는 의존성을 역전시킬 수 있다.
  • 위 구조는 영속성 계층에 대한 도메인 계층의 의존성 때문에 영속성 계층을 변경할 때마다 잠재적으로 도메인 계층도 변경해야 한다.
    • 먼저 엔티티는 도메인 객체를 표현하고 도메인 코드는 이 엔티티들의 상태를 변경하는 일을 중심으로 하기 떄문에 먼저 엔티티를 도메인 계층으로 올린다.
    • 영속성 계층의 리포지토리가 도메인 계층에 있는 있는 엔티티에 의존하기 때문에 두 계층 사이에 순환 의존성이 생기는데, 이 부분에 DIP를 적용할 수 있다.
      • 도메인 계층이 리포지토리에 대한 인터페이스를 만들고, 실제 리포지토리는 영속성 계층에서 구현하게 하는 것이다.

클린 아키텍처

  • 클린 아키텍처: 비즈니스 규칙은 프레임워크, 데이터베이스, UI기술, 그 밖의 외부 애플리케이션이나 인텊페이스로부터 독립적일 수 있다.
  • 도메인 코드가 밖으로 향하는 어떤 의존성도 없어야 한다.
  • 아키텍처의 코어에는 유즈케이스에서 접근하는 도메인 엔티티들이 있다.
    • 유스케이스는 앞에서 서비스라고 불렀던 것들인데, 단일 책임을 갖기 위해 좀 더 세분화돼 있다.
  • 클린 아키텍처에는 대가가 따른다.
    • 도메인 계층은 영속성 계층을 모르기 때문에 도메인 계층에서 사용한 엔티티 클래스를 영속성 계층에서 함께 사용할 수 없고 두 계층에서 각각 엔티티를 만들어야 한다.
    • JPA가 관리하는 엔티티에 인자가 없는 기본 생성사를 추가하도록 강제하는 것도 도메인 모델에 포함해서는 안 될 프레임워크에 특화된 결합의 예다.

육각형 아키텍처(헥사고날 아키텍처)

  • 육각형 안에는 도메인 엔티티와 이와 상호작용하는 유스케이스가 있다.
  • 귝각형에서 외부로 향하는 의존성은 없다. 모든 의존성은 코어를 향한다.
  • 육각형 바깥에는 애플리케이션과 상호작용하는 어댑터들이 있다.
    • 웹 브라우저와 상호작용하는 웹 어댑터
    • 일부 어뎁터들은 외부 시스템과 상호작용한다.
    • 데이터베이스와 상호작용하는 어댑터도 있다.
  • 왼쪽에 있는 어댑터들은 (애플리케이션 코어를 호출하기 떄문에) 애플리케이션을 주도하는 어댑터다. 반면 오른쪽에 있는 어댑터들은 (애플리케이션 코어에 의해 호출되기 때문에) 애플리케이션에 의해 주도되는 어댑터들이다.
  • 애플리케이션 코어와 어댑터들 간의 통신이 가능하려면 애플리케이션 코어가 각각의 포트를 제공해야 한다.
    • 주도하는 어댑터에게는 포트가 코어에 있는 유스케이스 클래스 중 하나에 의해 구현되고, 어댑터에 의해 호출되는 인터페이스가 된다.
    • 주도되는 어댑터에게는 포트가 어댑터에 의해 구현되고 코어에 의해 호출되는 인터페이스가 된다.

유지보수 가능한 소프트웨어를 만드는 데 어떻게 도움이 될까?

  • 도메인 코드가 다른 바깥쪽 코드에 의존하지 않게 함으로써 영속성과 UI에 특화된 모든 문제로부터 도메인 로직의 결합을 제거하고 코드를 변경할 이유의 수를 줄일 수 있다.
  • 도메인 코드는 비즈니스 문제에 딱 맞도록 자유롭게 모델링될 수 있고, 영속성 코드와 UI 코드도 영속성 문제와 UI 문제에 맞게 자유롭게 모델링될 수 있다.