指示服务器请求失败的最佳实践方法? [英] Best Practice way to indicate that a server request has failed?

查看:17
本文介绍了指示服务器请求失败的最佳实践方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个连接到服务的 API,该服务要么返回一条简单的成功"消息,要么返回 100 多种不同类型的失败之一.

I am writing an API that connects to a service which either returns a simple "Success" message or one of over 100 different flavors of failure.

本来我想写一个方法来向这个服务发送一个请求,这样如果它成功了,这个方法什么都不返回,但是如果它因为某种原因失败了,它就会抛出一个异常.

Originally I thought to write the method that sends a request to this service such that if it succeeded the method returns nothing, but if it fails for whatever reason, it throws an exception.

我不太在意这个设计,但另一方面,就在今天我正在阅读 Joshua Bloch 的如何设计一个好的 API 以及为什么它很重要",他说抛出异常以指示异常条件......不要强迫客户端使用异常来控制流."(和相反,不要默默地失败.")

I didn't mind this design very much, but on the other hand just today I was reading Joshua Bloch's "How to Design a Good API and Why it Matters", where he says "Throw Exceptions to indicate Exceptional Conditions...Don't force client to use exceptions for control flow." (and "Conversely, don't fail silently.")

另一方面,我注意到我使用的 HttpWebRequest 在请求失败时似乎抛出异常,而不是返回包含500 内部服务器错误"消息的响应.

On the other-other hand, I noticed that the HttpWebRequest I am using seems to throw an exception when the request fails, rather than returning a Response containing a "500 Internal Server Error" message.

在这种情况下报告错误的最佳模式是什么?如果我对每个失败的请求都抛出异常,我是否会在未来的某个时候遭受巨大的痛苦?

What is the best pattern for reporting errors in this case? If I throw an exception on every failed request, am I in for massive pain at some point in the future?

非常感谢您到目前为止的回复.一些阐述:

Thank you very kindly for the responses so far. Some elaboration:

  • 这是一个 DLL,将提供给客户在他们的应用程序中引用.
  • 一个类似的用法示例是 ChargeCreditCard(CreditCardInfo i) - 显然,当 ChargeCreditCard() 方法失败时,这是一个大问题;我只是不能 100% 确定我是否应该停止印刷或将责任转嫁给客户.
  • it's a DLL that will be given to the clients to reference in their application.
  • an analogous example of the usage would be ChargeCreditCard(CreditCardInfo i) - obviously when the ChargeCreditCard() method fails it's a huge deal; I'm just not 100% sure whether I should stop the presses or pass that responsibility on to the client.

编辑第二个:基本上我不完全相信使用这两种方法中的哪一种:

Edit the Second: Basically I'm not entirely convinced which of these two methods to use:

try { 
ChargeCreditCard(cardNumber, expDate, hugeAmountOMoney);
} catch(ChargeFailException e) {
  // client handles error depending on type of failure as specified by specific type of exception
}

var status = TryChargeCreditCard(cardNumber, expDate, hugeAmountOMoney);

if(!status.wasSuccessful) {
    // client handles error depending on type of failure as specified in status   
}

例如当用户尝试向信用卡收费时,信用卡被拒绝真的是例外情况吗?我一开始问这个问题是不是在兔子洞里走得太远了?

e.g. when a user tries to charge a credit card, is the card being declined really an exceptional circumstance? Am I going down too far in the rabbit hole by asking this question in the first place?

推荐答案

以下是需要考虑的事项的简短列表.虽然不全面,但我相信这些东西可以帮助您编写更好的代码.底线:不一定将异常处理视为邪恶.相反,在编写它们时,问问自己:我真正了解我正在解决的问题的程度如何?通常,这将帮助您成为更好的开发者.

Here's a short list of things to consider. While not comprehensive, I believe these things can help you write better code. Bottom line: Don't necessarily perceive exception handling as evil. Instead, when writing them, ask yourself: How well do I really understand the problem I am solving? More often than not, this will help you become a better developer.

  1. 其他开发者能否阅读此内容?普通开发者能否合理地理解?示例:ServiceConnectionException 与令人困惑的 ServiceDisconnectedConnectionStatusException
  2. 在抛出异常的情况下,情况如何异常?调用者必须做什么才能实现该方法?
  3. 这个异常是致命的吗?如果它被捕获,真的可以用这个异常做任何事情吗?线程中止,内存不足......你不能做任何有用的事情.不要抓住它.
  4. 异常是否令人困惑?假设您有一个名为 Car GetCarFromBigString(string desc) 的方法,它接受一个字符串并返回一个 Car 对象.如果该方法的主要用例是从该 string 生成一个 Car 对象,则不要在 Car 不能时抛出异常'不是由 string 决定的.相反,编写一个类似 bool TryGetCarFromBigString(string desc, out Car) 的方法.
  5. 这是否可以轻松避免?我可以检查一些东西吗,比如说数组或变量的大小为空?
  1. Will other developers be able to read this? Can it be reasonably understood by the average developer? Example: ServiceConnectionException vs. a confusing ServiceDisconnectedConnectionStatusException
  2. In the case of throwing an exception, how exceptional is the circumstance? What does the caller have to do in order to implement the method?
  3. Is this exception fatal? Can anything really be done with this exception if it is caught? Threads aborting, out of memory.. you can't do anything useful. Don't catch it.
  4. Is the exception confusing? Let's say you have a method called Car GetCarFromBigString(string desc) that takes a string and returns a Car object. If the majority use-case for that method is to generate a Car object from that string, don't throw an exception when a Car couldn't be determined from the string. Instead, write a method like bool TryGetCarFromBigString(string desc, out Car).
  5. Can this be easily prevented? Can I check something, let's say the size of an array or a variable being null?

为了代码可读性,让我们看一下您的上下文.

For code readability's sake, let's potentially take a look at your context.

bool IsServiceAlive()
{
   bool connected = false;  //bool is always initialized to false, but for readability in this context

   try
   {
      //Some check
      Service.Connect();
      connected = true;
   }
   catch (CouldNotConnectToSomeServiceException)
   {
      //Do what you need to do
   }

   return connected;
}

//or
void IsServiceAlive()
{
   try
   {
      //Some check
      Service.Connect();
   }
   catch (CouldNotConnectToSomeServiceException)
   {
      //Do what you need to do
      throw;
   }
}



static void Main(string[] args)
{
    //sample 1
    if (IsServiceAlive())
    {
       //do something
    }

    //sample 2
    try
    {
       if (IsServiceAlive())
       {
          //do something
       }
    }
    catch (CouldNotConnectToSomeServiceException)
    {
       //handle here
    }

    //sample 3
    try
    {
       IsServiceAlive();
       //work
    }
    catch (CouldNotConnectToSomeServiceException)
    {
       //handle here
    }
}

您可以在上面看到,如果上下文只是一个二进制测试,则捕获示例 3 中的 CouldNotConnectToSomeServiceException 不一定会产生更好的可读性.但是,两者都有效.但真的有必要吗?如果您无法连接,您的程序是否已停止运行?它到底有多重要?这些都是您需要考虑的因素.很难说,因为我们无法访问您的所有代码.

You can see above, that catching the CouldNotConnectToSomeServiceException in sample 3 doesn't necessarily yield any better readability if the context is simply a binary test. However, both work. But is it really necessary? Is your program hosed if you can't connect? How critical is it really? These are all factors you will need to take in to account. It's hard to tell since we don't have access to all of your code.

让我们来看看其他一些最有可能导致问题的选项.

Let's take a look at some other options that most likely lead to problems.

//how will the code look when you have to do 50 string comparisons?  Not pretty or scalable.
public class ServiceConnectionStatus
{
     public string Description { get; set; }
}

//how will your code look after adding 50 more of these?
public enum ServiceConnectionStatus
{
   Success,
   Failure,
   LightningStormAtDataCenter,
   UniverseExploded
}

这篇关于指示服务器请求失败的最佳实践方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