Использование обратного вызова вместо возврата объекта состояния - PullRequest
1 голос
/ 05 февраля 2010

В моем приложении я выполняю транзакцию, которая может находиться в трех разных состояниях в конце выполнения:

  • Успех
  • Сбой
  • До

В зависимости от состояния клиент приложения может выполнять различные действия. В случае успеха они захотят получить результат транзакции (виджет). В случае сбоя они захотят получить причину ошибки. В случае, если транзакция находится в состоянии ожидания, они захотят запланировать время для повторной попытки. В настоящее время я возвращаю объект следующими методами:

public interface Result() {
     State getState();
     Widget getWidget(); // Success
     Reason getFailureReason(); // Failure
     Callable<Result> getTask(); // Pending
}

Идея состоит в том, что клиент проверяет состояние объекта результата и вызывает соответствующий метод в зависимости от его значения, например

if (result.getState() == State.PENDING) {
    result.getTask();
}

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

public interface TransactionCallback() {
    void onFailure(Reason reason);
    void onSuccess(Widget widget);
    Delay onPending(Delay previous);
}

Где Delay - это класс, представляющий TimeUnit и период, позволяющий приложению перепланировать выполнение транзакции. Другой альтернативой является создание исключения, заключающего в себе причину сбоя (поскольку оно должно произойти только в исключительных условиях), и сохранение методов onSuccess и onPending.

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

Ответы [ 4 ]

3 голосов
/ 05 февраля 2010

Я не думаю, что это хорошее использование шаблона обратного вызова.

Обратный вызов уместен, если вызываемый объект (например, транзакция в вашем случае) должен продолжить работу после возврата из метода обратного вызова. Но если следующее, что всегда делает вызываемый, - это возврат к вызывающему, то обратный вызов не добавляет никакого значения. Это просто делает структуру кода более сложной и менее читаемой. ИМО, было бы лучше вернуть объект результата или (в случае исключительной ошибки) сгенерировать исключение.

РЕДАКТИРОВАТЬ - повторно комментарий ОП.

Я вижу значение использования метода обратного вызова для запроса вызывающей стороны, должна ли транзакция продолжаться, хотя я, вероятно, использовал бы простой параметр тайм-аута. Однако использование методов обратного вызова для возврата результатов (IMO) по-прежнему неверно.

3 голосов
/ 05 февраля 2010

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

2 голосов
/ 05 февраля 2010

Аргументы обратного вызова должны включать объект, являющийся источником вызова. Звучит хорошо для меня, но использование обратного вызова может повлечь некоторые проблемы с синхронизацией - вы не можете быть уверены, в каком состоянии вы получите обратный вызов. Не невозможно, но может потребоваться рассмотрение.

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

1 голос
/ 05 февраля 2010

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

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

...