# 1. 도메인 모델 시작하기

# 1.1 도메인이란?

  • 소프트웨어로 해결하고자 하는 문제 영역
  • 한 도메인은 다시 하위 도메인으로 나눌 수 있음
    • ex) 온라인 쇼핑몰 -> {회원, 주문, 결제, 배송, ...}

# 1.2 도메인 전문가와 개발자 간 지식 공유

  • 코딩에 앞서 요구사항을 올바르게 이해하는게 중유 → 개발자와 전문가가 직접 대화
  • 이해관계자와 개발자도 도메인 지식을 갖춰야 함
  • 반대로 전문가와 대화를 통해 원하는 요구사항을 찾는것도 중요

# 1.3 도메인 모델

  • 도메인 모델을 표현할 때 중요한 부분에 따라 다양한 모델링 방법을 사용할 수 있음
  • ex) 관계 → 그래프, 계산 규칙 → 수학 공식

# 1.4 도메인 모델 패턴

# 도메인 모델

  • 아키텍처 상의 도메인 계층을 객체 지향 기법으로 구현하는 패턴
  • 도메인의 핵심 규칙 구현
  • ex) 주문 취소는 배송 전에만 할 수 있다
  • OrderState로만 판단 가능하면 OrderState, Order 둘다에서 정의 가능
  • 다른 정보가 더 필요하면 Order에서만

# 개념 모델과 구현 모델

  • 개념 모델은 DB, 트랜잭션 처리, 성능 등에 대한 고려 없이 만든 결과물 → 순수하게 문제를 분석한 결과물
  • 처음부터 완벽한 도메인을 만들기보다는 전반적인 개요를 알 수 있게 개념 모델 작성하기 → 나중에 바뀔 수도 있기 때문

# 1.5 도메인 모델 도출

  • 도메인을 분석하고 제약사항들을 도출해내면서 도메인 모델을 점진적으로 구현
  • 코드를 보기 전 상위 수준에서 정리한 내용을 문서화 해놓으면 도움이 됨 → 추후 코드를 보여 도메인을 깊게 이해 가능

# 1.6 엔티티와 밸류

  • 엔티티와 밸류를 제대로 구분해야 도메인을 올바르게 설계하고 구현 가능

# 엔티티

  • 고유한 식별자를 가짐
  • ex) 주문번호
  • 엔티티를 생성하고 속성을 바꾸고 삭제할 때까지 식별자는 유지 식별자가 같으면 → 동일한 엔티티

# 엔티티의 식별자 생성

도메인의 특징과 사용하는 기술에 따라 식별자 생성 시점이 달라짐

  • 특정 규칙에 따라 생성
  • UUID와 같은 고유 식별자 생성기 사용
  • 값 직접 입력
  • 일련번호 (시퀀스, DB의 자동 증가 칼럼)

# 밸류

  • 개념적으로 완전한 하나
  • ex)
@Getter
@AllArgsConstructor
public class Receiver {
    private String name;
    private String phoneNumber;
}
  • 이를 통해 배송 정보를 다음과 같이 표현 가능
  • ex)
@Getter
@AllArgsConstructor
public class ShippingInfo {
    private Receiver receiver;
    private String address;
}
  • 꼭 2개 이상의 데이터를 가질 필요 없이 의미상 이해를 위해 밸류 타입을 사용할 수 있음
@Getter
@AllArgsConstructor
public class Money {
    private int value;

    public Money add(Money money) {
        return new Money(this.value + money.getValue())
    }
}
  • add() 메서드와 같이 밸류 타입을 위한 기능도 추가 가능
  • add() 메서드가 새로운 객체를 반환하는 것처럼 밸류 타입은 불변으로 구현하는 방식을 선호
  • 파라미터로 전달받은 값을 변경하지 못하게 → 안전하게 사용 가능

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

  • 주문번호의 경우 식별자 타입으로 String 대신 OrderNo 밸류 타입을 사용하면 해당 필드가 주문번호라는 것을 알 수 있음

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

  • ex) completePayment() → setOrderState() : 상태 변경과 관련된 도메인 지식이 사라질 수 있음
  • set을 사용함으로써 도메인 객체 생성 시 온전하지 않은 상태가 될 수 있음 → 생성자를 통해 생성 + 생성자를 호출하는 시점에 필요한 데이터가 올바른지 검사
  • 클래스 내부에서 사용하기 위한 set 정의 시 private로 설정

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

  • 도메인에서 쓰는 언어를 코드에 반영해야 추후에 코드의 의미를 해석하기 쉬움
  • ex)
// Before
public OrderState {
    STEP1, STEP2, ...
}

// After
public OrderState {
    PAYMENT_WAITING, PREPARING, ...
}
  • 전문가, 관계자, 개발자가 도메인과 관련된 공통의 언어를 만들어 모든 곳에서 같은 용어를 사용하도록
  • 영어 사용 시 알맞은 영단어를 찾도록 노력해야 함