В CQRS должна ли моя сторона чтения возвращать DTO или ViewModels? - PullRequest
31 голосов
/ 13 октября 2011

У меня спор с коллегами по разработке стороны чтения приложения CQRS.

Вариант 1: Сторона чтения моего приложения CQRS возвращает DTO, например:

public interface IOrderReadService
{
    public OrderDto Load(int id);
}

public class SomeController
{
    public ActionResult SomeAction(int id)
    {
        var dto = ObjectFactory.GetInstance<IOrderReadService>().Load(id);
        var viewModel = Mapper.Map<OrderDto, SomeViewModel>();
        return View(viewModel);
    }
}

public class SomeOtherController
{
    public ActionResult SomeOtherAction(int id)
    {
        var dto = ObjectFactory.GetInstance<IOrderReadService>().Load(id);
        var viewModel = Mapper.Map<OrderDto, SomeOtherViewModel>();
        return View(viewModel);
    }
}

Вариант 2: Сторона чтения приложения возвращает ViewModels, например ::

public interface IOrderReadService
{
    public SomeViewModel LoadSomething(int id);
    public SomeOtherViewModel LoadSomethingElse(int id);
}

public class SomeController
{
    public ActionResult SomeAction(int id)
    {
        return View(ObjectFactory.GetInstance<IOrderReadService>().LoadSomething(id));
    }
}

public class SomeOtherController
{
    public ActionResult SomeOtherAction(int id)
    {
        return View(ObjectFactory.GetInstance<IOrderReadService>().LoadSomethingElse(id));
    }
}

Из исследований, проведенных мной и моими коллегами по этому вопросу, ответы кажутся смешанными - похоже, это действительно зависит от контекста. Итак, я спрашиваю вас, мои дорогие стеки Оверфлояны:

Кажется ли, что один подход имеет явные преимущества перед другим? Если да, то что они?

Ответы [ 4 ]

30 голосов
/ 13 октября 2011

Общий совет: одна проекция на экран (Грег Янг) или даже одна проекция на виджет (если я правильно понимаю Уди Дахана).

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

Мой совет: постарайтесь максимально приблизиться к SELECT * FROM ViewSpecificTable [WHERE ...] или чему-то подобному, если используете NoSQL в вашем тонком слое чтения.

Концепция Aggregate Roots и их «потомков» не имеет большого значения для чтения, поскольку это концепции доменной модели.Вы не хотите иметь модель предметной области на стороне чтения, она существует только на стороне записи.

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

Короче говоря: я бы выбрал вариант 2. Чтобы не путать его с платформой ViewModel, я бы лучше назвал ее ReadModel, но в любом случае по одному на просмотр.

13 голосов
/ 13 октября 2011

Один из основных принципов DDD / CQRS заключается в том, что вам не следует редактировать модель представления. Вместо этого экраны на основе задач должны направлять пользователя к выполнению явных команд. Если вы не можете придумать экраны, основанные на задачах, вам следует использовать другую форму CQRS, такую ​​как я описываю здесь:

http://udidahan.com/2011/10/02/why-you-should-be-using-cqrs-almost-everywhere/

5 голосов
/ 13 октября 2011

Я бы предпочел вернуть DTO, чтобы отделить прикладной уровень от технологии представления (поскольку каждая технология представления может иметь некоторые требования к структуре модели представления), например, привязка веб-приложения MVC отличается от привязки WPF MVVM, также вы можете требуются некоторые свойства / поля в моделях представления, которые не имеют ничего общего с данными приложения, например, (SliderWidth или IsEmailFieldEnabled, ...). Также, например, если используется WPF MVVM, мне потребуется реализовать интерфейс INotifyPropertyChanged, чтобы разрешить привязку, это неудобно и не связано с реализацией этого интерфейса в службе чтения приложений.

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

Так что вариант 1 для меня лучше

3 голосов
/ 13 октября 2011

Модель чтения - это проекция модели записи. Это там, чтобы выполнить конкретную цель. В вашем случае это, кажется, предоставляет модели представления для ваших контроллеров MVC. Как таковой, зачем идти на карту отображения DTO в Viewmodels? Единственная причина, по которой я мог придумать, состояла в том, что преимущество наличия двух отдельных моделей чтения может не перевесить их стоимость обслуживания. Но учтите, что «объединение» моделей чтения с целью «повторного использования» и «снижения затрат на обслуживание» увеличивает сложность для разработчика (Могу ли я изменить эту таблицу? Хм, у меня теперь есть два (или более) потребителя, которых я должен принять во внимание учетная запись - пахнет немного как интеграция базы данных снова).

Только мои мысли.

...