# 도메인 모델 시작하기
# 도메인은 여러 하위 도메인으로 구성된다.

카탈로그 도메인
- 고객에게 구매할 수 있는 상품 목록을 제공
주문 하위 도메인
- 고객의 주문을 처리한다.
여기서 특정 도메인을 위한 소프트웨어라고 해서 도메인이 제공해야 할 모든 기능을 직접 구현하는 것은 아니다.
# 도메인 전문가와 개발자 간 지식 공유
- 요구사항을 올바르게 이해하려면 개발자와 전문가가 직접 대화하는 것이다.
- 이해관계자와 개발자도 도메인 지식을 갖춰야 한다.
"Garbage in Garbage out"
# 도메인 모델
## 객체 모델

## 상태 다이어 그램

# 도메인 모델 패턴
## 아키텍처 구


배송지 변경이 가능한지를 판단할 규칙이 주문 상태와 다른 정보를 함께 사용한다면
OrderState만으로는 배송지 변경 가능 여부를 판단할 수 없으므로 Order에서 로직을 구현해야 한다.
주문과 관련된 중요 업무 규칙을 주문 도메인 모델인 Order나 OrderState에서 구현한다는 점이다.
핵심 규칙을 구현한 코드는 도메인 모델만 위치하기 때문에 규칙이 바뀌거나 규칙을 확장해야 할 때 다른 코드에 영향을 덜주고 변경 내역 모델에 반영할 수 있게 된다. (단일 책임의 원칙)
# 도메인 모델 도출과정
1. 요구사항 정리

2. Order에 관련 기능을 메서드로 추가

3. 하위 Orderline 추가


3-1. Order와 Orderline과의 관계 반영


3-2 하위 ShippingInfo 반영



여기서 null이면 에러 처리로 `배송지 정보 필수` 도메인 규칙 구현



열거 타입을 이요해서 상태 정보를 표현

문서화를 하는 주된 이유는 지식을 공유하기 위함이다.
단순히 코드를 보기 좋게 작성하는 것 뿐만 아니라,
도메인 관점에서 코드가 도메인을 잘 표현해야 비로소 코드의 가독성이 높아지고 문서로서 코드가 의미를 갖는다.
# 엔티티와 밸류

## 엔티티
엔티티의 가장 큰 특징은 `식별자`를 가진다는 것이다.
ex) 주문 도메인에서 각 주문은 주문 번호를 가지고 있다. 이 때, 주문번호는 각 주문마다 다르다. "주문번호 = 식별자"

엔티티의 식별자는 바뀌지 않고 고유하기 때문에 두 엔티티 객체의 식별자가 같으면 두 엔티티는 같다고 판단할 수 있다ㅓ.
엔티티를 구현한 클래스는 식별자를 이용해서 equals() 메서드와 hashCode() 메서드를 구현할 수 있다.


## 엔티티의 식별자 생성
엔티티의 식별자를 생성하는 시점은 도메인의 특징과 사용하는 기술에 따라 달라진다.
다음 중 한가지 방식으로 생성한다.

날짜와 시간을 이용해서 식별자를 생성할 때는 동시에 식별자를 생성해도 같은 식별자가 만들어지면 안 된다는 것이다.
### 자동 증가 컬럼을 제외한 다른 방식
식별자를 먼저 만들고 엔티티 객체를 생성할 때 식별자를 전달한다.

### 자동 증가 컬럼
DB 테이블에 데이터를 삽입하기 전에는 식별자를 알 수 없다.

# 밸류 타입

이름, 전화번호 두 필드는 실제로 하나의 개념을 표현한다.

`받는 사람` 이라는 도메인 개념을 표현한다.
밸류 타입을 사용함으로써 개념적으로 완전한 하나를 잘 표현할 수 있다.

밸류 타입이 꼭 두 개 이상의 데이터를 가져야 하는 것은 아니다.
의미를 명확하게 표현한기 위해 밸류 타입을 사용하는 경우도 있다.
이를 위한 가장 좋은 예시가 OrderLine이다.


price, amounts는 int 타입의 숫자를 사용하고 있지만, 이들은 '돈'을 의미하는 값이다.
따라서 '돈'을 의미하는 Money 타입을 만들어 사용하면 코드를 이해하는 데 도움이 된다.



OrderLine의 price 값이 잘못 반영되는 상황이 발생하게 된다.
(price 가 2000이기에, amounts 가 4000이 되야 하는 데 변경이 안됨.)
이러한 문제가 발생하는 것을 방지하려면 OrderLine 생성자는 Money 객체 코드를 재작성 해야 한다.

Money가 불변이면 이런 코드를 작성할 필요가 없다.
Money의 데이터를 바꿀 수 없기 때문에 파라미터로 전달받은 price를 안전하게 사용할 수 있다 (참조 투명성과 스레드에 안전)
두 밸류 객체를 비교할 때는 모든 속성이 같은지 비교한다.

식별자를 String이 아니라, OrderNo라는 밸류 타입을 사용한다.

orderNo라는 필드 이름을 통해 이름만으로 주문번호인지 알 수 있다.
# 유비쿼터스 언어
도메인 용어 해석 과정을 줄여준다.
이를 통해 코드의 가독성을 높여서 코드를 분석하고 이해하는 시간을 줄여준다.
시간을 들여 찾는 노력이 필요하다.
# 도메인 모델 시작하기
# 도메인은 여러 하위 도메인으로 구성된다.

