Каков практический способ моделирования таблиц подстановки в Domain Driven Design (DDD)?

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

  •  03-07-2019
  •  | 
  •  

Вопрос

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

Бывший.

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

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

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

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

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

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

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

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

Мои выводы:

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

Решение

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

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

Другие советы

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

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

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

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

Цитирую из статьи, когда меня спросили, моделировать ли Страны как сущности или ценностный объект:

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

Он предложил другой подход к внедрению новой концепции под названием 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];
    }
}

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top