Exception 方法设计决策;何时抛出异常?

Exception 方法设计决策;何时抛出异常?,exception,Exception,假设我有一个方法,该方法必须返回一个对象(比如从数据库层),并将有关请求对象的一些信息作为输入 在正常情况下,该方法应返回对象。但是如果调用方没有满足方法的前提条件,会发生什么;我(方法的代码编写者)应该如何通知调用方 例如,我应该从数据库返回关于用户的信息,并输入用户名和密码。在正常情况下,我应该返回User对象。但是如果用户名和密码为空,如果它们不匹配,如果密码太短怎么办。。。我应该如何告知打电话的人到底是什么问题? 通常我会抛出一个异常,但这里有人建议这是一个坏主意。 我应该在用户中放置一

假设我有一个方法,该方法必须返回一个对象(比如从数据库层),并将有关请求对象的一些信息作为输入

在正常情况下,该方法应返回对象。但是如果调用方没有满足方法的前提条件,会发生什么;我(方法的代码编写者)应该如何通知调用方

例如,我应该从数据库返回关于用户的信息,并输入用户名和密码。在正常情况下,我应该返回User对象。但是如果用户名和密码为空,如果它们不匹配,如果密码太短怎么办。。。我应该如何告知打电话的人到底是什么问题? 通常我会抛出一个异常,但这里有人建议这是一个坏主意。
我应该在用户中放置一个errorDetail字段,还是制作一个方法checkInputData或getErrorStatus

返回某种哨兵值有意义吗?如果是这样,考虑使用它。否则,为什么不抛出异常?

我将返回一个对象,该对象包含一个用户(出错时为null)、一个成功标志(出错时为false)和一个字符串列表作为验证消息(出错时为失败原因列表)


在用户对象上添加errorDetail字段没有意义,因为这实际上不是用户对象的属性。这只是该方法返回数据的一部分。此路径将导致对象具有仅由某些方法使用的muddles属性。

在这种情况下抛出异常听起来完全合理。该方法应该做一件事,而且只有一件事,它只是尝试从数据库中获取用户记录。如果先决条件失败,就放弃。如果数据库出错,请放弃。如果找不到用户,请放弃。让调用代码处理结果

异常是方法完全可以接受的退出路径

在前提条件的情况下,方法不负责修复它。这是呼叫代码的责任。因此,抛出某种类型的
ArgumentException
,让调用代码处理它

在数据库错误的情况下,捕获它并抛出自定义异常(类似于
InfrastructureFailed
异常),以便应用程序相应地处理。基本上,应用程序需要告诉用户存在技术困难,请稍后再试

如果找不到用户,这听起来像是登录失败。抛出某种类型的
SecurityException
,并让调用应用程序通过通知用户登录失败来处理它。(不要说得更具体。例如,不要告诉用户用户名很好,但密码不好。这会给恶意用户提供比您希望的更多的信息。只需说登录失败,就可以了。)

您还提到了密码太短的情况。我想这是在达到这一点之前应该验证的东西。在本例中,这属于方法的输入检查。因此,前提条件失败,该方法甚至从未尝试访问数据库。但是,在登录提示时告诉用户“密码太短”可能不是一个好错误。相反,这是为他们尝试创建密码时使用的

您不应该做的一件事是返回null或空用户对象或诸如此类的内容。这使得调用代码有责任检查是否存在错误。异常是通知调用代码错误的一种非常有效的方法。返回的“magic object”与代码中的任何其他“magic string”一样,但更糟糕的是,它从方法中泄漏到其他代码中

当然,这并不总是一条完整的规则。这取决于应用程序的结构。例如,如果这是一个web服务或某种其他类型的请求/响应系统,那么您可能需要一个标准的响应对象来指示失败。不过,这假设方法周围有一些应用程序上下文。在这种情况下,您可能仍然需要处理多种方法。内部方法(一个域逻辑方法)将抛出异常,外部方法(一个应用程序UX感知方法)将捕获异常并为UI创建一个适当的非空响应


如何处理异常取决于应用程序的逻辑结构。但是抛出和捕获异常(请记住,“捕获”与有意义的“处理”不是一回事)是完全可以接受的行为。

当异常(即意外)发生时,抛出异常(…鼓点…),例如,参数不符合方法的约定。在约定中不可能指定从数据库检索不存在的用户;还有什么方法可以将此信息返回给方法的调用方呢?那么您创建了一个包装类,将用户作为字段保存,以及其他有关最终错误的信息?假设您有一种强类型语言,并且不适合返回具有不同类型的元素数组。。。我将创建一个包装器类,该类将表示此方法返回的数据—用户对象、成功标志和消息字符串。你用什么语言工作?我从未使用过不支持这样的语言。与抛出异常相比,这种方法的一个优点是可以向用户返回多条消息。(即邮政编码无效,用户名已被占用)我在Java中工作;发送对象列表是合法的,但不适合。无论如何,拥有一个包装器会使事情复杂化,因为你不能使用polymorhism。关于更多信息,youn可以在自定义异常中放入任意数量的字段。返回sentinel值没有意义。抛出一个异常我会这么做