Использование обратного вызова вместо возврата объекта состояния

StackOverflow https://stackoverflow.com/questions/2205959

Вопрос

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

  • Успех
  • Неудача
  • Ожидающий рассмотрения

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

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 является классом, представляющим Временная единица и период, позволяющий приложению перенести выполнение транзакции.Другой альтернативой является создание исключения, описывающего причину сбоя (поскольку оно должно завершаться сбоем только в исключительных условиях), и сохранение onSuccess и onPending методы.

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

Это было полезно?

Решение

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

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

Редактировать - повторите комментарий оператора.

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

Другие советы

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top