Каков практический способ моделирования справочных таблиц в доменно-управляемом дизайне (DDD)? - PullRequest
42 голосов
/ 30 апреля 2009

Я только изучаю DDD (книга Эрика Эванса передо мной открыта), и я столкнулся с проблемой, на которую я не могу найти ответ. Что вы делаете в DDD, когда вы просто пытаетесь получить простой список записей поиска?

Ex.

EmployeeID: 123
Имя сотрудника: Джон Доу
Штат: Аляска (раскрывающийся список)
Округ: Василла (раскрывающийся список - будет отфильтрован по штатам).

Например, допустим, у вас есть объект домена Employee, интерфейс IEmployeeRepository и класс EmployeeRepository. Это будет использоваться пользовательским интерфейсом для отображения списка сотрудников и индивидуальных данных. В пользовательском интерфейсе вы хотите использовать раскрывающийся список для штата и округа, где живет сотрудник. Доступные округа будут отфильтрованы в зависимости от того, какое государство было выбрано.

К сожалению, таблицы базы данных и пользовательский интерфейс выглядят очень по-разному. В tblEmployees он содержит код штата = AK и код округа = 02130, а не названия штатов и округов.

Старый способ (до того, как я начал этот квест DDD) был бы довольно простым, просто создайте 2 запроса и используйте DataReader для заполнения раскрывающихся списков. Под отображением в раскрывающихся списках находится значение, которое автоматически используется в сообщениях формы.

Однако с DDD я не уверен, как ты должен это делать. Сначала я создал объекты State и County, а также репозитории и интерфейсы для репозиториев. Тем не менее, написание 4 классов + 2 интерфейса и верстка в файлах hbm.xml + Employee Business кажется избыточным всего за 2 запроса на 2 выпадающих списка. Должен быть лучший способ, не так ли? Я не изменяю записи в таблицах штата или округа в ближайшее время, и даже если бы я это сделал, это было бы не через это приложение. Поэтому я не хочу создавать бизнес-объекты для штата и округа, если мне это не нужно.

Самое простое решение, которое я вижу, это просто создать вспомогательный класс с методами, которые возвращают словари, такие как GetStatesAll (), GetState () и GetCounties () и GetCounty (), но это просто кажется неправильным с точки зрения DDD.

Пожалуйста, помогите. Как я могу использовать DDD без чрезмерных усилий всего за пару простых поисков?

Окончательное решение Я думаю, что я наконец нашел свой ответ на опыте, который заключался в том, чтобы поместить метод GetStates () в его собственный класс доступа к данным, но не в класс репозитория. Так как у меня был только доступ только для чтения, я бросил его в struct DTO. Поскольку база данных была маленькой, я бросил их в один класс, как описано ниже в Тодде.

Мои выводы:

  1. Таблицы поиска НИКОГДА не являются объектами значений, потому что таблицы поиска ВСЕГДА имеют идентичность. Если бы у них не было личности, у вас были бы дубликаты, что не имело бы особого смысла.
  2. Таблица поиска только для чтения может иметь репозиторий, но, вероятно, он не нужен. Цель репозитория - уменьшить сложность, форсируя доступ только через совокупность. Просмотр совокупности дает вам возможность обеспечить соблюдение бизнес-правил, например, не добавлять шины, если у вас нет автомобиля.
  3. Если вы разрешите обслуживание CRUD для справочной таблицы, то для справочной таблицы имеет смысл иметь собственный репозиторий.
  4. Тот факт, что я в итоге хранил коды как структуры, не делает их "типами значений". Фаулер говорит в POEAA, что структура является типом значения. Это правда, структуры являются неизменяемыми, поэтому Фаулер говорит, что они являются «типами значений», однако я использовал их по-другому. Я использовал структуры как легкий способ обойти DTO, которые я даже не планировал менять после их первоначального создания. По правде говоря, структуры, которые я использовал, действительно имели идентичность, но поскольку они были доступны только для чтения, они работали как структуры.
  5. Один шаблон, который я использовал, которого я не вижу в других местах, - сделать поля первичного ключа неизменными. Они устанавливаются конструктором, но доступны только для чтения (не являются частными средствами доступа) и не могут быть изменены после создания объекта.

Ответы [ 5 ]

6 голосов
/ 01 мая 2009

Возможно, вы захотите взглянуть на концепцию Разделение запросов команд . Я бы не стал беспокоиться о типизированных репозиториях для поиска значений, но я все равно, вероятно, использовал бы классы типов DTO над наборами данных и т. Д ...

Возможно, вы захотите потратить некоторое время на чтение блогов Грега Янга, начиная с этого до настоящего времени. Он не говорит конкретно о заполнении справочных данных, но часто говорит о том, что не обрабатывает функции чтения / отчетности вашего приложения с помощью типизированных методов в хранилище.

6 голосов
/ 01 мая 2009

Используя DDD у меня что-то похожее со следующим:

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

Страна, штат и город - это объекты-значения, полученные из справочной таблицы в базе данных.

3 голосов
/ 26 февраля 2014

Ну, я читал статью Матиаса Верраеса , когда-то об этом здесь . Он говорит об отделении ценностных объектов в модели от концепций, обслуживающих пользовательский интерфейс.

Цитирование из статьи на вопрос, моделировать ли страны как объекты или объекты стоимости:

В модельных странах нет ничего плохого сущности и хранение их в базе данных. Но в большинстве случаев это усложняющие вещи. Страны не часто меняются. Когда название страны меняется, фактически для всех практических целей новая страна. Если однажды страны больше не существует, вы не сможете просто измените все адреса, потому что, возможно, страна была разделена в две страны.

Он предложил другой подход для введения новой концепции под названием AvailableCountry:

Эти доступные страны могут быть субъектами в базе данных, записи в JSON, или даже просто жестко закодированный список в вашем коде. (Это зависит от хочет ли бизнес простой доступ к ним через пользовательский интерфейс.)

<?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];
    }
}

Так что, похоже, существует третье решение, которое заключается в моделировании таблиц поиска как объектов-значений, так и объектов.

Кстати, убедитесь, что вы проверили раздел комментариев для серьезных обсуждений о статье.

2 голосов
/ 01 мая 2009

Вы читаете не ту книгу, если хотите научиться делать DDD, не усложняя его. : -)

Самое простое решение, которое вы предлагаете, подойдет, если оно отвечает вашим потребностям. Инкапсуляция адресных данных в бизнес-объектах может быть такой простой или сложной, как того требует ваше приложение. Например, объект State имеет отношение один-ко-многим с округом, поэтому сотруднику просто нужно указать округ, если вы решили смоделировать его таким образом. Я бы представил такую ​​сложность только в случае необходимости.

Кроме того, я не думаю, что можно многое определить, определяя интерфейсы для ваших репозиториев, если только у вас не будет реальной возможности иметь несколько репозиториев для ваших объектов.

2 голосов
/ 01 мая 2009

Штат и округ не являются субъектами, а ценными объектами. Они не являются предметом вашей системы. То, как вы сказали, что обращались с ними ранее, в порядке. Когда вы измените записи штата или округа в своей базе данных, основываясь на изменениях в состоянии вашей доменной модели? Нет, поэтому им не понадобится репозиторий.

...