책 일지/만들면서 배우는 클린 아키텍쳐 11

12장 아키텍처 스타일 결정하기

언제 육각형 아키텍처를 사용해야 할까? 언제 계층형 아키텍처 스타일을 사용할까? 도메인이 왕이다. 육각형 아키텍처의 특징은 다음과 같다. 외부의 영향을 받지 않고 도메인 코드를 자유롭게 발전시킬 수 있다는 것은 육각형 아키텍처 스타일이 내세우는 가장 중요한 가치다. 따라서 도메인 주도 설계 방식과 잘어울린다. 영속성이나 다른 기술에 대해 신경 쓸 이유가 없기 때문이다. 첫 지표로, 도메인 코드가 애플리케이션에서 중요한지 안한지를 따져야 한다. 경험이 여왕이다. 다른 아키텍처 스타일을 작은 모듈부터 시도해보자! 개념에 익숙해지고, 스타일에 익숙해져라. 그때그때 다르다. 응.. 말그대로, 아키텍처 스타일은 그때그때 달라.. 소프트웨어의 종류, 도메인 코드의 역할, 팀의 경험에 따라서도 다르다.

11장 의식적으로 지름길 사용하기

소프트웨어는 하드웨어에 비해 쉽게 변경할 수 있기 때문에, 어떤 떄는 지름길을 먼저 취하고 나중에 고치는 것이 더 경제적일 수 있다. 지름길은 깨진 창문과 같다. 품질이 떨어진 코드에서 작업할 때 더 낮은 품질의 코드를 추가하기 쉽다. 코딩 규칙을 많이 어긴 코드에서 작업할 때 또 다른 규칙을 어기기 쉽다. 지름길을 많이 사용한 코드에서 또 다른 지름길을 추가하기 쉽다. → 레거시 코드 일 수록, 코드 품질이 낮아진다. 깨끗한 상태로 시작할 책임 소프트웨어 프로젝트는 대개 큰 비용이 들고 장기적인 노력을 필요로 하기 때문에 깨진 창문을 막아야 한다. 의도적인 지름길에 대해서는 세심하게 기록해두어야 한다. 유스케이스 간 모델 공유하기 유스케이스 간에 입출력 모델을 공유하게 되면 유스케이스들 사이에 결합이 ..

10장 아키텍처 경계 강제하기

규모가 커질 수록 아키텍처가 서서히 무너지게 된다. 계층 간의 경계가 약화되고, 코드는 테스트하기 어려워진다. 새로운 기능을 구현하는데 점점 더 많은 시간이 든다. 경계와 의존성 경계를 강제한다는 것은 의존성이 올바른 방향을 향하도록 강제하는 것이다. 계층 경계를 넘는 의존성은 항상 안쪽 방향으로 향해야 한다. 따라서 이러한 의존성 규칙을 강제하는 방법을 알아보자! 방법 1 : 접근 제한자. public, protected, private, default(package-private) 제한자가 존재한다. 여기서 default 제한자가 중요하다. 왜냐하면 자바 패키지를 통해, 클래스들을 응집적인 모듈로 만들어 주기 때문에, 모듈 내에 있는 클래스들은 서로 접근 가능 하지만, 패키지 바깥에서는 접근할 수 없..

9장 애플리케이션 조립하기

모든 의존성은 안쪽으로, 애플리케이션의 도메인 코드 방향으로 향해야한다. → 도메인 코드가 바깥 계층의 변경으로부터 안전하다. 유스케이스는 인터페이스만 알아야 하고, 런타임에 구현을 제공받는다. ⇒ 생성자를 통해 객체를 전달 받기 때문에 실제 객체 대신 목으로 전달할 수 있고, 격리된 단위 테스트를 생성하기 쉬워진다. 그렇다면 객체 인스턴스를 생성할 책임은 누구에게 있을까? 모든 클래스에 대한 의존성을 가지는 설정 컴포넌트가 있어야 한다. 다음과 같이 중립적인 설정 컴포넌트는 인스턴스 생성을 위해 모든 클래스에 접근 가능하다. 설정 컴포넌트의 책임과 역할 웹 어댑터 인스턴스 생성, HTTP 요청 → 웹 어댑터 전달 보장 유스케이스 인스턴스 생성, 웹어댑터에 유스케이스 인스턴스 제공 영속성 어댑터 인스턴스..

8장 경계 간 매핑하기

매핑하지 않기 전략 (No Mapping) 웹, 애플리케이션, 영속성 계층 모두에서 도메인 모델을 입출력 모델로 쓰는 것이다. 이는, 단일 책임 원칙을 위반한다. 절대로 쓰면 안되는 건 아니고, 간단한 CRUD 유스케이스 같은 경우, 모든 계층이 정확히 같은 구조의, 같은 정보를 필요로 한다면 괜찮다. 양방향 매핑 전략 각 계층이 전용 모델을 가진 매칭 전략을 양방향 매핑 전략이라고 한다. 각 어댑터가 해당 모델을 도메인 모델로, 도메인 모델을 해당 모델로 매핑할 책임을 가지고 있다. 모두 양방향으로 매핑한다. 장점 각 계층이 전용 모델을 변경하더라도, 다른 계층에는 영향이 없다. 웹이나 영속성 관심사로 오염되지 않는 깨끗한 도메인 모델로 이어진다. 매핑하지 않기 전략 다음으로 간단한 전략이다. 단점 보..

