개요
- 사이드 프로젝트를 시작하게 되었다. 처음부터 진행하는게 아닌 진행되어있는 프로젝트에 합류했다. 처음보는 패키지 구조였는데 한눈에 파악하기가 쉬웠고 오히려 이제까지 개발하던 구조보다 더 확장성 있고 가독성이 좋다고 느꼈다. 그 이유는 메인 도메인 안에 하위 도메인과 도메인이 가지고있는 비즈니스 로직들을 한번에 파악할 수 있어 도메인의 역할을 쉽게 파악할 수 있엇다. 알고보니 해당 구조는 DDD(Domain Driven Design)를 기반으로 만들어졌다. 사실 이전까지 DDD에 대해 많이 들어는 봤지만 실제로 적용해 본 적은 없었다.이제 프로젝트를 진행하면서 내가 DDD를 적용하고 개발을 해야되는데 많이 부족하다 느껴 도메인 주도 개발 시작하기 by 최범균 책으로 DDD를 공부하기 시작했다.
도메인이란?
- 소프트웨어로 해결하고자 하는 문제 영역 ( ex: 온라인 서점)
- 메인 도메인과 여러 하위 도메인이 존재한다.
- 코딩을 하기전 이해관계자와 개발자는 도메인 지식을 갖추고 소통을 하며 개발을 해야한다. -> 커뮤니케이션이 중요
- 도메인을 정확하게 이해하지 못하고 개발을 하면 Garbage in, Garbage Out(잘못된 값이 들어가면 잘못된 결과가 나온다 -> 요구사항을 잘 못이해해서 개발한 경우) 이 발생한다.
Domain
- 도메인 모델에 set 메서드 넣지 말아야한다. -> set 메소드는 도메인의 핵심 개념이나 의도를 코드에서 사라지게 한다.
- 도메인의 상태를 변경하는 메서드가 필요하면 네이밍을 직관적으로 작성 후 사용해야한다.
public class Order{
public Order(Orderer order,List<OrderLine> orderLines, shippingINfo shippingInfo,
OrderState state){
setOrderer(orderer);
setOrderLines(orderLines);
calculateTotalAmounts();
}
private void setOrderer(Orderer orderer){
if (orderer ==. null) throw new IllegalArgumentException("no orderer");
this.orderer = orderer;
}
private void calculateTotalAmounts(){
this.totalAmounts = orderLines.stream().mapToInt(x -> x.getAmounts()).sum();
}
}
- 위 코드는 주문 관련 도메인이다. 주문자를 넣는 setOrderer() 와 가격을 계산하는 calculateTotalAmounts()가 있다. 이러한 필요한 메서드들은 set 메서드를 올바르게 사용한 경우이다. 무조건적으로 set 메서드가 안 좋은건 아니다. 내부에서 데이터를 변경할 목적으로 사용할 경우 접근 범위를 private으로 주고 외부에서는 데이터를 변경할 목적으로 set 메서드를 사용할 수 없다.
- 도메인 상태 변경을 하는 메소드의 네이밍은 계속 진화할 수 있다 -> 개발을 할 수록 도메인을 더 잘 이해하기 때문
- 절대적으로 도메인에 사용하는 언어를 고민하고 또 고민해서 작성해야한다. 그래야 유지보수 측면이든 팀이랑 의사소통을 하던 파악하기가 편리하다.
public OrderState {
STEP1, STEP2, STEP3, STEP4, STEP5, STEP6
}
- 위 처럼 주문의 상태값을 저렇게 STEP으로 나열하면 작성한 사람만 알 수 있다.
public enum OrderState {
PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED;
)
- 위 처럼 단어를 정확히 명시를 하면 어떤 상태인지 파악하기가 쉽다.
Entity
- 엔티티의 가장 큰 특징은 식별자를 갖는다. 식별자는 엔티티 객체마다 가지고 있는 고유의 값이다.
- 식별자는 절대로 바뀌지가 않는다.
- 식별자가 같으면 식별자를 이용해 equals()메소드와 hashcode() 메소드로 두 엔티티가 같다고 판단할 수 있다.
- 식별자는 다음 중 한 가지 방식으로 생성된다.
- 특정 규칙에 따라 생성
- UUID나 Nano ID와 같은 고유 식별자 생성기 사용
- 값을 직접 입력
- 일련번호 사용(시퀀스나 DB의 자동 증가 컬럼 사용 -> pk id)
보통은 2번이나 4번 방법으로 많이 사용한다. UUID같은 경우에는 entity의 id값이 외부로 노출되지 않아 보안에 우수하며 또한 multi-db인 경우에는 유일성도 보장해주는 식별자다. 하지만 식별자를 UUID로 가지는 경우 시퀀스(id)에 비해 메모리를 많이 가져 간다. 상황에 맞게 전략적으로 잘 사용해야한다.
- 의미를 명확하게 하기 위해 기본형이나 참조형 데이터 타입을 객체로 생성해서 사용할 수 있다.
public class Money {
private int value;
public Money(int value) {
this.money = money;
}
)
public class OrderLine {
private Product product;
private Money price;
private int quantity;
private Money amounts;
...
- 위 처럼 기본형인 int를 money라는 객체로 사용해서 OrderLine 클래스에서 명확하게 price는 money(돈, 숫자) 임을 알 수 있다. 개발자는 money라는 객체를 정수 타입 연산이 아닌 돈 계산이라는 의미로 코드를 작성할 수 있다.
결론
길지만 개인적으로 중요한거 같아서 책에서 그대로 가져왔다.
- 도메인에서 사용하는 용어의 의미를 명확하게 전달하는 영단어를 찾기 힘든 경우도 있고,
반대로 비슷한 의미의 영단어가 많으면 각 단어의 뉘앙스나 미세한 차이를 몰라서 선택하기 어려울 때도 있다. 도메인
용어의 '상태'를 코드로 표현할 때 'state'와 'status' 중 어떤 단어를 사용할지 고민해야 하고, '종류'를 표현
하기 위해 'kind'와 'type' 중 어떤 단어가 맞는지 고심할 때도 있다. 그냥 이해하기 쉽게 발음 나는 대로 gubun(구분)
과 같은 이름을 사용하기도 한다.
알맞은 영단어를 찾는 것은 쉽지 않은 일이지만 시간을 들여 찾는 노력을 해야 한다. 한영사전을 사용해서 적당한 단어를
찾는 노력을 하지 않고 도메인에 어울리지 않은 단어를 사용하면 위 코드는 도메인과 점점 멀어지게 된다. 그러니 도메인
용어에 알맞은 단어를 찾는 시간을 아까워하지말자. - 위에서 말하는 것처럼 네이밍이나 도메인에 대해 고민을 할 때 중요하다 생각한 후 개발했지만, 생각한것 만큼 시간을 사용하고 고민하고 또 고민하지 않은 것 같다. 이번 CH1을 통해 조금 더 개발할 때 도메인적으로 접근하고 고민하고 또 고민한 후에 코드를 작성해야겠다는 경각심이 생겼다.
reference:
- 도메인 주도 개발 시작하기 by 최범균 (http://www.yes24.com/Product/Goods/108431347)
'책 > 도메인 주도 개발' 카테고리의 다른 글
[DDD] 도메인 주도 개발 시작하기 CH_5. 스프링 데이터 JPA를 이용한 조회 기능 (0) | 2023.02.18 |
---|---|
[DDD] 도메인 주도 개발 시작하기 CH_4. 리포지터리와 모델 구현 2편 (0) | 2023.02.13 |
[DDD] 도메인 주도 개발 시작하기 CH_4. 리포지터리와 모델 구현 1편 (0) | 2023.02.10 |
[DDD] 도메인 주도 개발 시작하기 CH_3.Aggregate(애그리거트) (0) | 2023.02.06 |
[DDD] 도메인 주도 개발 시작하기 CH_2.아키텍쳐 개요 (2) | 2023.02.02 |