본문 바로가기

책리뷰/도메인 주도 개발 시작하기(DDD핵심 개념 정리부터 구현까지)

도메인 주도 개발(DDD) 도메인 서비스

728x90
반응형

목차

    도메인 서비스

    도메인 서비스를 사용하는 상황

    • 계산 로직 : 여러 애그리거트가 필요한 계산 로직이나, 한 애그리거트에 넣기에는 다소 복잡한 계산 로직
    • 외부 연동 시스템이 필요한 도메인 로직 : 구현하기 위해 타 시스템을 사용해야 하는 도메인 로직

    계산 로직과 도메인 서비스

    • 할인 규칙 같이 한 애그리거트에 넣기 애매한 도메인 개념 구현시 도메인 서비스를 이용해 도메인 개념을 명시적으로 드러내면 됨 
    • 도메인영역의 애그리거트, 밸류와 같은 구성요소 vs 도메인 서비스 
      • 도메인 서비스는 상태없이 로직만 구현 
      • 도메인 서비스에 필요한 상태는 다른 방법으로 전달받음 
       public class DiscountCalculationService {
    
            public Money calcutationDiscountAmounts(List<OrderLine> orderLines, 
                                                List<Coupon> coupons, 
                                                MemberGrade grade) {
    
                Money couponDiscount = coupons.stream()
                                    .map(coupon -> calculateDiscount(coupon))
                                    .reduce(Money(0), (v1, v2) -> v1.add(v2));
    
                Money membershipDiscount = calculateDiscount(orderer.getMember().getGrade());
                return couponDiscount.add(membershipDiscount);
    
            }
    
            private Money calculateDiscount(Coupon coupon) {
    
            }
    
            private Money calculateDiscount(MemberGrade grade) {
                
            }
        }
    • 할인 계산 서비스 사용 주체는 애그리거트 일 수도 있고 응용서비스일 수도 있음
    public class Order {
    
        public void calculateAmounts(DiscountCalculationService disCalSvc, MemberGrade grade) {
            Money totalAmounts = getTotalAmounts();
            Money discountAmounts disCalSvc.calcutationDiscountAmounts(this.orderLines, this.coupons, grade);
            this.paymentAmounts = totalAmounts.minus(discountAmounts);
        }
    }
    • 애그리거트 객체에 도메인 서비스를 전달하는 것은 응용 서비스의 책임 

    • 도메인 객체에 애그리거트 주입하지 않는다.
    • 도메인 객체는 필드로 구성된 데이터와 메서드를 이용해 개념적으로 하나인 모델을 표현함
    • 모델 내 데이터 필드는 데이터를 담는 중요한 구성요소인데 discountCalculationService는 
      Order객체에서 DB에 데이터를 저장하는데 사용하는 필드가 아님 
    • Order가 제공하는 모든 기능에서 discountCalculationService를 필요로하지 않기 때문에
      애그리거트에 도메인 서비스 객체를 주입할 이유가 없음 

    • 계좌 이체는 두 계좌 애그리거트가 관여함 (출금, 입금)
    • 응용서비스는 두 Account 애그리거트를 구한 후 해당 도메인 영역의 TransferService를 이용해 계좌이체 도메인 기능을 실행 
    • 도메인서비스는 도메인 로직을 수행하고 응용로직수행은 하지 않음 
      트랜잭션처리는 응용로직이므로 응용서비스에서 처리

     

     

    ☝🏼도메인 서비스인지 응용서비스인지 체크 하는 방법

    계좌이체는 계좌 애그리거트의 상태를 변경하고 결제금액로직은 주문 애그리거트의 주문금액을 계산한다.

    이 두 로직은 애그리거트를 변경하고 값을 계산하기 때문에 도메인 로직이다.

    도메인 로직이면서 한 애그리거트에 넣기 적합하지 않기 때문에 도메인 서비스로 구현한다.

     

     

    외부 시스템 연동과 도메인 서비스

    • 외부시스템이나 타 도메인과의 연동 기능도 도메인 서비스가 될 수 있음 

    • 설문조사 시스템에서 설문조사를 생성할 때 사용자가 생성 권한이 있는지 확인하는 역할
    • 도메인로직으로 볼 수 있고 이 로직은 도메인 서비스로 표현 가능 
    • 도메인 로직 관점에서 인터페이스를 작성함 

     

    • 응용서비스는 도메인서비스를 이용해서 생성 권한을 검사함 
    • SurveyPermissionChecker 인터페이스를 구현한 클래스는 인프라스트럭처 영역에 위치 

     

    도메인 서비스의 패키지 위치

     

    • 도메인 서비스는 도메인 로직을 표현하기 때문에 다른 도메인 구성요소와 동일한 패키지에 위치 
    • 명시적으로 구분을 원한다면 domain 패키지 밑에 domain.model, domain.service, domain.repository와 같이 하위 패키지로 구분해서 위치시켜도 됨

     

    인터페이스와 클래스

    • 도메인 서비스의 로직이 고정되어있지 않으면 도메인 서비스 자체를 인터페이스로 구현하고 이를 구현한 클래스를 둘 수 있음 
    • 도메인 서비스의 구현이 특정 구현 기술에 의존하거나 외부 시스템의 API를 실행하면 도메인 영역의 도메인 서비스는 인터페이스로 추상화 해야 함.
    728x90
    반응형