插入方法应该返回对象还是抛出异常?

3

我正在设计一个API(第一次),它将是非常公开的(为免费在线服务)。

我在考虑使用诸如InsertResult这样的结构返回,其中包含了它失败或成功时的属性(例如有多少行),错误消息等等。现在,另一种方法是从API插入方法中仅抛出异常。我知道这有点“通用和开放”的问题,但是什么被认为是更清洁和优化的API呢?

场景

该API是一个DLL(它内部调用和消耗来自4或5个不同来源的Web服务,并根据诸如地理位置之类的事情决定要与哪个服务进行交互)。它是用C#和Mono构建的。使用情景包括桌面,移动和Web客户端作为库使用该API。这确实是个问题,假设是离线用例,从Web客户端不会发生,但从移动或桌面上,则会(从移动上更频繁),那么怎么办呢?如何处理说从移动应用中插入调用以存储模拟数据的情况当它处于离线状态时。或者是当发生其他(服务器相关)错误时。


API是做什么的?我通常把它看作是某人正在使用的服务(Web服务),如果失败则返回有用的信息。如果您正在设计框架,应该抛出异常,因为开发人员可能希望以不同的方式处理它。 - Justin
@Justin,该API公开了我们的WebServices以管理文档(类似于另一个iCloud或Dropbox,但用于存储UI草图)。 - Erre Efe
@RandolfR-F,你能为我们澄清一下“API”的含义吗?你是在制作一个将被使用的框架(dll),还是一组Web服务? - Justin
1
@Justin,该API是一个DLL(它内部调用和消耗来自4或5个不同来源的Web服务,并根据地理位置等因素决定与哪个服务进行交互)。 - Erre Efe
1
@RandolfR-F 我已经更新了我的回答,但是你的API是一个框架,普通客户不会使用它,而是开发人员。 - Justin
显示剩余6条评论
5个回答

2
一般来说,如果用户试图执行无效操作,则应抛出异常。但是,在发生异常之前,您还应提供一条代码路径,使用户能够合理地检查可能引发异常的条件。如果重要(可能是出于性能原因),您可能希望包括一个TryInsert方法,该方法安全处理无效插入并简单返回一个bool值以指示成功。 这适用于纯C# API以及服务API。

我甚至没有考虑过TryInsert,它看起来是一种安全路径的自然方式;但是,为同一件事提供两个选项只会让决策变得更混乱吗? - Erre Efe
@RandolfR-F 考虑使用包装类来封装请求/响应参数。您可以指定 ThrowOnError 或类似的可选参数,仍然只需进行一次服务调用。 - p.s.w.g

2
在C#/.NET中,抛出异常是处理错误和意外情况的更自然方式。此外,.NET还提供了定义自己的异常或使用已存在异常的可能性。
通过提供像finally{}块这样的内容,当出现问题时可以创建非常平稳的过程。
检查返回值容易出错,如果用户没有正确响应您的返回值,则可能使过程不稳定。未处理的异常通常会停止进程,迫使用户在后台进行检查。尽管如此,这是我的观点。

MSDN上,他们说,如果参数错误且无法继续使用错误输入,则很有理由抛出异常。


你的回答是准确的,但我不确定它是否与所提出的问题相关。这个问题是关于如何向Web服务的使用者正确传达失败信息。 - Cᴏʀʏ
有时候我也会成功的^^ - bash.d
@Cory 当异常发生时,服务主机(例如WCF)应该负责将异常合理地转换为客户端可以消费的形式。 - p.s.w.g
1
@Cory 这两者有什么区别?只有当消费者知道错误消息是什么时,它才能正确处理错误。问题是如何最有效地使服务支持这一点。 - p.s.w.g
@p.s.w.g 这正是问题所在。 - Erre Efe
显示剩余4条评论

2
由于问题是“通用和开放的”,我认为如果我们考虑像谷歌、亚马逊这样最常用的网络服务,它们都遵循尽可能详细地提供细节的原则,以便使用者知道他们做错了什么。如果你只是抛出异常,那么你的 API 的用户可能会更加麻烦。
因此,总结起来,定义良好的错误代码并将相同的信息传递给客户端/使用者始终是一个好主意,这样他们可以轻松地找出调用出了什么问题或应该如何纠正它。例如,如果由于某种原因你的 API 只接受特定的编码,那么用户会感到沮丧。

2

我建议返回详细的错误信息。由于你正在使用web服务进行消费,不是每个人都会使用相同的技术与之交互。如果你是在制作框架,那么我会建议使用异常,因为开发人员将使用相同的技术来消费它。这就是异常在框架级别上更有用的地方。

更新(涉及的API实际上是一个框架):既然现在谈论的是使用框架,你应该抛出异常,因为客户端必须引用DLL并且将知道可能的框架异常。为了使用库,必须是CLR兼容语言,因此他们应该具备相同的概念、类、异常等。


0

对于 API 来说,异常总是更好的选择。API 消费者可以使用 catch 块来处理各种异常。如果您使用错误消息和错误代码,则要求 API 消费者编写 If 语句。下面的代码片段始终比需要检查错误的 If 条件更清晰。

因此,从 API 消费者的角度来看,API 抛出异常总是更加清晰。

try
{
    yourAPIClass.YourMethod();
}
catch(YourException1 ex)
{
   action1();

}
catch(YourException2 ex)
{
   action1();

}

这是一个关于编写和抛出异常的好指南http://blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接