何时支持消费者<t>而不是仅仅返回T?

时间:2018-03-18 21:30:48

标签: java java-8 functional-programming java-stream consumer

我遇到了代码,它返回了一个&#34;解析结果列表&#34;总是单个结果只有异常值或成功解析T对象。

class SingleResult<T> {
    Optional<T> parseResult;
    Optional<Exception> parseException;
}

我重构了那个&#34;两个目的&#34; class分为表示成功或不成功导入结果的单独类,后面的处理器重构也返回SingleResult<T>以发布到两个Consumer

SingleResult<T> process(Input );

为:

void process(Input , Consumer<SuccessResult<T>> , Consumer<Exception> )

现在我想知道是否有一些干净的代码规则/标准,我们应该支持这样的Consumer而不仅仅返回结果?我们是否应该采用这种方法,即使对于单个严格类型返回alwyas什么时候可能?

我们是&#34;导出&#34;是否还有其他缺点?处理过程中的部分结果还在进行中? (在许多情况下,这对流/事件如处理和易于调试的堆栈跟踪有益)

2 个答案:

答案 0 :(得分:1)

如果您有一个直接的结果,您应该像Java开发人员在过去二十年中那样返回它。偏离既定模式应该有理由。

使用Consumer的原因要么是,没有一个结果值,要么没有立即结果值。

E.g。使用Optional.ifPresent(Consumer)Spliterator.tryAdvance(Consumer)您正在处理没有结果值的可能性,而使用Iterable.forEach(Consumer)Stream.forEach(Consumer)您可能会处理多个值。

使用CompletableFuture.thenAccept(Consumer)及其 async 变体时,您可能会在方法返回时仍无法使用该值,因此可能会在以后调用使用者。 / p>

在您的情况下,提供这样的方法可能是合理的,因为结果可能不存在,但提供类似

的方法可能更好。
void process(Input i, BiConsumer<? super SuccessResult<T>, ? super Exception> c)

CompletableFuture.whenComplete(BiConsumer<? super T,? super Throwable> action)

比较

但没有理由将你的班级锁定在任何一种模式上 注意,例如, OptionalCompletableFuture都提供了查询结果值(get() resp,join())的方法,以及预先检查这些方法是否成功的方法({ {3}} resp。isPresent() / isDone())以及消费者变体(以及其他链接方法)。

因此,使用消费者是另一个机会,并不意味着取代现有的模式。

答案 1 :(得分:0)

在大多数情况下,由于KISS和YAGNI,第一种方法更好。 如果您正在处理有状态资源(例如InputStream)并希望强制执行资源安全,则第二种方法非常有用。

使用第一种方法,Input的所有者在SingleResult方法之外发布process并且无法控制它。因此,在对大量输入进行流解析的情况下,很容易遇到内存问题。

使用第二种方法解析数据永远不会逃避process方法,并且资源的所有者可以完全控制数据。因此,它可以打开和关闭输入并安全地应用消费者。

除非您想利用纯函数式编程的优势,否则请继续使用最简单的解决方案。但请注意,它在Java中通常很尴尬。