我遇到了代码,它返回了一个"解析结果列表"总是单个结果只有异常值或成功解析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;是否还有其他缺点?处理过程中的部分结果还在进行中? (在许多情况下,这对流/事件如处理和易于调试的堆栈跟踪有益)
答案 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)
但没有理由将你的班级锁定在任何一种模式上
注意,例如, Optional
和CompletableFuture
都提供了查询结果值(get()
resp,join()
)的方法,以及预先检查这些方法是否成功的方法({ {3}} resp。isPresent()
/ isDone()
)以及消费者变体(以及其他链接方法)。
因此,使用消费者是另一个机会,并不意味着取代现有的模式。
答案 1 :(得分:0)
在大多数情况下,由于KISS和YAGNI,第一种方法更好。 如果您正在处理有状态资源(例如InputStream)并希望强制执行资源安全,则第二种方法非常有用。
使用第一种方法,Input
的所有者在SingleResult
方法之外发布process
并且无法控制它。因此,在对大量输入进行流解析的情况下,很容易遇到内存问题。
使用第二种方法解析数据永远不会逃避process
方法,并且资源的所有者可以完全控制数据。因此,它可以打开和关闭输入并安全地应用消费者。
除非您想利用纯函数式编程的优势,否则请继续使用最简单的解决方案。但请注意,它在Java中通常很尴尬。