Ваши решения кажутся мне хорошими. Я использую подобные методы, и они хорошо работают.
Наличие Команд инкапсулирует некоторую логику приложения - это хороший шаблон, и возвращение результатов из них - не плохая вещь. Если вы этого не сделаете, это означает, что вам придется делать дополнительные запросы, чтобы выяснить результат, и это может привести к снижению производительности. Почему плохо возвращать результат из Command , чтобы избежать одного или нескольких обращений к базе данных?
Если вы имеете в виду такие принципы, как CQS , в которых говорится, что Команды не должны возвращать результаты, возможно, нам придется немного подробнее поговорить об определении Command . Этот принцип предназначен для объектов в ОО-системе и применяется к методам на объектах, а не для Команды как объекта, выполняющего некоторую логику приложения, как объясняет Мартин Фаулер здесь . Вы можете применять его везде, где вы как из couse. Никто не останавливает вас, но для того, чтобы полностью понять то, что вам нужно, теперь это задумано.
Лучше думать об этих методах команды как о мутаторах состояния объекта. Если они работают как мутаторы и запрашивают что-то, это может быть сложнее для понимания и использования. Однако иногда полезно иметь метод command / mutator , который изменяет состояние и возвращает результат. как в случае Stack.Pop () . Лучше придерживаться этого шаблона большую часть времени, но если вы не можете просто не делать этого.
Определение общего интерфейса, который должен возвращать результат, который может различаться в строго типизированном языке, может быть сложной задачей. Если вы делаете это на таком языке, как JavaScript, то это не проблема. Вы либо возвращаете результат, либо нет. Если вы это сделаете, то получатель проверит, какие свойства имеет этот объект. По моему опыту, как со свободными типами, так и со строго типизированными языками, это одна из вещей, которую легче реализовать. Потому что у вас есть динамические данные, возвращенные из того же метода.
Вот несколько способов сделать это:
Тот, который вы используете: Используйте разные типы для каждого результата и приведите к нему.
Не определяйте общий интерфейс для всех команд, таких как ICommand . Определите общий интерфейс для семейства команд. Сделайте так, чтобы ваша фабрика возвращала наиболее распространенный объект, подобный классу, который вы приведете позже к IPaymentCommand . Это будет интерфейс для всех PaymentCommands . IPaymentCommand.Execute вернет EmiSchemeValidationResult и ваш штраф. Я использовал это и хорошо работает, если вы заранее знаете тип, который вы собираетесь получить. Если ваш исполняемый код должен быть более общим, это может вызвать проблемы
Определите класс результата, который содержит пару ключ / значение с результатами (сохраните их в HashMap в Java, в Dictionary в C # что-то в этом роде). Вы имитируете пример JavaScript с этим. Хороший шаблон, но он сделает код обработки результатов команды более трудоемким для написания. Иногда это может даже стать неприятным и разозлить вас каждый раз, когда вам нужно написать это.
Добавить свойство с результатом к Command . Если у вас уже есть тип команды, такой как PaymentCommand . Добавьте к нему свойство EmiSchemeValidationResult PaymentCommand.Result и проверьте его после выполнения команды. Я тоже использовал этот шаблон, и он хорошо работал.
Это зависит от потребностей вашего кода и того, что вам (и / или вашей команде) удобно.
Вот статья, которая объясняет эти вещи более подробно:
https://martinfowler.com/bliki/CommandOrientedInterface.html