Правильно и неправильно об услугах в DDD - PullRequest
0 голосов
/ 10 июля 2019

Пожалуйста, исправьте меня, если я ошибаюсь (и добавьте другие вещи, которые вы считаете верными):

Службы приложений ...

  • (общедоступный интерфейс) APIдомена
  • , ответственного за загрузку и сохранение агрегатов
  • может обращаться к репозиториям и другим службам инфраструктуры
  • не является частью вездесущего языка доменов
  • должен /может быть очень тонким слоем поверх домена (который в основном обрабатывает загрузку / сохранение агрегатов и делегирует остальное домену)
  • может содержать чистые операции чтения

Доменные службы...

  • "истинный" API домена
  • содержит доменную логику
  • работает только с объектами домена (не с инфраструктурными сервисами, такими как репозитории и почтовые рассылки).sender-services)
  • обычно содержат код, который управляет различными агрегатами
  • является частью вездесущего языка доменов
  • может зависеть от других доменных служб
  • содержит толькоmodifyiнг операции

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Я полагаю, что ваше понимание Domain Service неверно.

Правильной отправной точкой будет глава 5 Domain Driven Design Эрика Эванса, где он определяет Value Object, Entity и Domain Service.

Насколько я могу судить, Эванс основывал свои шаблоны на опыте, накопленном при написании моделей предметной области с использованием Java около 2003 года. В Java все, что не является примитивом, независимым от предметной области, является "объектом"; в то время как вы могли бы реализовать статические функции, не было особенно хороших способов передать их. Вместо этого вам нужно было обернуть функцию внутри объекта.

Таким образом, «доменные службы» являются «объектами без состояния»; объекты, потому что это было ограничением при их передаче, и без сохранения состояния, потому что вся мутация базовых данных является обязанностью объекта, который управляет этими данными.

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

В примере «Перевозка грузов» Груз должен быть назначен маршрутам, но объекты «Грузовые» не управляют своими собственными копиями графиков доставки. Вместо этого запросы к этим таблицам поддерживаются «RoutingService».

Координация сущностей, которую Роберт Мартин назвал Варианты использования , относится к приложениям, а не к управлению доменами (как описано Эвансом).

0 голосов
/ 10 июля 2019

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

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

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

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

    public static DisplayName FromString(
        string displayName,
        CheckTextForProfanity hasProfanity)
    {
        if (displayName.IsEmpty())
            throw new ArgumentNullException(nameof(FullName));

        if (hasProfanity(displayName).GetAwaiter().GetResult())
            throw new DomainExceptions.ProfanityFound(displayName);

        return new DisplayName(displayName);
    }

Следовательно, в домене определен договор на обслуживание домена (в данном случае именованный делегат),

namespace Marketplace.Domain.Shared
{
    public delegate Task<bool> CheckTextForProfanity(string text);
}

, но его реализация является проблемой инфраструктуры и осуществляется на стороне приложения.

namespace Marketplace.Infrastructure
{
    /// <summary>
    /// PurgoMalum is a simple, free, RESTful web service for filtering and removing content of profanity, obscenity and other unwanted text.
    /// Check http://www.purgomalum.com
    /// </summary>
    public class PurgomalumClient
    {
        private readonly HttpClient _httpClient;

        public PurgomalumClient() : this(new HttpClient()) { }

        public PurgomalumClient(HttpClient httpClient) => _httpClient = httpClient;

        public async Task<bool> CheckForProfanity(string text)
        {
            var result = await _httpClient.GetAsync(
                QueryHelpers.AddQueryString("https://www.purgomalum.com/service/containsprofanity", "text", text));

            var value = await result.Content.ReadAsStringAsync();
            return bool.Parse(value);
        }
    }
}
...