도메인 구동 디자인 (DDD)에서 조회 테이블을 모델링하는 실용적인 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/808481

  •  03-07-2019
  •  | 
  •  

문제

나는 단지 DDD를 배우고 있습니다 (Eric Evans Book은 내 앞에서 열려 있습니다). 나는 답을 찾을 수없는 문제를 발견했습니다. 간단한 조회 레코드 목록을 얻으려고 할 때 DDD에서 무엇을합니까?

전.

Employeeid : 123
Employeename : John Doe
주 : 알래스카 (드롭 다운)
카운티 : Wasilla (드롭 다운-상태에 따라 필터링).

예를 들어, 직원 도메인 객체, IEMPLOYEEREORITION 인터페이스 및 EmployeEREOTIONTION 클래스가 있다고 가정 해 봅시다. 이것은 UI가 직원 및 개인 세부 정보 목록을 표시하는 데 사용됩니다. UI에서는 직원이 거주하는 주 및 카운티에 드롭 다운을 사용하려고합니다. 가용 카운티는 어떤 주를 선택했는지에 따라 필터링됩니다.

불행히도 데이터베이스 테이블과 UI는 매우 다르게 보입니다. tblemployees에서는 주 및 카운티 이름이 아닌 주 코드 = AK 및 카운티 코드 = 02130을 포함합니다.

오래된 방법 (이 DDD 퀘스트를 시작하기 전에)은 매우 간단 할 것입니다. 단지 2 개의 쿼리를 만들고 DataReader를 사용하여 드롭 다운을 채우십시오. 드롭 다운의 디스플레이 아래에는 값이 있으며, 이는 양식 게시물에 자동으로 사용됩니다.

그러나 DDD를 사용하면 어떻게 해야하는지 잘 모르겠습니다. 처음에는 주 및 카운티 객체와 저장소의 저장소 및 인터페이스를 만들기 시작했습니다. 그러나 4 개의 클래스 + 2 개의 인터페이스를 작성하고 HBM.XML 파일의 배관 + 직원 비즈니스 객체는 2 개의 드롭 다운에 대해 2 쿼리에 대한 과잉처럼 보입니다. 더 나은 방법이 있어야합니까? 나는 곧 주 또는 카운티 테이블의 레코드를 변경하지 않으며, 내가 그렇게 하더라도이 응용 프로그램을 통해서는 안됩니다. 따라서 필요하지 않으면 주와 카운티를위한 비즈니스 객체를 만들고 싶지 않습니다.

내가 보는 가장 간단한 솔루션은 getStatesall (), getState () 및 getCounties () 및 getCounty ()와 같은 사전을 반환하는 메소드를 사용하여 도우미 클래스를 만드는 것입니다.

도와주세요. 간단한 몇 가지 조회를 과도하게 참여하지 않고 DDD를 어떻게 사용할 수 있습니까?

마지막 해결책리포지토리 클래스는 아니지만 GetStates () 메소드를 자체 데이터 액세스 클래스에 넣는 경험을 통해 내 답변을 마침내 찾았습니다. 읽기 전용 액세스 만 수행했기 때문에 구조물 DTO에 던졌습니다. 데이터베이스는 작기 때문에 아래에 설명 된 Todd와 같이 단일 클래스에 모두 던졌습니다.

내 결론 :

  1. 조회 테이블에는 항상 아이덴티티가 있기 때문에 조회 테이블은 객체를 가치가 없습니다. 그들이 정체성이 없다면, 당신은 중복을 가지고있을 것입니다.
  2. 읽기 전용 조회 테이블에는 저장소가있을 수 있지만 아마도 필요하지 않을 수 있습니다. 저장소의 목표는 집계를 통해서만 액세스를 강제하여 복잡성을 줄이는 것입니다. 집계를 통과하면 자동차가없는 경우 타이어를 추가하지 않는 등 비즈니스 규칙을 시행 할 수있는 방법을 제공합니다.
  3. 조회 테이블에서 CRUD 유지 보수를 허용하는 경우 조회 테이블에 자체 저장소가있는 것이 좋습니다.
  4. 내가 코드를 structs로 저장하게된다는 사실은 그것들을 "값 유형"으로 만들지 않습니다. Fowler는 Poeaa에서 구조물이 값 유형이라고 말합니다. 사실, Structs는 불변이기 때문에 Fowler는 그들이 "가치 유형"이라고 말하지만 다르게 사용하고있었습니다. 나는 초기 창조 후에 변화를 계획하지 않은 DTO를 통과하는 가벼운 방법으로 스트러크를 사용하고있었습니다. 사실, 내가 사용한 구조는 실제로 정체성을 가지고 있었지만 읽기 전용이기 때문에 그들은 구조로 일했습니다.
  5. 내가 사용했던 패턴 중 하나는 다른 곳에서 많이 보지 못하는 패턴 중 하나는 기본 키 필드를 불변으로 만드는 것입니다. 그들은 생성자에 의해 설정되었지만 읽기 전용 (개인 액세서가 아님)이며 객체가 생성되면 변경할 수 없습니다.
