DDD Start 1장
도메인
-
도메인 : 소프트웨어로 해결하고자 하는 문제영역(기능)
-
도메인 모델 : 특정 도메인을 이해하기 위해서 개념적으로 표현한 다이어 그램
-
도메인 모델을 표현할 때 클래스 다이어그램이나 상태 다이어그램과 같은 UML표기법만 사용해야 하는 것은 아니다.
관계가 중요한 도메인이라면 그래프를 이용해서 도메인을 모델링 할 수 있다. 계산 규칙이 중요하다면 수학 공식을
활용해서 도메인 모델을 만들 수도 있다. 도메인을 이해하는 데 도움이 된다면 표현 방식이 무엇인지는 중요하지 않다. -
구현 모델 : 개념을 모델을 통해서 바로 코드를 작성하기는 어렵다. 따라서 구현 기술에 맞는 구현 모델이 따로 필요하다.
-
개념 모델과 구현 모델은 서로 다르지만 구현 모델이 개념 모델을 최대한 따르도록 할 수는 있다.
개념 모델과 구현 모델 개념 모델은 순수하게 문제를 분석한 결과물이다. 개념 모델은 데이터 데이터 베이스, 트랜잭션 처리, 성능 구현 기술과 같은 것들을 고려하고 있지 않기 때문에 실제 코드를 작성할 때 개념 모델을 있는 그대로 사용 할 수 없다. 그래서 개념 모델을 구현 가능한 형태의 모델로 전환하는 과정을 거치게 된다. 개념 모델을 만들때 처음부터 완벽한 모델을 만드는 것은 불가능에 가깝다. 따라서, 처음부터 완벽한 개념 모델을 만들기 보다 전반적인 개요를 알 수 있는 수준으로 개념모델을 작성해야 한다.
도메인 모델 패턴
- 일반적인 애플리케이션의 아키텍처는 네 개의 계층으로 구성 된다.
-
사용자인터페이스(UI) 혹은 표현(Presentation) 사용자의 요청을 처리하고 사용자에게 정보를 보여준다. 여기서 사용자는 소프트웨어를 사용하는 사람뿐만 아니라 외부 시스템도 사용자가 될 수 있다.
-
응용(Application) 사용자가 요청한 기능을 실행한다. 업무 로직을 직접 구현하지 않으며 도메인 계층을 조합해서 기능을 실행한다.
-
도메인 시스템이 제공할 도메인의 규책을 구현한다.
-
인프라스트럭처(Infrastructure) 데이터베이스나 메시징 시스템과 같은 외부 시스템과의 연동을 처리한다.
도메인 모델 도출
도메인을 모델링 할때 기본이 되는 작업은 모델을 구성하는 핵심 구성요소, 규칙, 기능을 찾는 것이다. 이것들은 바로 요구사항으로 부터 나온다.
문서화 문서화를 하는 주된 이유는 지식을 공유하기 위함이다. 모든 것은 코드를 보면 알 수 있지만 코드는 상세한 모든 내용을 다루고 있기 때문에 코드를 이용해서 전체 소프트웨어를 분석하려면 많은 시간을 투자해야 한다. 전반적인 기능 목록이나 모듈 구조, 빌드 과정은 코드를 보고 직접 이해하는 것보다 상위 수준에서 정리한 문서를 참조 하는 것이 소프트웨어 전반을 빠르게 이해하는 데 도움이 된다.
엔티티와 밸류
- 엔티티 : 식별자를 갖는 도메인. (예 : 주문 - 주문번호)
- 밸류 타입 : 개념적으로 완전한 하나를 표현할 때 사용. (예 : 주문자, 받는자)
- 밸류 객체의 데이터를 변경할 때는 기존 데이터를 변경하기보다는 변경한 데이터를 갖는 새로운 밸류 객체를 생성하는 방식을 선호한다.
//불변객체의 예 public class Money{ private int value; public Money add(Money money){ return new Money(this.value + money.value); } //value를 변경할 수 있는 메서드 없음 }
- 불변(immutable) : 불변 객체는 참조 투명성과 쓰레드에 안전한 특징을 갖고 있다. (함수형 프로그래밍에서 추구하는..)
엔티티 식별자와 밸류 타입
엔티티 식별자의 데이터는 주로 숫자나 문자열 타입으로 구성된 경우가 많지만 밸류타입으로 만들면 의미가 잘 드러나도록 할 수 있다.
public class Order {
private String OrderId;
}
//밸류타입 객체를 이용한 식별자 데이터
public class Order {
private OrderNo OrderId;
}
도메인 모델에 set메서드 넣지 않기
set 메소드를 습관적으로 만들곤 하지만, 무조건 추가하는 것은 좋지 않은 버릇이다. 객체에 필수 적인 정보다 다 결정되지 않은 상태에서 데이터가 변경 될 수 있는 위험성을 가지고 있다. 아래 예를 보자
order order = new Order();
order.setOrderLine(lines);
order.setShippingInfo(shippinInfo);
//주문자를 설정하지 않은 상태에서 주문 완료 처리
order.setState(OrderState.PREPARING);
도메인 객체가 불완전한 상태로 사용되는 것을 막으려면 생성 시점에 필요한 것을 전달해줘야 한다. 즉, 생성자를 통해 필요한 데이터를 모두 받아야 한다.
Order order = new Order(orderer, lines, shippingInfo, OrderState.PREPARING);
도메인 용어
도메인에서 사용하는 용어를 코드에 반영하지 않으면 그 코드는 개발에게 코드의 의미를 해석해야 하는 부담을 준다. 아래 나쁜 예를 보자. (휴…갑자기 현타가…이런코드는 지금도 아주 가까운곳에서 보고 있어서.. )
public OrderState{
STEP1, STEP2, STEP3, STEP4, STEP5;
}
- 올바른 예
public OrderState{ PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED; }