소프트웨어로 해결하고자 하는 문제 영역.
도메인은 여러 개의 하위 도메인으로 나눌 수 있다.
예) 온라인 서점 - 주문, 배송, 회원, 결제, ...
도메인 모델은 특정 도메인을 개념적으로 표현한 것.
도메인을 모델을 표현할 때 도메인을 이해하는 데 도움이 된다면 표현 방식이 무엇인지는 중요하지 않다.
도메인 모델은 기본적으롷 도메인 자체를 이해하기 위한 개념 모델이다.
개념 모델을 이용해 코드를 작성할 수 있는 것은 아니기에 구현 모델이 필요하다.
일반적인 애플리케이션의 아키텍처는 네 개의 영역으로 구성된다.
응용, 도메인, 인프라는 스프링의 컨트롤러, 서비스, 리포지토리와 비슷하게 구분된다.
도메인을 모델링할 때 기본이 되는 작업은 모델을 구성하는 핵심 구성요소, 규칙, 기능을 찾는 것이다.
그리고 이 과정은 요구사항에서부터 출발한다.
주문 도메인을 예로 들면 요구사항 중
을 보면 '출고 상태로 변경', '배송지 정보 변경', '주문 취소', '결제 완료' 메서드와 주문 상태 정보를 표현하는 Enum이 필요하다는 것을 알 수 있다.
또, 두 요구 사항에 따르면 주문 항목은 주문할 상품, 상품의 가격, 구매 개수를 포함해야 한다.
이렇게 요구 사항에서 도메인 모델을 점진적으로 만들어 나갈 수 있다.
엔티티의 가장 큰 특징은 식별자를 가진다는 것이다.
스프링 JPA에서는 @Id @GeneratedValue를 사용해 표현했다.
보통 식별자는 특정 규칙이나 UUID, 일련번호 등을 사용해 생성한다.
JPA의 Embeddable 개념과 유사해 보인다.
코드 이해하는 것이 빠를 것이다.
public class DeliveryInfo{
private String receiverName; // 받는 사람
private String receiverPhoneNumber; // 받는 사람
private String shippingAddress1; // 주소
private String shippingAddress2; // 주소
private String shippingZipcode; // 주소
}
위 코드처럼 DeliveryInfo 클래스에서 여러 필드들이 하나의 개념을 표현할 때, 밸류 타입으로 묶어줄 수 있다.
@Getter @Setter
public class Receiver{
private String name;
private String PhoneNumber;
}
Address 코드 생략
private class DeliveryInfo{
private Receiver receiver;
private Address address;
}
이처럼 단지 하나의 개념을 표현하는 필드들을 묶어주는 것 뿐 아니라 필드 하나에 대해서도 만들 수 있다.
public class Money{
private int value;
public Money add(Money money){
return new Money(this.value+money.value)
}
...
}
벨류 객체의 데이터를 변경할 때는 기존 데이터를 변경하기 보다는 새 객체를 만드는 방식을 선호한다. 참조 투명성과 관련한 문제가 발생할 수 있기 때문이다.
이처럼 데이터 변경 기능을 제공하지 않는 타입을 불변이라고 표현한다.
Money price = new Money(1000);
OrderLine line = new OrderLine(product, price, 2); // [price=1000, quantity=2, amounts=2000]
price.setValue(2000); //[price=2000, quantity=2, amounts=2000]
이러면 OrderLine의 price 값이 잘못 반영되는 상황이 발생할 수 있다.
의도치 않은 set 호출로 비즈니스 로직과 맞지 않는 예외상황이 발생할 가능성이 높다.
코드를 작성할 때 도메인에서 사용하는 용어는 매우 중요하다.
도메인에서 사용하는 용어를 코드에 반영하지 않으면 개발자가 코드를 해석 해야하는 부담을 준다.
예)
public OrderStateWrong{
STEP1, STEP2, STEP3, STEP4, STEP5, STEP6
}
public OrderState{
PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED
}
에릭 에반스는 도메인 주도 설계에서 언어의 중요함을 강조하기 위해 유비쿼터스 언어라는 용어를 사용했다. 전문가, 관계자, 개발자가 도메인과 관련된 공통의 언어를 만들고 이를 대화, 문서, 도메인 모델, 코드, 테스트 등 모든 곳에서 같은 용어를 사용한다.