JAVA/DDD

AGGREGATE와 REPOSITORY 5부

100win10 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의 적용