소프트웨어에서 표현되는 모델

모델 기반 설계(Model-Driven Design)를 구현하면서 타협하지 않으려면 기본 개념을 재구성하는 것이 중요합니다. 특히 객체 간의 연관 관계와 이를 설계 및 간소화하는 문제에 집중합니다.

연관 관계 설계 및 간소화

객체 간의 연관 관계는 모델링과 구현 간의 상호작용에서 특히 까다롭습니다. 연관 관계는 단순하게 그릴 수 있지만 구현 시 복잡해질 수 있습니다. 다음은 연관 관계를 보다 실용적으로 만드는 몇 가지 방법입니다.

방향 부여

연관 관계를 단방향으로 설정하여 상호 의존성을 줄이고 설계를 단순화할 수 있습니다. 예를 들어, 미국의 대통령과 국가 간의 관계는 단방향으로 설정할 수 있습니다. 현실적으로 '조지 워싱턴'이 어느 나라의 대통령인지를 묻는 경우는 드물기 때문입니다.

한정자 추가

연관 관계를 제한하여 다중성을 줄이고 중요한 규칙을 모델에 명시적으로 포함할 수 있습니다. 예를 들어, 한 국가에는 동시에 한 명의 대통령만 존재할 수 있다는 규칙을 모델에 반영할 수 있습니다.

비필수 연관 관계 제거

필수적이지 않은 연관 관계를 제거하여 복잡성을 줄이고 유지보수를 용이하게 합니다. 예를 들어, '브로커리지 계좌'와 '투자' 간의 관계에서 불필요한 연관 관계를 제거할 수 있습니다.

예제: 브로커리지 계좌의 연관 관계

브로커리지 계좌 모델을 예로 들어 설명합니다.

초기 모델

브로커리지 계좌는 고객과 투자 객체와 연관됩니다. 이 연관 관계는 객체 포인터나 데이터베이스 조회를 통해 구현될 수 있습니다.

다중성 제한

특정 주식에 하나의 투자만 존재하도록 연관 관계를 제한하여 모델을 간소화할 수 있습니다. 예를 들어, 동일한 주식에 여러 투자가 존재하지 않도록 제한할 수 있습니다.

코드 예시

public class BrokerageAccount {
    String accountNumber;
    Customer customer;
    Map<String, Investment> investments;
    
    public Customer getCustomer() {
        return customer;
    }
    
    public Investment getInvestment(String stockSymbol) {
        return investments.get(stockSymbol);
    }
}

엔티티와 값 객체의 구분

모델을 표현할 때, 엔티티(ENTITY)와 값 객체(VALUE OBJECT)의 구분은 매우 중요합니다.

엔티티(ENTITY)

엔티티는 지속성과 식별성에 의해 정의됩니다. 엔티티는 시간이 지나도 동일한 식별성을 유지하며, 다양한 상태로 변할 수 있습니다.

예시

고객 객체는 시간이 지나도 동일한 식별성을 가집니다. 고객의 속성(예: 이름, 주소)은 변할 수 있지만 고객의 고유 ID는 변하지 않습니다.

값 객체(VALUE OBJECT)

값 객체는 속성만으로 정의되며 식별성을 갖지 않습니다. 값 객체는 불변성으로 설계되어 복사 및 공유가 용이합니다.

예시

색상 객체는 동일한 속성을 가진 여러 인스턴스로 존재할 수 있으며, 이는 값 객체로 처리됩니다.

코드 예시

public class Address {
    private final String street;
    private final String city;
    private final String state;

    public Address(String street, String city, String state) {
        this.street = street;
        this.city = city;
        this.state = state;
    }

    // 불변 객체이므로 setter 메서드는 제공하지 않음
}

서비스의 개념

서비스(SERVICE)는 개념적으로 객체로 모델링하기 어려운 도메인 작업을 캡슐화합니다.

서비스의 정의

서비스는 도메인 모델의 일부로 정의되며, 도메인 언어를 사용하여 인터페이스를 설계합니다. 서비스는 상태를 가지지 않으며, 요청 시 클라이언트에게 작업을 수행합니다.

도메인 서비스

도메인 내에서 중요한 프로세스나 변환을 수행하는 독립적인 인터페이스로 정의됩니다. 예를 들어, 자금 이체 서비스는 계좌 객체와 관련된 도메인 로직을 포함합니다.

서비스의 특징

  1. 도메인 개념과의 관계: 서비스는 도메인 개념과 직접 관련되며, 엔티티나 값 객체와 달리 상태를 가지지 않습니다.

  2. 인터페이스 정의: 서비스의 인터페이스는 도메인 모델의 다른 요소들로 정의되며, 도메인 언어를 사용합니다.

  3. 상태 없음: 서비스는 상태를 가지지 않으며, 모든 클라이언트가 동일한 인스턴스를 사용할 수 있습니다.

코드 예시

public class TransferService {
    public void transferFunds(Account fromAccount, Account toAccount, BigDecimal amount) {
        // 자금 이체 로직 구현
    }
}

모듈의 중요성

모듈(MODULE)은 개념적 응집력을 가지고 도메인 모델의 큰 그림을 이해하기 쉽게 합니다.

모듈화의 목적

높은 응집력과 낮은 결합도를 통해 복잡성을 줄이고 모델의 변경을 쉽게 합니다. 예를 들어, 고객 모듈과 주문 모듈은 독립적으로 이해할 수 있도록 구성됩니다.

모듈 이름

모듈 이름은 도메인 모델의 개념을 반영하며, 개발자 간의 커뮤니케이션을 촉진합니다.

모듈 설계의 실천

모듈은 도메인 모델의 개념을 조직화하고, 코드의 이해와 변경을 용이하게 합니다.

기술적 구분

인프라 코드와 도메인 코드를 분리하여 모듈화를 실현합니다.

도메인 중심의 모듈화

도메인 개념을 반영한 모듈 구성을 통해 모델과 구현의 일관성을 유지합니다.

예제: 브로커리지 계좌의 모듈화

브로커리지 계좌는 고객과 투자 객체와의 관계를 가지며, 이를 모듈화하여 관리할 수 있습니다. 각 모듈은 독립적으로 동작하면서도 전체 시스템과 통합될 수 있도록 설계됩니다.

이 장에서는 모델 기반 설계의 핵심 요소들을 소프트웨어로 구현하는 방법을 다루며, 세부적인 설계 결정이 모델의 표현력과 구현의 유지보수성에 미치는 영향을 강조합니다. 각 요소들은 모델과 구현 간의 명확한 연관성을 유지하도록 설계되어야 하며, 이를 통해 개발자는 도메인 개념을 소프트웨어에 효과적으로 반영할 수 있습니다.

Last updated