고딩왕 코범석
1장 도메인 본문
반응형
1장 - 도메인
Index
도메인 모델이란?
- 특정 도메인을 개념적으로 표현한 것
하위 도메인과 모델
- 도메인은 다수의 하위 도메인으로 구성된다.
- 만약 용어가 같더라도 각 도메인마다 용어의 의미는 달라진다.
- 예를 들어, 카탈로그 도메인의 상품은 상품의 상세 정보들을 다룬다.
- 하지만 배송 도메인의 상품은 배송되는 상품에 대한 상세 정보들을 다룬다.
- 즉, 특정 도메인마다 하위 도메인 모델을 공유하지 않고 따로 만들어야 한다.
- 카탈로그 도메인의 상품과 배송 도메인의 상품을 따로 만들어야 한다.
도메인 모델 패턴
영역 | 설명 |
---|---|
UI or Presentation | 사용자의 요청을 처리하고 사용자에게 정보를 보여주는 책임을 갖는 영역. 소프트웨어를 사용하는 사람 뿐만아니라 외부 시스템일 수 있다. |
Application | 사용자가 요청한 기능을 실행하는 영역. 도메인 계층을 직접 조합하여 기능을 실행한다. |
Domain | 시스템이 제공할 도메인의 규칙을 구현하는 영역 |
Infrastructure | 데이터베이스, 메시징 시스템과 같은 외부 시스템과의 연동을 처리한다. |
Domain Layer (Domain Model Pattern)
- 도메인의 핵심 규칙을 구현한다.
- 주문 도메인의 경우 ‘출고 전에 배송지를 변경할 수 있다.’, ‘주문 취소는 배송 전에만 할 수 있다.’를 구현한 코드가 도메인 레이어에 위치한다.
- 이런 도메인 규칙을 객체 지향 기법으로 구현하는 패턴이 도메인 모델 패턴이다.
- 주문 도메인에서 주문 상태에 따라 주문 취소 가능 여부에 대해 구현해본다면 다음과 같이 구현할 수 있다.
public enum OrderState {
PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED, CANCELED
}
public class Order {
private ShippingInfo shippingInfo;
private OrderState orderState;
public void changeShippingInfo(ShippingInfo newShippingInfo) {
if (!isShippingChangeable())
throw new IllegalStateException();
}
private boolean isShippingChangeable() {
// logic...
}
}
중요한 점은 배송지 변경에 대해 판단하는 로직은 도메인 모델인 Order
나 OrderState
에서 구현한다는 점이다. 이런 코드가 도메인 모델에만 위치하기 때문에 규칙 변경, 확장 시 다른 코드에 대한 영향을 덜 줄 수 있다는 장점이 있다.
도메인 모델 도출
모델을 구성하는 핵심 구성 요소, 규칙, 기능을 먼저 찾기
주문 항목이 어떤 데이터로 구성되는지 알려주는 요구사항
- 한 상품을 한 개 이상 주문할 수 있다.
- 각 상품의 구매 가격 합은 상품 가격에 구매 갯수를 곱한 값이다.
- 배송지 정보는 받는 사람 이름, 전화번호, 주소로 구성된다.
기능에 대한 요구사항
- 출고를 하면 배송지를 변경할 수 없다.
- 출고 전에 주문을 취소할 수 있다.
- 고객이 결제를 완료하기 전 까지는 상품을 준비하지 않는다.
주문과 주문 상품에 대한 관계를 알려주는 요구 사항
- 최소 한 종류 이상의 상품을 주문해야 한다.
- 총 주문 금액은 각 상품의 구매 가격 합을 모두 더한 금액이다.
조건에 대한 요구 사항
- 주문할 때 배송지 정보를 반드시 지정해야 한다.
- 최소 한 종류 이상의 상품을 주문해야 한다.
- 출고를 하면 배송지를 변경할 수 없다.
- 출고 전에 주문을 취소할 수 있다.
- 고객이 결제를 완료하기 전 까지는 상품을 준비하지 않는다.
Entity & Value
엔티티와 밸류를 구분해야 도메인을 올바르게 설계하고 구현할 수 있다. 그 전에 이 둘의 명확한 차이를 알아야 한다.
Entity
- 고유한 식별자를 가지고 있다.
- 이 식별자는 절대 변경되지 않는다.
- 주문 도메인을 예를 들면 주문 번호가 있다.
- 주문 도메인을
Order
엔티티로 도출하고 해당 엔티티에 고유한 ID를 부여한다.
- 주문 도메인을
- 엔티티 객체에서 식별자가 같으면 같은 객체로 판단한다. 따라서
equals()
,hashCode()
를 재정의한다.
Value
- 밸류 타입은 완전한 하나를 표현할 때 사용한다.
- 꼭 두개 이상의 필드를 가져야하는 것은 아니며 의미를 명확하게 표현하기 위해 사용한다.
- 밸류 타입의 장점은 밸류 타입을 위한 기능을 추가할 수 있다는 점이다.
- 예를 들어 받는 사람 이라는 개념을 밸류 타입으로 표현하면 다음과 같은 밸류 타입 클래스를 만들 수 있다.
public class Receiver { private String name; private String phoneNumber; }
- 또한, 주소 라는 개념을 밸류 타입으로 표현하면 다음과 같다.
public class Address { private String address1; private String address2; private String zipCode; }
- 밸류 타입의 객체를 변경 시 기존 데이터를 변경하기 보다는 변경한 데이터를 갖는 새로운 밸류 객체를 생성하여 이를 저장하는 방식이 선호된다.
- 이처럼, 데이터 변경 기능을 제공하지 않는 타입을 불변이라고 한다. 불변의 장점은 보다 안전한 코드를 작성하는데 있다.
- 안전한 코드?
- 아래 상황의 경우 price와 OrderLine의 price가 모두 변경되는 대참사가 일어난다.
Money price = new Money(1000); OrderLine orderLine = new OrderLine(product, price, 2); price.setValue(2000); // price와 orderLine.getPrice 값 모두 변경
- 밸류 객체를 비교할 때는 밸류 객체의 필드들이 모두 같은지 비교한다.
Entity 식별자를 Value Type으로 변경
- 식별자는 문자열일 경우 하나의 Value Type을 정의하여 명확하게 설계할 수 있다.
public class Order {
private OrderNo id;
public OrderNo getOrderNo() {
return id;
}
}
반응형
'Book Lounge > 도메인 주도 개발 시작하기' 카테고리의 다른 글
6장 - 응용 서비스와 표현 영역 (0) | 2022.07.16 |
---|---|
5장 - 스프링 데이터 JPA를 이용한 조회 기능 (0) | 2022.07.16 |
4장 리포지터리와 모델 구현 (0) | 2022.07.09 |
3장 애그리거트 (0) | 2022.07.02 |
2장 아키텍처 개요 (0) | 2022.07.01 |