如何在不使用异常的情况下从方法返回失败详细信息,并可选择包含值?

Dan*_*mas 7 java generics inheritance exception-handling exception

首先是一些背景:

我已经实现了一个Result类来携带结果信息.它们是专门针对故障实施的,成功结果通常不会提供额外信息.我在我的一个项目中的核心API外部的公共方法中使用它们,或者在一两层深的方法中使用它们,我需要将详细信息备份到公共API.这个API在容器和命令行客户端中使用,并且之前已经非常快速地检查了异常.另一种方法是将这种失败上下文信息添加到异常中,并添加几个不同的异常类,它们不属于它们.我想这反映了我的一般做法:

http://blogs.atlassian.com/2011/05/exceptions_are_bad

结果有一个支持枚举和界面:

  1. ResultStatus:SUCCESS,FAILURE,CONDITIONAL_SUCCESS等.保存int返回码和通用消息(例如"操作成功")
  2. ResultCode:用于标记枚举结果代码的空接口,FILE_NOT_FOUND,FILE_INVALID,FILE_INCOMPATIBLE.这些主要用于单元和功能测试,但也用于在线帮助(Maven在故障方面的帮助在功能上类似于我正在做的事情)

Result为状态提供静态工厂方法,构建其他关键字段的构建器方法是不可变的.这是构建结果的样子:

Result.success().withCode( ResultCode ).withMessage( "" );
Run Code Online (Sandbox Code Playgroud)

并评估返回的结果:

result.isSuccessful();
result.hasCode( ResultCode );
result.getMessage();
Run Code Online (Sandbox Code Playgroud)

我的问题:

这种方法非常成功,特别是使功能测试变得轻而易举,但是我有一个主要的差距:在大多数情况下我只关心结果,在一些关键区域我需要返回一个带有结果的值.

我对第一次尝试感到不满意:ResultPair<T>它包含结果和值,其中T是值的类型.除非我复制所有Result方法,否则使用该类是冗长且笨拙的:获取结果,将其添加到ResultPair,并在评估之前捕获结果和值.乍一看,由于构建器模式,继承将无法工作,我无法想到一种方法可以获得结果允许的清晰,干净的代码,而无需完全复制Result类.

理想情况下,该方法将允许Result可选地返回一个值,但我无法想到以类型安全的方式执行它的方法,以确保方法签名清楚地指示值的类型,但避免在任何地方都有无意义的通用参数我没有返回值.

我真的不介意有两个类,复制结果构建器和评估代码不是世界末日,它只是感觉不对,我觉得缺乏经验让我变得更好,我错过了(明显或不那么明显)解决方案.我正在使用Guava并且我想以友好的方式禁止空值,因此可能另外将所有值包装在Optional中,但我仍然需要泛型参数(并将其组合到类中以避免result.value( ).get()......好的,我现在正在大声思考.我应该问一个问题......).

有没有办法满足这些明显相互排斥的要求?

Jor*_*dão 2

您可以创建ResultPair<T>作为void结果类的基类:

public class Result extends ResultPair<Void> { ... }
Run Code Online (Sandbox Code Playgroud)

所有相关方法都将在 中声明ResultPair<T>

更新

更好的是,只有一种类型Result<T>,并Result<Void>在您不想有返回值时使用。或者更确切地说,如果用作Void类型参数对您来说看起来很奇怪,请创建一个新的不可实例化(或单例)类型,这意味着“没有结果”,然后使用它:例如Result<Unit>