我为我的应用程序不期望的每个条件创建了异常。UserNameNotValidException, PasswordNotCorrectException等。
然而,我被告知我不应该为这些条件创造例外。在我的UML中,那些是主要流程的异常,那么为什么它不应该是异常呢?
是否有创建异常的指导或最佳实践?
我为我的应用程序不期望的每个条件创建了异常。UserNameNotValidException, PasswordNotCorrectException等。
然而,我被告知我不应该为这些条件创造例外。在我的UML中,那些是主要流程的异常,那么为什么它不应该是异常呢?
是否有创建异常的指导或最佳实践?
当前回答
以下是我的建议:
我不认为这总是一个抛出异常的好方法,因为它将花费更多的时间和内存来处理这样的异常。
在我看来,如果某些事情可以用“友好、礼貌”的方式处理(这意味着如果我们可以“通过使用if......或类似的东西来预测这样的错误),我们应该避免使用“异常”,而只是返回一个像“false”这样的标志,用一个外部参数值告诉他/她详细的原因。
举个例子,我们可以这样创建一个类:
public class ValueReturnWithInfo<T>
{
public T Value{get;private set;}
public string errorMsg{get;private set;}
public ValueReturnWithInfo(T value,string errmsg)
{
Value = value;
errMsg = errmsg;
}
}
我们可以使用这种“多值返回”类来代替错误,这似乎是处理异常问题的一种更好、更礼貌的方式。
但是,请注意,如果一些错误不能如此容易地用"if"......(例如FileIO异常)描述(这取决于您的编程经验),则必须抛出异常。
其他回答
我想说的是,如果发生了意想不到的行为,应该抛出异常。
比如试图更新或删除一个不存在的实体。它应该在异常可以处理并且有意义的地方被捕获。如果要以另一种方式继续工作,请在Api级别上添加日志记录或返回特定的结果。
如果您期望某些事情是这样的,那么您应该构建代码来检查并确保它是正确的。
for me Exception should be thrown when a required technical or business rule fails. for instance if a car entity is associated with array of 4 tires ... if one tire or more are null ... an exception should be Fired "NotEnoughTiresException" , cuz it can be caught at different level of the system and have a significant meaning through logging. besides if we just try to flow control the null and prevent the instanciation of the car . we might never never find the source of the problem , cuz the tire isn't supposed to be null in the first place .
一个经验法则是在您通常无法预测的情况下使用异常。例如数据库连接、磁盘上丢失的文件等。对于您可以预测的场景,例如用户试图使用错误的密码登录,您应该使用返回布尔值的函数,并知道如何优雅地处理这种情况。您不希望仅仅因为有人输入了密码错误而抛出异常,从而突然结束执行。
我同意japollock的说法当你不确定手术的结果时就放弃接受。调用api、访问文件系统、数据库调用等。任何时候你都要超越编程语言的“界限”。
我想补充一点,请随意抛出一个标准异常。除非你打算做一些“不同”的事情(忽略,电子邮件,日志,显示twitter鲸鱼图片之类的东西),否则不要费心自定义异常。
我认为只有在无法摆脱当前状态时才应该抛出异常。例如,如果您正在分配内存,但没有任何内存可以分配。在您提到的情况下,您可以清楚地从这些状态中恢复,并相应地将错误代码返回给调用者。
You will see plenty of advice, including in answers to this question, that you should throw exceptions only in "exceptional" circumstances. That seems superficially reasonable, but is flawed advice, because it replaces one question ("when should I throw an exception") with another subjective question ("what is exceptional"). Instead, follow the advice of Herb Sutter (for C++, available in the Dr Dobbs article When and How to Use Exceptions, and also in his book with Andrei Alexandrescu, C++ Coding Standards): throw an exception if, and only if
没有满足先决条件(通常会出现以下情况之一 不可能的)或 替代方案将无法满足后置条件或 替代方案将无法保持不变式。
为什么这样更好呢?它不是用几个关于前置条件,后置条件和不变量的问题代替了这个问题吗?这是更好的几个相关的原因。
Preconditions, postconditions and invariants are design characteristics of our program (its internal API), whereas the decision to throw is an implementation detail. It forces us to bear in mind that we must consider the design and its implementation separately, and our job while implementing a method is to produce something that satisfies the design constraints. It forces us to think in terms of preconditions, postconditions and invariants, which are the only assumptions that callers of our method should make, and are expressed precisely, enabling loose coupling between the components of our program. That loose coupling then allows us to refactor the implementation, if necessary. The post-conditions and invariants are testable; it results in code that can be easily unit tested, because the post-conditions are predicates our unit-test code can check (assert). Thinking in terms of post-conditions naturally produces a design that has success as a post-condition, which is the natural style for using exceptions. The normal ("happy") execution path of your program is laid out linearly, with all the error handling code moved to the catch clauses.