【问题标题】:VAVR compose Try and ListVAVR 组合 Try and List
【发布时间】:2019-05-09 22:56:07
【问题描述】:

我正在尝试找出使用 VAVR 的 Try 的惯用方式。 我正在查看的用例必须执行以下步骤:
- 获取鞋子列表(调用可以抛出检查异常)
- 清洁每只鞋子(调用可能会引发检查异常)
- 恢复每只鞋(调用可以抛出一个检查异常)
- 返回清洁/修复的鞋子清单

这是我的示例玩具代码,其中 processRequest 方法购买了 n 双鞋,清洁并修复它们;打印错误(如果有):

// definitions
ShoeStore java.util.List<Shoe> buy(int numberOfPairs) throws OutOfStockException;
ShoeCleaningService Shoe clean(Shoe dirtyShoe) throws OutOfShoePolishException;
ShoeRestoreService Shoe restore(Shoe oldShoe) throws OutOfSparePartsException;

class EnterpriseShoeService {
    // constructor
    ...

    public List<Shoe> processRequest(int numberOfPairs) {
        Try<List<Shoe>> shoes = Try.of(() -> shoeStore.buy(numberOfPairs));
        Try<List<Try<Shoe>>> cleanedAndRestoredShoes = shoes.map(xs -> xs.stream().map(shoe ->
                Try.success(shoe)
                        .andThenTry(shoeCleaningService::clean)
                        .andThenTry(shoeRestoreService::restore))
                .collect(Collectors.toList()));

        List<Shoe> result = cleanedAndRestoredShoes
                .getOrElseGet(err -> {
                    System.out.println(err.getMessage());
                    return Collections.emptyList();
                })
                .stream()
                .map(shoeTry -> shoeTry.onFailure(err -> System.out.println(err.getMessage())))
                .filter(Try::isSuccess)
                .map(Try::get)
                .collect(Collectors.toList());

        return result;

    }
}

我的问题是:如何简化这个逻辑?有没有可以消除的方法调用?可读性可以提高吗?

【问题讨论】:

  • 我喜欢您提供一个玩具示例来突出您面临的问题,但是从代码中逆向工程仍然有点困难,您想要实现什么。除了发布您最终得到的代码之外,您还可以添加需求列表。也许一些要点指出您想查看在取鞋时是否有错误,如果在清洁/修复鞋子时出现错误怎么办,以及当出现错误时您希望如何汇总生成的鞋子列表一些鞋子有问题,但不是全部(短路?)。
  • 我相信您应该首先关注您希望为此解决方案拥有的界面。如果鞋子不够怎么办?是全有还是全无?您将您的问题标记为函数式编程 - 关于这一点,您至少应该将您的函数拆分为多个命名良好的函数。
  • 例如 -> 返回类型没有意义,因为您只过滤成功的请求,所以 List> 将只包含 List>。我们可以从返回类型中删除这个 Try 包装器。类型在 FP 中很重要 - 您的示例充满了编译错误。
  • 我已经拥有了多种功能:购买、清理、恢复。现在我想要实现的是以可读的方式编写它们。
  • 类似于:buy().flatMap(shoes -> shoes.stream).map(shoe -> clean(shoe)).map(shoe->restore(shoe)).collect(列表)。我的动机是编写一个可读的解决方案。在 Java 中,lambda 表达式和检查异常很难编写,所以我正在查看 Option(al)、Try、Either。

标签: java functional-programming vavr


【解决方案1】:

我不知道一切是否按预期工作,因为没有提及任何要求,但这应该让您了解分解的力量。

import io.vavr.collection.List;
import io.vavr.control.Try;


public class TryListComposition {

   ShoeStore store;

   ShoeCleaningService cleaningService;

   ShoeRestoreService restoreService;

   public java.util.List<Shoe> processRequest(int numberOfPairs) {
    return processShoesRequest(numberOfPairs).getOrElse(List.empty()).toJavaList();
   }

   public Try<List<Shoe>> processShoesRequest(int numberOfPairs) {
      return this.buy(numberOfPairs)
            .map(shoes -> shoes
                    .map(this::cleanAndRestore)
                    .flatMap(x -> x)
            );
   }

   public Try<Shoe> cleanAndRestore(Shoe shoe) {
      return clean(shoe).flatMap(this::restore);
   }


   Try<List<Shoe>> buy(int numberOfPairs) {
      return Try.of(() -> 
        List.ofAll(store.buy(numberOfPairs).stream());
   }

   Try<Shoe> clean(Shoe dirtyShoe) {
      return Try.of(() -> cleaningService.clean(dirtyShoe));
   }

   Try<Shoe> restore(Shoe oldShoe) {
      return Try.of(() -> restoreService.restore(oldShoe));
   }

}

class Shoe {

}

interface ShoeStore {
   java.util.List<Shoe> buy(int numberOfPairs) throws 
   OutOfStockException;
}

interface ShoeCleaningService {
   Shoe clean(Shoe dirtyShoe) throws OutOfShoePolishException;
}

interface ShoeRestoreService {
   Shoe restore(Shoe oldShoe) throws OutOfSparePartsException;
}

class OutOfStockException extends Exception {

}

class OutOfShoePolishException extends Exception {

}

class OutOfSparePartsException extends Exception {

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    相关资源
    最近更新 更多