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