6장 영속성 어댑터 구현하기

의존성 역전 애플리케이션의 서비스에서는 영속성 기능을 사용하기 위해 포트 인터페이스를 호출한다. 육각형 아키텍처에서 영속성 어댑터는 주도되는 혹은 아웃고잉 어댑터이다. 즉, 애플리케이션에 의해 호출된다. 포트는 애플리케이션 서비스와 영속성 코드 사이의 간접적인 계층이다. 이를 통해 의존성을 역전 시켜, 영속성 코드를 리팩터링 해도 코어의 코드는 변경 되지 않는다. 영속성 어댁터의 책임 입력을 받는다. 포트 인터 페이스를 통해 입력을 받는다. 입력을 데이터 베이스 포맷으로 매핑한다. 입력 모델을 데이터 베이스 테이블 구조를 반영한 JPA 엔티티 객체로 매핑한다. 매핑하지 않는 전략은 8장에서 다룬다. 영속성 어댑터 입력 모델이 영속성 어댑터 내부에 있는 것이 아니라 애플리케이션 코어에 있다. → 이를 통해..

5장 웹 어댑터 구현하기

의존성 역전 인커밍 어댑터는 애플리케이션 서비스에 의해 구현된 인터페이스인 전용 포트를 통해 애플리케이션 계층과 통신한다. 여기서 왜 어댑터와 유스케이스 중간에 간접 계층을 넣어야 할까? 애플리케이션 코어가 외부 세계와 통신할 수 있는 곳에 대한 명세가 포트이기 때문이다. → 여기에 대한 이야기는 11장에서 더 하기로 한다. 웹 어댑터의 책임 Http 요청을 자바 객체로 매핑. 파라미터와 콘텐츠를 객체로 역직렬화 한다. 권한 검사 입력 유효성 검증 유스 케이스 입력 모델은 유스케이스의 맥락에서 유효한 입력만 허용해야 한다. 웹어댑터의 입력모델과 유스케이스의 입력 모델과는 또 다른 유효성 검증을 해야한다. 웹 어댑터의 입력 모델을 유스케이스의 입력 모델로 변환할 수 있다는 것을 검증해야 한다. 입력을 유스..

4장 유스케이스 구현하기

육각형 아키텍쳐의 장점은 애플리케이션, 웹, 영속성 계층이 아주 느슨하게 결합돼 있다는 점이다. 이를 통해, 도메인 코드를 자유롭게 모델링 하고, DDD, 풍부하거나 빈약한 도메인 모델을 구현할 수 있다. 유스케이스 입력의 유효성 검증 책임은 없다. 비즈니스 규칙을 검증할 책임이 있다. 도메인 엔티티와 이 책임을 공유한다. 유스케이스는 입력을 기반으로 어떤 방법으로든 모델의 상태를 변경한다. 아웃고잉 어댑터를 호출한다. 아웃고잉 어댑터에서 온 출력값을, 유스케이스를 호출한 어댑터로 반환할 출력 객체로 변환한다. 다음과 같이,, 하나의 서비스가 하나의 유스케이스를 구현한다. 도메인 모델을 변경하고, 변경된 상태를 저장하기 위해 아웃고잉 포트를 호출. 입력 유효성 검증 애플리케이션 계층에서 이를 검증한다. ..

3장 코드 구성하기

계층으로 구성하기 buckapl |--- domain | |----- Account | |----- Activity | |----- AccountRepository | |----- AccountService |--- persistence | |----- AccountRepositoryImpl |--- web | |----- AccountController 기능을 구분짓는 패키지 경계가 없다. 애플리케이션이 어떤 유스 케이스를 제공하는지 파악하기 어렵 패키지 구조를 통해서는 우리가 목표로 하는 아키텍처를 파악할 수 없다 기능으로 구성하기 buckapl |--- account | |----- Account | |----- Activity | |----- AccountRepository | |----- Sen..

2장 의존성 역전하기

목차에 앞서서, SOLID 의 핵심 기능 중 하나인 S와 D를 먼저 이야기 나누어 보겠다. 단일 책임 원칙 (SRP) Single Responsibility Principle 로 직역하자면 하나의 컴포넌트는 오로지 한 가지 일만 해야하고, 그것을 올바르게 수행해야 한다는 의미이다. 하지만, 실제 정의는 다음과 같다. 컴포넌트를 변경하는 이유는 오직 하나뿐이어야 한다. 즉, 책임은 오로지 한가지 일을 하는 것 보다 “변경할 이유” 로 해석되어야 한다. 다음과 같이, E는 다른 컴포넌트에 의존하지 않으므로, E를 변경할 이유는 새로운 요구사항에 의해 E의 기능을 바꾸어야 할 때이다. 하지만, A와 같은 경우, 여러 컴포넌트에 의존하고 있기 때문에, 직접적인 B, C 의존성은 물론, 간접적인 D, E의 변경 ..