java - 返回事物或导致调用范围/上下文返回的辅助方法

标签 java design-patterns java-8 exception option-type

我不知道如何分解这段代码。

  private CompletionStage<Response<String>> foo(RequestContext rc) {

    final Optional<String> campaignIdOpt = rc.request().parameter("campaignId").filter(s -> !s.isEmpty());
    final Optional<String> creativeIdOpt = rc.request().parameter("creativeId").filter(s -> !s.isEmpty());

    Optional<Uuid> campaignIdOptOfUuid = Optional.empty();
    if (campaignIdOpt.isPresent()) {
      try {
        campaignIdOptOfUuid = Optional.of(UuidUtils.fromString(campaignIdOpt.get()));
      } catch (IllegalArgumentException e) {
        LOG.error(String.format("Invalid campaignId: %s", campaignIdOpt.get()), e);
        return CompletableFuture.completedFuture(
            Response.forStatus(Status.BAD_REQUEST.withReasonPhrase("Invalid campaignId provided.")));
      }
    }

    Optional<Uuid> creativeIdOptOfUuid = Optional.empty();
    if (creativeIdOpt.isPresent()) {
      try {
        creativeIdOptOfUuid = Optional.of(UuidUtils.fromString(creativeIdOpt.get()));
      } catch (IllegalArgumentException e) {
        LOG.error(String.format("Invalid creativeId: %s", creativeIdOpt.get()), e);
        return CompletableFuture.completedFuture(
            Response.forStatus(Status.BAD_REQUEST.withReasonPhrase("Invalid creativeId provided.")));
      }
    }

    // Simplified, do something with Uuids.
    return bar(campaignIdOptOfUuid, creativeIdOptOfUuid);
  }

基本上,我们经常需要解析 Google protobuf Uuid s 从查询字符串传递到另一个将找到(或找不到)的服务。如果未设置参数或空字符串,我们需要传递一个空选项,因为这两种情况都意味着“不要按此参数进行过滤”。最后,如果字符串根本无法解析,那么我们希望立即返回错误 400(错误请求),而不是将无意义的参数传递给服务。

所以,从代码角度来说,我想要一个实用方法

  1. 需要 Optional<String> ,并且
  2. 返回 Optional<Uuid>如果存在,Optional.empty()否则,并且
  3. 如果抛出异常,return来自原始上下文的错误。

但显然,我不能“双返”。我应该使用什么模式来实现这一目标?我尝试为 Optional<Uuid> 创建一个封装器和一个 CompletionStage<Response<String>>但这很尴尬。有一些惯用的方法吗?

最佳答案

您可以使用循环。循环允许您平等地处理所有元素,从而消除代码重复,同时仍然允许立即返回:

private CompletionStage<Response<String>> foo(RequestContext rc) {
    String[] parameters = {"campaignId", "creativeId" };
    List<Optional<Uuid>> uuids = new ArrayList<>(parameters.length);
    for(String param: parameters) {
        Optional<String> o1 = rc.request().parameter(param).filter(s -> !s.isEmpty());
        Optional<Uuid> o2;
        try {
            o2 = o1.map(UuidUtils::fromString);
        } catch(IllegalArgumentException e) {
            LOG.error(String.format("Invalid %s: %s", param, o1.get()), e);
            return CompletableFuture.completedFuture(
                Response.forStatus(Status.BAD_REQUEST
                    .withReasonPhrase("Invalid "+param+ " provided.")));
        }
        uuids.add(o2);
    }
    // Simplified, do something with Uuids.
    return bar(uuids.get(0), uuids.get(1));
}

否则,您需要创建一个方法,返回一个包含两个替代结果的对象(例如 Either); JDK 还没有提供这样的类型。方法可以简单地抛出错误条件,但是当公共(public)代码主要是异常处理时,这会让您回到原点。

请注意,在空可选上调用 Optional.map 将返回一个空可选,而不评估提供的函数,因此您不需要通过 ifPresent 检查等

关于java - 返回事物或导致调用范围/上下文返回的辅助方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54463387/

相关文章:

java - 持久化 JPA 域对象的良好设计

java.net.SocketException : Unconnected sockets not implemented 异常

java - 如何在Java中获取类的TypeTag

javascript - Java 变量未在 Javascript 的 setinterval 内更新

java - 自动打开和关闭连接

javascript - 尝试在 React 中创建特殊的设计模式,不确定如何实现它

java - 在 java8 中使用 Stream groupingby 按字符串集合分组

java - 为什么 Files.list() 并行流的执行速度比使用 Collection.parallelStream() 慢得多?

Eclipse 配置 "Execution Environments"

java - 如何在 java 3d 中旋转相机/viewPlatform