ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • AGGREGATE와 REPOSITORY 5부
    JAVA/DDD 2021. 1. 8. 19:48

    ENTRY POINT REPOSITORY

     

    • 주문은 주문 AGGREGATE ENTRY POINT이다. 
    • 따라서 주문이 필요한 경우 OrderRepository를 통해 해당 주문 객체를 얻을 수 있다. 
    • 그럼 특정한 고객에 대한 주문 목록을 얻어야 한다면 어떻게 해야 할까? 

     

    • 쉽게 생각해 볼 수 있는 방법은 CustomerRepository로부터 고객 객체를 얻은 후 연관을 통해 해당하는 Order 객체들에게 접근하는 것이다. 
    • 그러나 이 방법은 Order Customer 클래스 간에 양방향 연관 관계를 추가한다. 
    • 특정 객체에 속하는 다른 객체들을 조회하는 요구사항마다 양방향 연관 관계를 설정한다면 감당하기 어려울 정도로 모델이 복잡해질 것이다.

     

    • 고객에 해당하는 주문 목록을 조회하는 적절한 방법은 OrderRepository에 고객 별 주문 목록을 조회하는 메서드를 추가하는 것이다.
    • OrderRepository Order의 컬렉션을 관리하기 위해 추가된 PURE FABRICATION이다.
    • 따라서 주문 객체를 얻기 위해 OrderRepository를 사용하는 것은 논리적으로 타당할 뿐만 아니라 주문 객체에 접근하기 위한 일관성 있는 방법을 제공한다. 
    • 또한 OrderRepository를 통해 Order와 Customer 간의 양방향 연관 관계를 방지할 수 있다.

     

     

    • OrderRepository에 기능을 추가하기 전에 실패하는 테스트부터 작성하자. 
    • 테스트가 OrderRepository에OrderRepositoryTest 클래스를 추가한 후 테스트 메서드를 작성하자.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public class OrderRepositoryTest extends TestCase {
     
        private Customer customer;
        private OrderRepository orderRepository;
        private ProductRepository productRepository;
        
        public void setUp() throws Exception {
            Registrar.init();
            orderRepository = new OrderRepository();
            productRepository = new ProductRepository();
            productRepository.save(new Product("상품1"1000));
            productRepository.save(new Product("상품2"5000));
            customer = new Customer("CUST-01""홍길동""경기도 안양시"200000);
        }
        
        public void testOrdreCount() throws Exception {
            orderRepository.save(customer.newOrder("CUST-01-ORDER-01")
                    .with("상품1"5)
                    .with("상품2"20)
                    .with("상품1"5));
            orderRepository.save(customer.newOrder("CUST-01-ORDER-02")
                    .with("상품1"20)
                    .with("상품2"5));
            assertEquals(2, orderRepository.findByCustomer(customer).size());
        }
    }
    cs

     

    • 두 번의 주문을 수행하여 생성된 Order 객체를 OrderRepository에 추가한다. 
    • 단언 문을 사용하여 고객에게 속한 주문이 두 건인지를 검증한다. 이제 OrderRepository findByCustomer() 메소드를 추가하자.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    OrderRepository.java
     
    public Set<Order> findByCustomer(Customer customer) {
            Set<Order> results = new HashSet<Order>();
            
            for(Order order : findAll()) {
                if (order.isOrderedBy(customer)) {
                    results.add(order);
                }
            }
            return results;
        }
        @SuppressWarnings("unchecked")
        public Set<Order> findAll() {
            return new HashSet<Order>((Collection<Order>)Registrar.getAll(Order.class));
        }
    }
    cs

     

    • findByCustomer() 메소드는 전체 주문 중에서 특정 고객에 속한 주문의 컬렉션을 반환한다.
    • Order Customer 정보를 알고 있으므로 INFORMATION EXPERT 패턴에 따라 고객에 포함되어 있는지 여부를 판단할 수 있는 isOrderedBy() 메소드를 Order에 추가한다.
    1
    2
    3
    4
    5
    Order.java
     
    public boolean isOrderedBy(Customer customer) {
        return this.customer == customer;
    }
    cs

     

    • Customer 클래스가 REFERENCE OBJECT이고 CustomerRepository에 의해 유일성과 추적성이 보장되므로 동등성 비교를 위해 ”==” 연산자를 사용했다. 
    • 테스트는 이제 성공한다.
    • 주문도 정상적으로 처리되고 불변식도 위반하지 않고 중복되는 주문 항목도 없고 고객의 주문 목록도 조회할 수 있게 되었다.

     

    참조


    이터니티 - Domain-Driven Design의 적용

    'JAVA > DDD' 카테고리의 다른 글

    DDD - Dependency Injection과 AOP 2부  (0) 2021.01.22
    DDD - Dependency Injection과 AOP 1부  (0) 2021.01.11
    AGGREGATE와 REPOSITORY 4부  (0) 2021.01.05
    Aggregate와 Repository 3부  (0) 2020.12.30
    AGGREGATE와 REPOSITORY 2부  (0) 2020.12.29
Designed by Tistory.