도움이 되었습니까?

해결책

당신은 개념을 조사하고 싶을 수도 있습니다 명령 쿼리 분리. 조회 값에 대한 유형의 리포지토리에 대해 걱정하지 않지만 데이터 세트 등을 통해 DTO 유형 클래스를 사용할 것입니다 ...

Greg Young의 블로그를 읽는 데 시간을 보내고 싶을 수도 있습니다. 이 하나 현재로. 그는 구체적으로 조회 데이터를 채우는 것에 대해 이야기하지 않지만 종종 저장소에서 입력 된 메소드를 통해 응용 프로그램의 읽기/보고 기능을 처리하지 않는 것에 대해 종종 이야기합니다.

다른 팁

DDD를 사용하면 다음과 비슷한 것이 있습니다.

interface IAddressService
{
  IList<Country> GetCountries ();
  IList<State> GetStatesByCountry (string country);
  IList<City> GetCitiesByState (string state);
  // snip
}

국가, 주 및 도시는 데이터베이스의 조회 테이블에서 나오는 가치 객체입니다.

글쎄, 나는 기사를 읽었다 Mathias Verraes 얼마 전에 이것에 대해 이야기합니다 여기. 그는 UI를 제공하는 개념에서 모델의 가치 객체를 분리하는 것에 대해 이야기합니다.

국가를 대상으로 모델을 대상으로 인용 : 엔티티 또는 가치 객체 :

모델링 국가에는 실체로서 본질적으로 문제가 없으며 데이터베이스에 저장하는 것은 없습니다. 그러나 대부분의 경우, 그것은 일을 과도하게 복잡하게합니다. 국가는 자주 변하지 않습니다. 국가의 이름이 바뀌면 실제로 모든 실용적인 목적으로 새로운 국가입니다. 언젠가 국가가 더 이상 존재하지 않는다면, 국가가 두 나라로 나뉘어 있었기 때문에 모든 주소를 단순히 변경할 수는 없습니다.

그는 새로운 개념을 소개하기위한 다른 접근법을 제안했습니다. AvailableCountry:

이용 가능한 국가는 데이터베이스의 엔티티, JSON의 레코드 또는 단순히 코드의 하드 코드 목록이 될 수 있습니다. (이는 비즈니스가 UI를 통해 쉽게 접근 할 수 있는지 여부에 따라 다릅니다.)

<?php

final class Country
{
    private $countryCode;

    public function __construct($countryCode)
    {
        $this->countryCode = $countryCode;
    }

    public function __toString()
    {
        return $this->countryCode;
    }
}

final class AvailableCountry
{
    private $country;
    private $name;

    public function __construct(Country $country, $name)
    {
        $this->country = $country;
        $this->name = $name;
    }

    /** @return Country */
    public function getCountry()
    {
        return $this->country;
    }

    public function getName()
    {
        return $this->name;
    }

}

final class AvailableCountryRepository
{
    /** @return AvailableCountry[] */
    public function findAll()
    {
        return [
            'BE' => new AvailableCountry(new Country('BE'), 'Belgium'),
            'FR' => new AvailableCountry(new Country('FR'), 'France'),
            //...
        ];
    }

    /** @return AvailableCountry */
    public function findByCountry(Country $country)
    {
        return $this->findAll()[(string) $country];
    }
}

따라서 테이블을 가치 객체와 엔티티로 모델링하는 세 번째 솔루션이있는 것 같습니다.

BTW 댓글 섹션을 확인하십시오 심각한 토론 기사에 대해.

주와 카운티는 단체가 아니라 가치있는 대상입니다. 그들은 당신의 시스템의 주제가 아닙니다. 당신이 이전에 이것을 대했다고 말한 방식은 괜찮습니다. 도메인 모델 상태의 변경에 따라 데이터베이스의 주 또는 카운티 레코드를 언제 변경합니까? 그렇지 않으므로 저장소가 필요하지 않습니다.

당신은 그것을 과도하게 복잡하지 않고 DDD를하는 방법을 배우고 싶다면 잘못된 책을 읽고 있습니다. :-)

당신이 제안하는 가장 간단한 솔루션은 필요에 맞는 경우 괜찮습니다. 비즈니스 객체의 주소 데이터를 캡슐화하면 응용 프로그램이 요구하는 것만 큼 간단하거나 복잡 할 수 있습니다. 예를 들어, 주 대상은 카운티와 일대일 관계를 맺고 있으므로 직원은 그렇게 모델링하기로 선택한 경우 카운티를 참조해야합니다. 필요한 경우에만 그런 종류의 복잡성을 소개합니다.

또한, 객체에 대한 여러 리포지토리가있을 수있는 실질적인 가능성이 없다면 저장소의 인터페이스를 정의하여 얻을 수있는 것이 많지 않다고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top