> For the complete documentation index, see [llms.txt](https://chloe-codes1.gitbook.io/book-reviews/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://chloe-codes1.gitbook.io/book-reviews/ddd-start/01_-_-_.md).

# Chapter 1: 도메인 모델 시작하기

<br>

## 💡 책에서 기억하고 싶은 내용

<br>

### 시작하기

* 소프트웨어가 도메인의 모든 기능을 제공하진 않는다
* 요구사항을 올바르게 이해하기
  * 개발자와 전문가가 직접 대화하자!

### 도메인 모델

* 도메인 자체를 이해하기 위한 `개념 모델`
  * 개념 모델을 이용해서 바로 코드를 작성할 수 있는 것은 아니므로, 구현 기술에 맞는 `구현 모델`이 따로 필요하다
* 도메인은 다수의 하위 도메인으로 구성된다
  * 도메인에 따라 용어 의미가 결정되므로, 여러 하위 도메인을 하나의 다이어그램에 모델링하면 안 된다
  * 모델의 각 구성요소는 특정 도메인으로 한정할 때 비로소 의미가 완전해지기 때문에 `각 하위 도메인`마다 `별도로 모델을 만들어야` 한다

### **어플리케이션 아키텍처**

* `사용자 인터페이스 (UI) or 표현(Presentation)`
  * 사용자의 요청을 처리하고 사용자에게 정보를 보여준다
    * 여기서 사용자는 소프트웨어를 사용하는 사람뿐만 아니라 `외부 시스템` 일 수도 있다
* `응용 (Application)`
  * 사용자가 요청한 기능을 실행한다
  * 업무 로직을 직접 구현하지 않으며, 도메인 계층을 조합해서 기능을 실행한다
* `도메인`
  * 시스템이 제공할 도메인 규칙을 구현한다
    * 도메인의 핵심 규칙을 구현!
  * `핵심 규칙`을 구현한 코드는 도메인 모델에만 위치하기 때문에, 규칙이 바꾸거나 규칙을 확장해야 할 때 다른 코드에 영향을 덜 주고 변경 내역을 모델에 반영할 수 있게 된다
* `Infrastructure`
  * 데이터베이스나 메시징 시스템과 같은 외부 시스템과의 연동을 처리한다

### 개념 모델과 구현 모델

* 개념 모델
  * 순수하게 `문제를 분석한 결과물`
  * 개념 모델은 데이터베이스, 트랜잭션 처리, 구현 기술과 같은 것을 고려하고 있지 않기 때문에 실제 코드를 작성할 때 개념 모델을 있는 그대로 사용할 수 없다
    * 그래서 개념 모델을 `구현 가능한 형태의 모델로 전환하는 과정`을 거치게 된다
  * 처음부터 완벽한 개념 모델을 만들기보다는, `전반적인 개요` 를 알 수 있는 수준으로 개념 모델을 작성해야 한다.
    * 프로젝트 초기에는 개요 수준의 개념 모델로 도메인에 대한 전체 윤곽을 이해하는데 집중하고, 구현하는 과정에서 개념 모델을 `구현 모델` 로 점진적으로 발전시켜 나가야한다

### 도메인 모델 도출

* 도메인을 모델링할 때 기본이 되는 작업
  * 모델을 구성하는 핵심 구성요소, 규칙, 기능을 찾는 것

### 엔티티

* `식별자` 를 갖는다
  * 식별자는 엔티티 객체마다 `고유`해서, 각 엔티티는 서로 다른 식별자를 갖는다
* 식별자는 `바뀌지 않는다`
  * 엔티티를 생성하고 속성을 바꾸고 삭제할 때까지 식별자는 유지된다
* 식별자는 고유하고 바뀌지 않기 때문에, 두 엔티티의 식별자가 같으면 두 엔티티는 같다고 판단 할 수 있다
  * 식별자를 이용해서 equals() 와 hashCode() method를 구현할 수 있다
* `엔티티의 식별자 생성`
  * 특정 규칙에 따라 생성
    * 식별자를 먼저 만들고 엔티티 객체를 생성할 때 식별자를 전달
  * UUID나 Nano ID 같은 고유 식별자 생성기 사용
  * 값을 직접 입력
  * 일련번호 사용 (Sequence나 DB의 자동 증가 칼럼)

### 밸류 타입

* `개념적으로 완전한 하나`를 표현할 때 사용
  * ex) 배송 수신인 이름 + 주소 → Receiver class
* 곡 두 개 이상의 데이터를 가져야 하는 것은 아님!
  * 의미를 명확하게 표현하기 위해 밸류 타입을 사용하는 경우도 있다
* 밸류 객체의 데이터를 `변경` 할 때는, 기존 데이터를 변경하기보다는 변경한 데이터를 갖는 `새로운 밸류 객체를 생성` 하는 방식을 선호한다
  * 데이터 변경 기능을 제공하지 않는 타입을 `불변 (Immutable)` 이라고 표현한다
  * 밸류 타입을 불변으로 구현하는 이유 중 가장 중요한 이유는 `안전한 코드` 를 작성할 수 있다는 것이다
    * 불변 객체는 `참조 투명성` 과 `스레드에 안전` 한 특징을 갖고 있다
* 두 밸류 객체를 비교할 때는 `모든 속성이 같은지` 비교한다

### 엔티티 식별자와 밸류 타입

* 식별자는 단순히 문자열이 아니라 도메인에서 특별한 의미를 지니는 경우가 많기 때문에, `식별자를 위한 밸류 타입` 을 사용해서 의미가 잘 드러나도록 할 수 있다
  * ex) 주문번호로 String type 대신 OrderNo 밸류 타입 사용

### 도메인 모델에 set method 넣지 않기

* set method는 도메인의 핵심 개념이나 의도를 코드에서 사라지게 한다
  * set method는 field 값만 변경하고 끝나기 때문에 `상태 변경과 관련된 도메인 지식`이 코드에서 사라지게 된다
* set method 로 인해 도메인 `객체를 생성할 때 온전하지 않은 상태`가 될 수 있다
  * set method로 데이터를 전달하도록 구현하면, 처음 객체를 생성하는 시점에 완전하지 않게 된다
* 도메인 객체가 불완전한 상태로 사용되는 것을 막으려면 `생성 시점`에 필요한 것을 전달해 주어야한다
  * 즉, 생성자를 통해 필요한 데이터를 모두 받아야 한다
  * 생성자로 필요한 것을 모두 받기 때문에, 생성자를 호출하는 시점에 필요한 데이터가 올바른지 검사할 수 있다

### 도메인 용어와 유비쿼터스 언어

* `유비쿼터스 언어`
  * 전문가, 관계자, 개발자가 도메인과 관련된 공통의 언어를 만들고 이를 대화, 문서, 도메인 모델, 코드, 테스트 등 모든 곳에서 같은 용어를 사용하는 것
  * 소통의 과정에서 발생하는 용어의 모호함을 줄일 수 있고, 개발자는 도메인과 코드 사이에서 불필요한 해석 과정을 줄 일 수 있다!
