Подтвердить что ты не робот

Статус возврата команды

Как только я обсудил дизайн, относительно шаблона команды. Мой партнер заявил, что объект команды не должен возвращать статус (успешный, неудачный и почему) после вызова метода .execute(). Причина в том, что вам не следует беспокоиться о том, выполняется ли команда или нет, потому что команда не должна содержать никакого состояния. Однако вы должны проверить после вызова, если команда имела ожидаемый эффект. Другой аргумент, который он утверждал, состоял в том, что в "Группе четырех" шаблон команды не показывает этот случай (возвращаемого статуса).

Я утверждал противоположную точку. GoF не представляет этот случай, но шаблон может быть смоделирован для ваших нужд. Если команда не увенчалась успехом, вызывающий клиент должен получить подтверждение статуса и в конечном итоге развернуть соответствующую реакцию. Заставляя клиента проверить, было ли достигнутое действие успешным, было подвержено ошибкам и выпущен дублированный код. Кроме того, бывают случаи, когда команда производит результат (например, команда, которая добавляет строку к сюжету, каким-то образом будет иметь идентификатор строки для возврата к клиенту), и притворяясь, что команды без состояния означает, что вам приходилось "выкинуть" новый идентификатор объекта из модели данных.

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

4b9b3361

Ответ 1

Есть два вопроса в вопросе с несколькими ответами:) Первый вопрос: должна ли команда вернуть состояние ошибки?

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

Одна из вещей, о которых вам нужно подумать:

  • Я добавляю больше связей ко многим командам и клиентам только для некоторых конкретных случаев ошибок?

В худшем случае у вас много команд, которые не заботятся об ошибках, но одна или две команды делают то, что важно для клиента, чтобы знать, работает ли оно. Теперь вы добавляете проверенные Исключения в Интерфейс, и поэтому каждый клиент и каждая Команда обязаны выполнять обработку ошибок и связаны с Исключением. Если у вас есть клиент, который имеет дело только с командами, которые не выбрасывают исключения, у вас есть большие накладные расходы в вашем коде.

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

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

Второй вопрос: если команда имеет состояние?

Существуют архитектуры, где команде требуется состояние, а некоторые - там, где им не требуется состояние.

Некоторые возможности решить это:

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

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

  • ... Если есть что-то, что, по вашему мнению, должно быть в этом списке, оставьте комментарий.

Ответ 2

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

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

Ответ 3

Я расскажу о "Head First Design Patterns". Примеры, которые они используют для шаблона команды:

  • сценарий ужина (клиент создает заказ, персонал ожидания вызывает его, крича на кухонный персонал, а персонал кухни получает заказ).
  • сценарий удаленного управления (человек нажимает кнопку, дистанционное управление вызывает команду, и устройство получает ее)

Очевидно, что в первом случае получатель получает какое-то состояние: "здесь grub", или "мы из ржаного хлеба". В фантастическом ресторане вы можете сделать это с помощью обработки исключений на более высоком уровне (maitre d 'подходит к столу и извиняется, предлагает замену и комплимент вашего десерта), а персонал ожидания должен ничего не делать, кроме как правильно вызывать команды. Но в закусочной, может быть, повар идет вперед и заменяет коричневый хлеб - персонал ожидания (и клиент) должен иметь возможность справиться с этим, не глядя на стойку, задаваясь вопросом, "где мой тунн на ржи?" Это не рассматривается непосредственно в книге, но я думаю, что это явно обоснованный случай.

Но во втором сценарии invoker намеренно делается глупым. Это не вызовет у вас ошибки, если что-то не так, просто не получится. Все умники находятся в клиенте, чтобы определить, была ли его команда успешной своевременно ( "дерьмо, я забыл подключить его" ) или в приемнике, чтобы выяснить, что делать ( "play CD: закрыть лоток для компакт-дисков" первый ").

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

Ответ 4

Это, безусловно, спорное, но это ясно показывает два стиля мышления:

  • Проверьте, нормально ли что-то, а затем действуйте соответственно
  • Продолжайте все равно и справляйтесь с ним, если что-то не так.

Я не думаю, что один путь лучше другого. Например, в Java обычно лучше не злоупотреблять обработкой исключений и не заботиться о любых возможных проблемах, прежде чем просто бросать руки (и исключения) в воздух. С Python более предпочтительным является просто пойти дальше и попытаться сделать что угодно, независимо от кода состояния, и пусть любое исключение просто обрабатывается соответствующим образом.

Это действительно зависит от того, хотите ли вы, чтобы шаблон команды возвращал статус.

Ответ 5

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

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

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

Примечание: При этом мне было бы интересно услышать мысли о том, почему это может быть запахом кода.

Ответ 6

Очень приятная дискуссия. Я занимался этим философским вопросом часами, и я пришел к решению, которое удовлетворяет мою одержимость. (Причина, по которой я люблю этот материал, состоит в том, что он сочетает в себе конкретную и абстрактную логику - Booleans + design.)

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

В конечном счете, я написал клиента, который сам создает экземпляр приемника, сохраняя всю логику в приемнике, где он принадлежит. Клиент просто вызывает команды execute() и продолжает. Затем получатель может вызвать общедоступные методы на клиенте. Нечего возвращать.

Вот пример кода. Я не написал командный класс, потому что я думаю, что вы получите идею без нее. Его метод execute() вызывает метод run() получателей.

Клиент:

Class ClientType{

    CommandType m_Command;
    ReceiverType m_Receiver;
    boolean m_bResult;

    ClientType(){

      m_Receiver = new ReceiverType(this);
      m_Command = new CommandType(m_Receiver);
    }

    public void run(){  
            ... 
      m_Command.execute();
    }


    /*  Decoupled from both the   
     *  command and the receiver. 
     *  It just a public function that
     *  can be called from anywhere. /
    public setResult(boolean bResult){
      m_bResult = bResult;
    }
}

Приемник:

Class ReceiverType{

    ClientType m_Client;
    boolean m_bResult;

    ReceiverType(ClientType client){
      m_Client = client;
    }

    public void run(){
            ...
      m_Client.setResult(m_bResult);    
    }
}

На первый взгляд может показаться, что Ive нарушило требование развязки. Но учтите, что клиент ничего не знает о реализации приемников. Тот факт, что получатель знает, чтобы вызвать общедоступные методы на клиенте, является стандартным тарифом. Ресиверы всегда знают, что делать с объектами параметров. Никаких зависимостей нет. Тот факт, что конструктор получателей принимает параметр ClientType, не имеет значения. Это может быть и любой объект.

Я знаю, что это старый поток, но надеюсь, что некоторые из вас снова зазвонят. Не стесняйтесь сломать мое сердце, если увидите недостаток. То, что мы делаем.

Ответ 7

Как говорится в вашем вопросе:

Если команда не увенчалась успехом, вызов КЛИЕНТА должен получить доказательство статуса и, наконец, развертывание соответствующая реакция.

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

С уважением,

Ответ 8

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

Ответ 9

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

Команды могут управлять пользовательским интерфейсом через интерфейсы просмотра и сообщать о любых ошибках.

В основном это идет

Формы реализуют IFormInterfaces и регистрируются с помощью ScreenViews в EXE

ScreenObjects реализует IScreenView и регистрируется с помощью сборки ScreenView, а также захватывает команды из сборщиков команд

Команды сборки ссылаются на сборку ScreenView и модель

ScreenView Assembly - это не что иное, как коллекция интерфейсов просмотра и содержит реализацию приложения.