Я до сих пор помню старые добрые времена хранилищ. Но хранилища со временем становились безобразными. Тогда CQRS получил господствующую тенденцию. Они были хороши, они были глотком свежего воздуха. Но в последнее время я снова и снова спрашиваю себя, почему я не придерживаюсь логики в методе Controller's Action (особенно в Web Api, где action сам по себе является своего рода обработчиком команд / запросов).
Ранее у меня был четкий ответ на этот вопрос: я делаю это для тестирования, так как сложно протестировать Controller со всеми этими немодными синглетонами и общей уродливой инфраструктурой ASP.NET. Но времена изменились, и классы инфраструктуры ASP.NET стали гораздо более удобными для модульных тестов (особенно в ASP.NET Core).
Вот типичный вызов WebApi: команда добавлена, и клиенты SignalR уведомляются об этом:
public void AddClient(string clientName)
{
using (var dataContext = new DataContext())
{
var client = new Client() { Name = clientName };
dataContext.Clients.Add(client);
dataContext.SaveChanges();
GlobalHost.ConnectionManager.GetHubContext<ClientsHub>().ClientWasAdded(client);
}
}
Я могу легко провести юнит-тест / издеваться над ним. Более того, благодаря OWIN я могу настроить локальные серверы WebApi и SignalR и провести интеграционный тест (и, между прочим, довольно быстро).
В последнее время я чувствовал все меньше и меньше мотивации для создания громоздких обработчиков команд / запросов, и я склонен держать код в действиях Web Api. Я делаю исключение, только если логика повторяется или она действительно сложна, и я хочу ее изолировать. Но я не уверен, правильно ли я здесь поступаю.
Каков наиболее разумный подход к управлению логикой в типичном современном приложении ASP.NET? Когда целесообразно переместить ваш код в обработчики команд и запросов? Есть ли лучшие образцы?
Обновить. Я нашел эту статью о подходе DDD-Lite. Похоже, мой подход к переносу сложных частей кода в обработчики команд / запросов можно было бы назвать CQRS-lite.
Ответы:
Является ли CQRS относительно сложной и дорогостоящей моделью? Да.
Это чрезмерная инженерия? Точно нет.
В оригинальной статье, где Мартин Фаулер говорит о CQRS, вы можете увидеть множество предупреждений о том, что не следует использовать CQRS там, где это не применимо:
Мой акцент выше.
Если ваше приложение использует CQRS для всего, то это не CQRS, а слишком ваше приложение. Это отличный шаблон для решения некоторых специфических проблем, особенно в приложениях с высокой производительностью и большим объемом, где параллелизм записи может быть серьезной проблемой.
И это может быть не целое приложение, а лишь небольшая его часть.
Живой пример из моей работы: мы используем CQRS в системе ввода заказов, где мы не можем потерять какие-либо заказы, и у нас есть всплески, когда тысячи заказов поступают одновременно из разных источников в определенные часы. CQRS помог нам поддерживать работоспособность системы и ее адаптивность, в то же время позволяя хорошо масштабировать бэкэнд-системы, чтобы обрабатывать эти заказы быстрее, когда это необходимо (больше бэкэнд-серверов), и медленнее / дешевле, когда не нужно.
CQRS идеально подходит для задачи, когда у вас есть несколько действующих лиц, сотрудничающих в одном наборе данных или пишущих в один и тот же ресурс.
Кроме того, распространение шаблона, созданного для решения одной проблемы на все ваши проблемы, просто создаст вам больше проблем.
Некоторые другие полезные ссылки:
http://udidahan.com/2011/04/22/when-to-avoid-cqrs/
http://codebetter.com/gregyoung/2012/09/09/cqrs-is-not-an-architecture-2/
источник
CQRS не является заменой репозиториев «один на один», потому что это сложный, дорогостоящий шаблон, который полезен только в некоторых случаях.
Вот что Уди Дахан должен сказать по существу:
( источник )
Мартин Фаулер:
( источник )
Наконец, Грег Янг:
( источник )
источник