블로그에 게시하는 위 글은 전체적인 내용 정리가 아닌
책을 읽으면서 새로 알게된 내용이나 제가 중요하다고 생각하는 내용을 정리한 글입니다.
1. 도메인
온라인 서점이 제공하는 기능
- 목차와 서평 확인
- 장바구니
- 바로 구매 (신용카드, 가상계좌)
- 적용할 수 있는 쿠폰 찾기
- 배송 추적
개발자가 구현해야하는 대상 → 온라인 서점
구현해야하는 기능 → 위에서 말한 것들 (장바구니, 배송 추적 ...)
여기서 도메인은 온라인 서점을 의미
한 도메인은 여러 하위 도메인으로 나눌 수 있다. (ex. 주문, 회원, 배송, 결제 ...)
2. 도메인 모델
객체 모델
출처 : ResearchGate
- 기능과 데이터를 같이 보여주기 때문에 모델링에 적합
- 하지만 필수는 아님
- ex. 상태 다이어그램 등으로도 모델링 가능
- UML 표기법은 필수가 아님. 중요한 것이 무엇인지에 따라 다름
- 관계가 중요한 경우 : 그래프
- 계산 규칙이 중요한 경우 : 수학공식
- 이해하는데 도움이 된다면 무슨 방법을 사용해도 상관 X
개념 모델과 구현 모델
- 도메인 모델 = 개념 모델
- 구현 기술에 맞는 모델 = 구현 모델
3. 도메인 모델 패턴
일반적인 애플리케이션의 아키텍처 4계층
- 표현 계층 : UI
- 응용 계층 : 사용자가 요청한 기능 실행
- 도메인 계층 : 시스템이 제공할 도메인의 규칙 구현
- 인프라 계층 : 외부 시스템(ex. DB)과의 연동 처리
4. 도메인 모델 도출
도메인 모델링 시 필요한 것
→ 모델을 구성하는 핵심 구성요소, 규칙, 기능을 찾는 것
→ 은 요구사항에서부터 출발
ex. 주문 도메인의 경우
- 최소 한 종류 이상의 상품을 주문해야한다.
- 한 상품을 한 개 이상 주문할 수 있다.
- 총 주문 금액은 각 상품의 구매 가격 합을 모두 더한 금액이다.
- 각 상품의 구매 가격 합은 상품 가격에 구매 개수를 곱한 값이다.
- 주문할 때 배송지 정보를 반드시 지정해야 한다.
- 배송지 정보는 받는 사람 이름, 전화번호, 주소로 구성된다.
- 출고를 하면 배송지 정보를 변경할 수 없다.
- 출고 전에 주문을 취소할 수 있다.
- 고객이 결제를 완료하기 전에는 상품을 준비하지 않는다.
이 요구 사항에서 알 수 있는 것은 아래 4가지 기능을 제공한다는 것이다.
- 출고 상태로 변경하기
- 배송지 정보 변경하기
- 주문 취소하기
- 결제 완료로 변경하기
이렇게 기능을 축약시키면 메소드로 나타낼 수 있다.
public class Order {
public void changeShipped() { ... }
public void changeShippingInfo(ShippingInfo newShipping) { ... }
public void cancel() { ... }
public void completePayment() { ... }
}
이외에도 위 요구사항을 하나하나 분석해가며 도메인 모델을 완성시켜나아가는 코드를 작성했다.
5. 엔티티와 밸류
도출한 모델은 크게 엔티티와 밸류로 구분할 수 있다.
엔티티와 밸류
엔티티
- 각자 다른 식별자를 가짐
- 식별자를 생성하는 방식
- 특정 규칙에 따라 생성
- UUID
- 값을 직접 입력
- 일련번호 사용
밸류
- 한 개의 완전한 개념을 표현할 때 사용 (ex. 주소)
- 식별자를 가지지 않음
- 보통 불변 타입으로 만듬
- 보다 안전한 코드 작성이 가능
- 아래 예제 같이 불변으로 작성하지 않으면 각자 가격은 2000, 갯수는 2인데 총액은 2000이 되는 현상이 발생할 수 있다.
- 참조 투명성, 스레드 세이프하다. (자세한 설명)
Money price = new Money(1000);
OrderLine line = new OrderLine(product, price, 2);
price.setValue(2000);
엔티티 식별자와 밸류 타입
- 식별자의 실제 데이터는 String으로 구성되는 경우가 많다.
도메인 모델에 set 메서드(public) 넣지 않기
- 도메인의 핵심 개념이나 의도를 코드에서 사라지게 할 수도 있다.
- ex. change - set의 뜻을 비교
- change : 새로 변경한다는 의미
- set : 단순히 값을 설정
- 완전한 상태가 아니게 될 수도 있다.
Order order = new Order()
order.setState(OrderState.PREPARING);
- 위 코드처럼 아무런 정보가 없는 상태에서 주문 완료 처리를 할 수 있다.
- setState()에 필요한 정보들이 null인지 확인하는 코드를 넣는 것도 올바른 방법이 아니다.
- 생성 시점에 필요한 것들을 모두 전달하는것이 올바르다 (ex. 생성자)
- 생성자 안에 set 메소드를 넣는 것이 바람직 (private으로)
- 되도록이면 밸류 타입은 불변으로 구현하는 것이 올바르다.
6. 도메인 용어
- 도메인 용어는 되도록이면 이해가 잘 가게 구현하는 것이 중요
- ex. 상태를 STEP1, STEP2, STEP3 ... 이렇게 설정하는 것 보다, PAYMENT_WATING, PREPARING, SHIPPED ... 이런식으로 도메인 용어를 사용하는게 더 바람직
- 도메인과 알맞은 적절한 영어 단어를 찾는 노력을 하는 게 중요