카탈로그 도메인
- 고객에게 구매할 수 있는 상품 목록을 제공
주문 하위 도메인
- 고객의 주문을 처리한다.
여기서 특정 도메인을 위한 소프트웨어라고 해서 도메인이 제공해야 할 모든 기능을 직접 구현하는 것은 아니다.
# 도메인 전문가와 개발자 간 지식 공유
- 요구사항을 올바르게 이해하려면 개발자와 전문가가 직접 대화하는 것이다.
- 이해관계자와 개발자도 도메인 지식을 갖춰야 한다.
"Garbage in Garbage out"
# 도메인 모델
## 객체 모델

## 상태 다이어 그램

# 도메인 모델 패턴
## 아키텍처 구


배송지 변경이 가능한지를 판단할 규칙이 주문 상태와 다른 정보를 함께 사용한다면
OrderState만으로는 배송지 변경 가능 여부를 판단할 수 없으므로 Order에서 로직을 구현해야 한다.
주문과 관련된 중요 업무 규칙을 주문 도메인 모델인 Order나 OrderState에서 구현한다는 점이다.
핵심 규칙을 구현한 코드는 도메인 모델만 위치하기 때문에 규칙이 바뀌거나 규칙을 확장해야 할 때 다른 코드에 영향을 덜주고 변경 내역 모델에 반영할 수 있게 된다. (단일 책임의 원칙)
# 도메인 모델 도출과정
1. 요구사항 정리

2. Order에 관련 기능을 메서드로 추가

3. 하위 Orderline 추가


3-1. Order와 Orderline과의 관계 반영


3-2 하위 ShippingInfo 반영



여기서 null이면 에러 처리로 `배송지 정보 필수` 도메인 규칙 구현



열거 타입을 이요해서 상태 정보를 표현

문서화를 하는 주된 이유는 지식을 공유하기 위함이다.
단순히 코드를 보기 좋게 작성하는 것 뿐만 아니라,
도메인 관점에서 코드가 도메인을 잘 표현해야 비로소 코드의 가독성이 높아지고 문서로서 코드가 의미를 갖는다.
# 엔티티와 밸류

## 엔티티
엔티티의 가장 큰 특징은 `식별자`를 가진다는 것이다.
ex) 주문 도메인에서 각 주문은 주문 번호를 가지고 있다. 이 때, 주문번호는 각 주문마다 다르다. "주문번호 = 식별자"

엔티티의 식별자는 바뀌지 않고 고유하기 때문에 두 엔티티 객체의 식별자가 같으면 두 엔티티는 같다고 판단할 수 있다ㅓ.
엔티티를 구현한 클래스는 식별자를 이용해서 equals() 메서드와 hashCode() 메서드를 구현할 수 있다.


## 엔티티의 식별자 생성
엔티티의 식별자를 생성하는 시점은 도메인의 특징과 사용하는 기술에 따라 달라진다.
다음 중 한가지 방식으로 생성한다.

날짜와 시간을 이용해서 식별자를 생성할 때는 동시에 식별자를 생성해도 같은 식별자가 만들어지면 안 된다는 것이다.
### 자동 증가 컬럼을 제외한 다른 방식
식별자를 먼저 만들고 엔티티 객체를 생성할 때 식별자를 전달한다.

### 자동 증가 컬럼
DB 테이블에 데이터를 삽입하기 전에는 식별자를 알 수 없다.

# 밸류 타입

이름, 전화번호 두 필드는 실제로 하나의 개념을 표현한다.

`받는 사람` 이라는 도메인 개념을 표현한다.
밸류 타입을 사용함으로써 개념적으로 완전한 하나를 잘 표현할 수 있다.

밸류 타입이 꼭 두 개 이상의 데이터를 가져야 하는 것은 아니다.
의미를 명확하게 표현한기 위해 밸류 타입을 사용하는 경우도 있다.
이를 위한 가장 좋은 예시가 OrderLine이다.


price, amounts는 int 타입의 숫자를 사용하고 있지만, 이들은 '돈'을 의미하는 값이다.
따라서 '돈'을 의미하는 Money 타입을 만들어 사용하면 코드를 이해하는 데 도움이 된다.



OrderLine의 price 값이 잘못 반영되는 상황이 발생하게 된다.
(price 가 2000이기에, amounts 가 4000이 되야 하는 데 변경이 안됨.)
이러한 문제가 발생하는 것을 방지하려면 OrderLine 생성자는 Money 객체 코드를 재작성 해야 한다.

Money가 불변이면 이런 코드를 작성할 필요가 없다.
Money의 데이터를 바꿀 수 없기 때문에 파라미터로 전달받은 price를 안전하게 사용할 수 있다 (참조 투명성과 스레드에 안전)
두 밸류 객체를 비교할 때는 모든 속성이 같은지 비교한다.

식별자를 String이 아니라, OrderNo라는 밸류 타입을 사용한다.

orderNo라는 필드 이름을 통해 이름만으로 주문번호인지 알 수 있다.
# 유비쿼터스 언어
도메인 용어 해석 과정을 줄여준다.
이를 통해 코드의 가독성을 높여서 코드를 분석하고 이해하는 시간을 줄여준다.
시간을 들여 찾는 노력이 필요하다.