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

时间:2012-01-13 23:30:31

标签: java generics exception inheritance exception-handling

首先是一些背景:

我已经实现了一个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的失败帮助功能与我正在做的相似)
  3. Result为状态提供静态工厂方法,构建其他关键字段的构建器方法是不可变的。以下是构建结果的结果:

    Result.success().withCode( ResultCode ).withMessage( "" );
    

    评估返回的结果:

    result.isSuccessful();
    result.hasCode( ResultCode );
    result.getMessage();
    

    我的问题:

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

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

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

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

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

1 个答案:

答案 0 :(得分:2)

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

public class Result extends ResultPair<Void> { ... }

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

<强>更新

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