Должен ли я вернуть ноль или сгенерировать исключение? - PullRequest
8 голосов
/ 19 октября 2010

Я нашел здесь вопросы Должен ли метод поиска возвращать 'null' или выдавать исключение, если он не может получить возвращаемое значение? и Должны ли функции возвращать null или пустой объект? , но я думаю, что мой случай совсем другой.

Я пишу приложение, которое состоит из веб-сервиса и клиента.Веб-сервис отвечает за доступ к данным и их возврат клиенту.Я создаю свое приложение так:

// webservice

try
{
   DataTable data = GetSomeData(parameter);
   return data
}
catch (OopsException ex)
{
   //write some log here
   return null; 
}

// client:

   DataTable data = CallGetSomeData(parameter);
   if(data == null) 
   {
      MessageBox.Show("Oops Exception!");
      return;
   }

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

Спасибо.

Ответы [ 11 ]

4 голосов
/ 19 октября 2010

В вашем случае исключение уже было сгенерировано и каким-то образом обработано в вашем веб-сервисе.

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

В случае с клиентом, я думаю, что у вас это хорошо. Я не думаю, что есть причина выдавать другое исключение (даже если вы больше не находитесь в веб-сервисе).

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

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

Просто убедитесь, что вы обрабатываете условие data == null таким образом, чтобы оно не разрушало ваш клиентский код.

4 голосов
/ 29 октября 2010

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

результат-> Код = "ОБСЛУЖИВАНИЕ" result-> MaintenanceTill = "2010-10-29 14:00:00"

так что для веб-сервиса, который должен получить мне список dataEntities, я верну что-то вроде:

<result>
    <result>
        <Code>OK</Code>
    </result>
    <functionalResult>
        <dataList>
            <dataEntity>A</dataEntity>
        </dataList>
    </functionalResult>
</result>

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

2 голосов
/ 29 октября 2010

Ваша первая проблема - «правило не возвращать ноль». Я настоятельно рекомендую пересмотреть это.

Возврат SoapException возможен, но, как уже упоминалось выше, было бы лучше возвращать сложный объект с флагом состояния {Success, Fail} при каждом ответе веб-службы.

2 голосов
/ 29 октября 2010

Я думаю, что при принятии решения могут учитываться несколько факторов:

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

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

Клиент:

try:
  # Restore Serialized object, rethrow if exception
  return CallGetSomeData(parameter);
except Timeout, e:
  MessageBox.Show("timed out")
except Exception, e:
  MessageBox.Show("Unknown error")
exit(1)

WebService:

try:
  return GetSomeData(parameter) # Serialized
except Exception, e:
  return e # Serialized
2 голосов
/ 19 октября 2010

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

1 голос
/ 26 октября 2010

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

1 голос
/ 26 октября 2010

Я думаю, что все сводится к вопросу, может ли ваш клиент использовать любую информацию о том, почему данные не были возвращены.
Например, если данные не были возвращены, потому что (скажем,sql) сервер, который вызывается в GetSomeData, не работает, и клиент может что-то сделать с этой информацией (например, отобразить соответствующее сообщение) - вы не хотите скрывать эту информацию - выдает ошибку, которая более информативна.
Другой пример - если parameter имеет значение NULL, и это вызывает исключение .. (хотя вы, вероятно, должны были позаботиться об этом ранее в коде ... Но вы поняли) - должно быть выбрасывать соответствующее (информативное) исключение,

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

0 голосов
/ 30 октября 2010
  • Поскольку вы являетесь клиентом веб-службы, вы можете зарегистрировать исключение на уровне службы и вернуть клиенту нулевое значение, однако клиент все равно должен знать, вернул ли CallGetSomeData нулевое значение, поскольку а) данные недоступны, или б) есть исключение базы данных, так как таблица заблокирована. Следовательно, всегда полезно знать, что вызвало ошибку, чтобы упростить отчетность на стороне клиента. Вы должны иметь код ошибки и описание как часть вашего сообщения.
  • Если вы не пользуетесь своим веб-сервисом, то вам обязательно следует выдать исключение по тем же причинам, указанным выше, клиент должен знать, что произошло, и он сам должен решить, что с этим делать.
0 голосов
/ 28 октября 2010

Исключения рекомендуются в том же пространстве процесса. Через процессы, только через информацию, оценивается успех / неудача.

0 голосов
/ 26 октября 2010

Как насчет передачи делегата для вызова, когда происходит что-то плохое? Делегат может сгенерировать исключение, если это то, что может захотеть внешний объект, или позволить функции вернуть значение null (если внешний код проверит это), или, возможно, предпринять какое-либо другое действие. В зависимости от информации, передаваемой делегату, он может быть в состоянии справиться с проблемными условиями таким образом, чтобы разрешить продолжение обработки (например, делегат может установить флаг 'retry' в первые несколько раз, когда он вызывается, в случае нестабильной сети соединения ожидаются). Делегат также может регистрировать информацию, которая не будет существовать к тому времени, когда может быть получено исключение.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...