Я должен пойти на компромисс: СУХОЙ или Command-Query-Separation?

10

Недавно я проводил рефакторинг метода, который был и командой, и методом запроса.

Разделив его на один метод команды и один метод запроса, я обнаружил, что в коде теперь есть несколько мест, где я вызываю команду, а затем получаю значение из запроса, что выглядит как нарушение принципа СУХОЙ.

Но если бы я обернул этот общий код в метод, этот метод был бы и командой, и запросом. Это приемлемо?

Крис Уэлш
источник
хорошо, я не знал, было ли сообщество в согласии, и я не мог найти никакого обсуждения этой темы.
Крис Уэлш
Его чаще называют CQRS google.com.au/…
Даниэль Литтл
@DanielLittle - нет, это не так. CQS и CQRS - это совершенно разные предметы. CQRS - это гораздо более сложный архитектурный шаблон, в то время как CQS - это скорее шаблон проектирования, который гораздо проще понять и реализовать. См. Codebetter.com/gregyoung/2009/08/13/command-query-separation
Эрик Фанкенбуш
@Erik Funkenbusch Вы правы
Даниэль Литтл

Ответы:

11

Всегда есть компромисс между противоречивыми принципами проектирования. Чтобы решить эту проблему, нужно взглянуть на причины, лежащие в основе принципов. В этом случае невозможность выполнить запрос без выполнения команды является проблематичной, но невозможность выполнить команду без выполнения запроса, как правило, безвредна. Пока есть способ выполнить запрос автономно, я не вижу причин не добавлять результат запроса в команду, особенно если сделано что-то вроде этого:

QueryResult command()
{
   // do command stuff
   return query();
}
Карл Билефельдт
источник
4

Раньше я не слышал о разделении команд-запросов (CQS), но, похоже, это будет относиться к принципу единой ответственности (SRP), который гласит, что функция / класс в идеале должна отвечать за выполнение только одного и только одного ,

Если ваш код команды состоит из 20 строк кода, а код запроса - это еще 30 строк, и все они находятся в одном теле функции, очевидно, что вы нарушаете SRP, и я бы также предположил, что CQS и эти две части логики должны быть отделены друг от друга. ,

Однако, следуя вашему гипотетическому примеру, я бы, скорее всего, создал метод-обертку, который бы объединял вашу команду и запрос, чтобы DRY не нарушался во многих местах кода. Я бы также не считал это нарушением SRP (и, возможно, CQS), потому что оболочка по-прежнему несет только одну ответственность: объединять команду с запросом и создавать абстракцию более высокого уровня, которую легче использовать.

Я думаю, что метод обертки является вполне приемлемым решением, и чтобы проиллюстрировать это, давайте сделаем ваш пример еще на шаг вперед. Что делать, если вам нужно было выполнить 2 запроса вместо 1, а затем выполнить командное действие, основанное на этом. Таким образом, ваши две строки кода будут 6 или 8. Что если бы между данными и проверкой была некоторая проверка / проверка данных, то теперь у вас есть 15 строк кода. Не могли бы вы дважды подумать о создании оболочки, которая делает все это, вместо того, чтобы разбрасывать эти 15 строк в несколько файлов?

DXM
источник
Я думаю, что «единый принцип» оболочки должен заключаться в том, чтобы другие методы, которым нужна команда и запрос, были сухими.
Дрооганс
Google CQRS: google.com.au/…
Даниэль Литтл
Хотя решение этой проблемы лучше для Карла, я считаю, что ваша разработка более длинных функций-оберток - очень хороший момент.
Крис Уэльс
-3

СУХОЙ является более важным, поскольку он решает гораздо более фундаментальную задачу - избегая лишних, эффективно потраченных усилий. Это фундаментальная вещь - не нужно быть программистом, чтобы понять это.

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

  1. Нельзя избежать необходимости выполнения кода для его результатов, поскольку это является основой для составления больших программ из небольших модулей.

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

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

Реальное решение проблемы слежения за эффектами, которые слишком сложны для людей без посторонней помощи, - это, конечно, чтобы компьютеры помогали нам, людям ! То же самое можно сказать о отслеживании сложных взаимосвязей между значениями времени выполнения (такими как достоверность индексов массива), для которых исключения и принудительно выполняемые контракты представляют собой (не) решения.

В заключение, «решения», такие как CQS, просто мешают проектировать программы в соответствии с разумными принципами, основанными на реальности. Перейти на сухой.

Пен
источник
Иногда вам нужно избегать связывания, чтобы уменьшить сложность. Вы должны взглянуть на CQRS.
Даниэль Литтл
@Lavinski: лучший инструмент для избежания сложности (не уменьшая ее, что бесполезно) - это абстракция, которая отделяет общую сущность проблем, которые мы решаем, от конкретных деталей примеров указанных общих проблем. Магические рецепты (или «шаблоны дизайна», как я их называю) в лучшем случае могут помешать вам нанести слишком большой ущерб, если вы ошибаетесь в своем дизайне, но они не могут превратить неправильный дизайн в правильный.
Пион
@Lavinski: Что касается CQRS, концептуально правильное альтернативное решение состоит в следующем: 1. понять модель данных (никакое количество слоев объектов не может исключить необходимость в этом), 2. кодировать столько свойств корректности, сколько вы можете в схеме базы данных. (К сожалению, большинство популярных RDBMS обеспечивают довольно ограниченную поддержку последних, не говоря уже о NoSQL, что делает это еще более неправильным. Мое текущее исследование предлагает лучшее решение для этого.)
Pyon
CQRS работает полностью в соответствии с Domain Driven Design. Я предлагаю вам немного изучить. Домен внутри приложения должен обеспечивать корректность, а не ваше хранилище данных.
Даниэль Литтл
1
@ EduardoLeón: Если вы хотите доказать, что ваш дизайн верен, попробуйте написать тесты для вашей программы. Я могу гарантировать вам, что отказ от CQS только помешает вам в этом.
Стефан Биллиет