ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DDD - Value Object와 Reference Object 4부
    JAVA/DDD 2020. 12. 24. 20:49

     

    • 앞 선 예제에서는 Customer 클래스 자체에 ENTRY POINT의 컬렉션을 관리하는 인터페이스를 추가함으로써 시스템 내에 ENTRY POINT의 인스턴스가 하나만 유지되도록 만들었다.
    •  또 다른 방법으로는 Customer 클래스와는 분리된 별도의 클래스에 Customer 클래스의 컬렉션 관리 인터페이스를 할당하는 방법이 있다.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public void setUp() {
     
      Registrar.init();
     
    }
     
     
     
    public void testCustomerIdentical() {
     
      CustomerRepository customerRepository = new CustomerRepository();    
     
      Customer customer = new Customer("CUST-01""홍길동""경기도 안양시");
     
      customerRepository.save(customer);
     
      Customer anotherCustomer = customerRepository.find("CUST-01");
     
      assertSame(customer, anotherCustomer);
     
    }
     
     
    cs

     

    • Customer 클래스를 통해 컬렉션 관리를 수행하던 이전의 예제와 달리
    • 이번에는 CustomerRepository라는 별도의 REPOSITORY 객체를 사용해서 객체 컬렉션을 관리하고 있다.

     

     

     

    • 별도의 객체로 검색 메커니즘을 분리했으므로 EntryPoint는 단순히 검색 키를 반환하는 메서드만을 제공하면 된다. 
    • 다음은 persist() 메소드를 제거한 EntryPoint 클래스 코드를 나타낸 것이다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class EntryPoint {
     
      private final String identity;
     
     
     
      public EntryPoint(String identity) {
     
        this.identity = identity;
     
      }
     
     
     
      public String getIdentity() {
     
        return identity;
     
      }
     
    }
    cs

     

     

     

     

     

    • Customer 클래스는 이제 더 이상 save() find() 메소드와 같은 컬렉션 관리 메서드를 제공하지 않아도 된다. 
    • 과감히 제거하자.
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    import org.eternity.common.EntryPoint;
     
     
     
    public class Customer extends EntryPoint {
     
    private String customerNumber;
     
    private String name;
     
    private String address;
     
    private long mileage;
     
          
     
    public Customer(String customerNumber, String name, String address) {
     
    super(customerNumber);
     
           this.customerNumber = customerNumber;
     
           this.name = name;
     
           this.address = address;
     
    }
     
          
     
    public void purchase(long price) {
     
           mileage += price * 0.01;
     
    }
     
          
     
    public boolean isPossibleToPayWithMileage(long price) {
     
           return mileage > price;
     
    }
     
          
     
    public boolean payWithMileage(long price) {
     
           if (!isPossibleToPayWithMileage(price)) {
     
                 return false;
     
         }
     
                
     
           mileage -= price;
     
          
     
           return true;
     
    }
     
          
     
    public long getMileage() {
     
           return mileage;
     
    }
     
    }
    cs

     

     

     

     

    • Customer에 대한 컬렉션 관리 메커니즘을 제공하는 CustomerRepository 
    • Registrar를 사용하기 위한 세부 내용을 캡슐화 한다.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class CustomerRepository {
     
        public void save(Customer customer) {
            Registrar.add(Customer.class, customer);
        }
     
        public Customer find(String identity) {
            return (Customer)Registrar.get(Customer.class, identity);
        }
    }
    cs

     

     

    • 이제 테스트 케이스를 실행하자. 
    • 예상한 대로 동일한 객체가 반환되었다.
    • ENTRY POINT의 컬렉션을 관리할 수 있는 기본 인프라가 갖추어진 것이다. 
    • 이제 ENTRY POINT를 효율적으로 관리할 수 있게 되었다.

     

     

    도메인의 복잡성


    • 소프트웨어는 복잡하다. 0 1의 비트들을 갈아 먹이면 모든 것이 동작할 것이라는 단순한 예상과 달리, 0 1을 조합할 수 있는 무수히 많은 방법이 존재하기 때문에 소프트웨어는 복잡하다.
    • 인간의 언어에 비해 표현력에 한계를 지닌 컴퓨터의 언어를 사용하기 때문에 단순할 것이라는 예상과 달리, 복잡한 인간 세상을 담아내야 하기 때문에 소프트웨어는 복잡하다
    • 설상가상으로 소프트웨어를 만드는 것이 근본적으로 불완전한 인간이기 때문에 소프트웨어 개발 과정 역시 복잡하고 불완전할 수밖에 없다.

     

    • 따라서 사람들은 지수적인 소프트웨어의 본질적인 복잡성을 선형적으로 완화하기 위해 다양한 기법들을 적용해 왔다.
    • 이 기법들의 우두머리가 추상화(abstraction). 불필요한 군더더기를 제거하고
    • 현재의 문제 해결에 필요한 핵심 개념만을 끌어안음으로써 문제 영역의 복잡성을 감소시키는 기법을 추상화라고 한다.
    • REFERENCE OBJECT VALUE OBJECT의 개념 역시 도메인 영역을 추상화시키는 한 방법이다.

     

     

    • REFERENCE OBJECT VALUE OBJECT의 분리는 도메인 개념들의 추적성 및 식별성을 추상화하기 위한 분석 기법이다. 
    • 도메인 영역의 개념을 REFERENCE OBJECT VALUE OBJECT로 분리함으로써 도메인의 본질적인 특성에 초점을 맞추게 된다.

     

     

    • 고객은 유일한가? 
    • 고객을 유일하게 구분 짓는 특성은 무엇일까? 
    • 시스템은 고객의 주문 및 구매 기록을 추적하기 위해 어떤 처리를 해야 하는가? 
    • 금액은 유일할 필요가 없는가? 
    • 단순하게 값만 비교하면 되는가?

     

    • 도메인 개념에 대한 이런 질문들은 도메인에 대한 이해를 향상하고 소프트웨어의 전반적인 복잡성을 완화하는 유용한 분석 기법이다.
    • REFERENCE OBJECT를 식별함으로써 시스템의 핵심 개념들의 생명 주기에 초점을 맞출 수 있다. VALUE OBJECT를 식별함으로써 도메인의 일부지만 중요하지 않은 개념들을 걸러낼 수 있다

     

    • 메모리 상에서 REFERENCE OBJECT VALUE OBJECT를 관리하는 것은 그리 어렵지 않다. 
    • 그러나 데이터베이스와 같은 영속성 메커니즘이 끼어드는 순간 세상은 급격하게 일그러진다. 
    • 그 위에 다중 사용자 지원을 위한 동시성 메커니즘이 얹어지기라도 하면 REFERENCE OBJECT VALUE OBJECT에 대한 근본적인 개념에 금이 가기 시작한다. 
    • 이제부터는 단순히 언어적인 측면에서 객체를 구별하던 REFERENCE OBJECT VALUE OBJECT의 개념을 넘어 인프라 스트럭쳐나 구현과 세부 구현과 관련된 문제도 함께 고려해야 한다.

    참조


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

     

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

    AGGREGATE와 REPOSITORY 2부  (0) 2020.12.29
    AGGREGATE와 REPOSITORY 1부  (0) 2020.12.28
    DDD Value Object와 Reference Object 3부  (0) 2020.12.23
    DDD - Value Object와 Reference Object 2부  (0) 2020.12.22
    DDD - Value Object와 Reference Object  (0) 2020.12.21
Designed by Tistory.