Eternity's Chit-Chat

aeternum.egloos.com



Domain-Driven Design의 적용-2.AGGREGATE와 REPOSITORY 5부 Domain-Driven Design

ENTRY POINT REPOSITORY

주문은 주문 AGGREGATEENTRY POINT이다. 따라서 주문이 필요한 경우 OrderRepository를 통해 해당 주문 객체를 얻을 수 있다. 그럼 특정한 고객에 대한 주문 목록을 얻어야 한다면 어떻게 해야 할까? 쉽게 생각해 볼 수 있는 방법은 CustomerRepository로부터 고객 객체를 얻은 후 연관을 통해 해당하는 Order 객체들에게 접근하는 것이다. 그러나 이 방법은 Order Customer 클래스 간에 양방향 연관 관계를 추가한다. 특정 객체에 속하는 다른 객체들을 조회하는 요구사항마다 양방향 연관 관계를 설정한다면 감당하기 어려울 정도로 모델이 복잡해질 것이다.

 

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

 

OrderRepository에 기능을 추가하기 전에 실패하는 테스트부터 작성하자. 테스트가OrderRepository에 대한 테스트이므로 별도의 테스트 클래스인 OrderRepositoryTest 클래스를 추가한 후 테스트 메소드를 작성하자.


OrderRepositoryTest.java

package org.eternity.customer;

 

import junit.framework.TestCase;

 

import org.eternity.common.Registrar;

 

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());

}

}



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



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));

}


 

findByCustomer() 메소드는 전체 주문 중에서 특정 고객에 속한 주문의 컬렉션을 반환한다. OrderCustomer 정보를 알고 있으므로 INFORMATION EXPERT 패턴에 따라 고객에 포함되어 있는 지 여부를 판단할 수 있는 isOrderedBy() 메소드를 Order에 추가한다.



Order.java
public boolean isOrderedBy(Customer customer) {

return this.customer == customer;

}


Customer 클래스가 REFERENCE OBJECT이고 CustomerRepository에 의해 유일성과 추적성이 보장되므로 동등성 비교를 위해 ”==” 연산자를 사용했다. 테스트를 실행해 보자. 녹색 막대다. 주문도 정상적으로 처리되고 불변식도 위반하지 않고 중복되는 주문 항목도 없고 고객의 주문 목록도 조회할 수 있게 되었다. 이제 고객이 주문이 잘 못 처리됐다고 불평할 일이 없을 것 같다. 통합 빌드를 수행하고 코드를 형상 관리 툴에 체크인 한 후 어서 퇴근 준비를 서두르자


핑백

  • Domain-Driven Design | Jongmin Kim&#039;s Blog 2014-09-02 01:18:29 #

    ... endency Injection과 Aspect-Oriented Programming 1부 2008/11/30 Domain-Driven Design의 적용-2.AGGREGATE와 REPOSITORY 5부 2008/11/27 Domain-Driven Design의 적용-2.AGGREGATE와 REPOSIT ... more