Вспомогательный метод, который возвращает вещь или вызывает возврат в вызывающей области / контексте - PullRequest
0 голосов
/ 31 января 2019

Я не могу понять, как выделить этот код.

  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 Uuid s из строки запроса для передачи другому сервису, которыйнайдет (или не найдет).Нам нужно передать пустой необязательный параметр, если параметр не был задан, или пустую строку, поскольку оба случая означают «Не фильтровать по этому параметру».Наконец, если строка вообще не анализируется, мы хотим немедленно вернуть ошибку 400 (неверный запрос), а не передавать бессмысленный параметр в службу.

Итак, по кодам янужен вспомогательный метод, который

  1. принимает Optional<String>, а
  2. возвращает Optional<Uuid>, если присутствует, Optional.empty() в противном случае и
  3. , если исключениеreturn выдает ошибку из оригинального контекста.

Но, очевидно, я не могу "двойного возврата".Какой шаблон я использую для достижения этой цели, хотя?Я пытался создать инкапсулятор для Optional<Uuid> и CompletionStage<Response<String>>, но это было неудобно.Есть какой-то идиоматический способ сделать это?

1 Ответ

0 голосов
/ 31 января 2019

Вы можете использовать цикл.Цикл позволяет обрабатывать все элементы одинаково, тем самым устраняя дублирование кода, и в то же время позволяет сразу же возвращать:

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 пока не предоставляет такой тип.Метод может просто вызвать ошибочное условие, но это вернет вас к исходной точке, когда общий код в большинстве случаев является обработкой исключений.

Обратите внимание, что вызов Optional.map для пустого необязательного параметра уже вернет пустой необязательный параметр.без оценки предоставленной функции, поэтому вам не нужно проверять через ifPresent и т. д.

...