Exceções na expressão lambda usando o Vavr

Exceções na expressão lambda usando o Vavr

1. Introdução

OsFunctional Interfaces fornecidos pelo JDK não são preparados adequadamente para o tratamento de exceções verificadas. Se você quiser ler mais sobre o problema, verifiquethis article.

Neste artigo, veremos várias maneiras de superar esses problemas usando a biblioteca Java funcionalVavr.

Para obter mais informações sobre o Vavr e como configurá-lo, verifiquethis article.

2. UsandoCheckedFunction

O Vavr fornecefunctional Interfaces que possuem funções que lançam exceções verificadas. Essas funções sãoCheckedFunction0,CheckedFunction1 e assim por diante atéCheckedFunction8. O0, 1, … 8 no final do nome da função indica o número de argumentos de entrada para a função.

Vamos ver um exemplo:

static Integer readFromFile(Integer integer) throws IOException {
    // logic to read from file which throws IOException
}

Podemos usar o método acima dentro de uma expressão lambda sem manipularIOException:

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);

CheckedFunction1 readFunction = i -> readFromFile(i);
integers.stream()
 .map(readFunction.unchecked());

Como você pode ver, sem otry-catch padrão ou os métodos wrapper, ainda podemos chamar métodos de lançamento de exceção dentro de uma expressão lambda.

Devemos ter cuidado ao usar esse recurso com a APIStream, pois uma exceção encerraria imediatamente a operação - abandonando o resto do fluxo.

3. Usando métodos auxiliares

A classe API fornece um método de atalho para o exemplo na seção anterior:

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);

integers.stream()
  .map(API.unchecked(i -> readFromFile(i)));

4. Usando levantamento

Para lidar com umIOException normalmente, podemos introduzir blocostry-catch padrão dentro de uma expressão lambda. No entanto, a concisão de uma expressão lambda será perdida. O levantamento de Vavr vem em nosso resgate.

Levantar é um conceito da programação funcional. Você pode elevar uma função parcial para uma função total que retorna umOption como resultado.

Uma função parcial é uma função definida apenas para um subconjunto de um domínio, em oposição a uma função total definida para a totalidade do seu domínio. Se a função parcial for chamada com uma entrada que esteja fora do seu intervalo de suporte, ela normalmente emitirá uma exceção.

Vamos reescrever o exemplo da seção anterior:

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);

integers.stream()
  .map(CheckedFunction1.lift(i -> readFromFile(i)))
  .map(k -> k.getOrElse(-1));

Observe que o resultado da função levantada éOptione o resultado seráOption.None no caso de uma exceção. O métodogetOrElse() assume um valor alternativo para retornar no caso deOption.None.

5. UsandoTry

Embora o métodolift() na seção anterior resolva o problema do encerramento abrupto do programa, ele na verdade engole a exceção. Conseqüentemente, o consumidor do nosso método não tem idéia do que resultou no valor padrão. A alternativa é usar um contêinerTry.

Try é um contêiner especial com o qual podemos encerrar uma operação que pode possivelmente lançar uma exceção. Nesse caso, o objetoTry resultante representa umFailuree envolve a exceção.

Vejamos o código que usaTry:

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);
integers.stream()
  .map(CheckedFunction1.liftTry(i -> readFromFile(i)))
  .flatMap(Value::toJavaStream)
  .forEach(i -> processValidValue(i));

Para saber mais sobre o contêinerTry e como usá-lo, verifiquethis article.

6. Conclusão

Neste artigo rápido, mostramos como usar os recursos da biblioteca Vavr para contornar os problemas ao lidar com exceções nas expressões lambda.

Embora esses recursos nos permitam lidar com exceções de maneira elegante, eles devem ser usados ​​com o máximo cuidado. Com algumas dessas abordagens, os consumidores de seus métodos podem se surpreender com exceções verificadas inesperadas, embora elas não sejam explicitamente declaradas.

O código-fonte completo para todos os exemplos neste artigo pode ser encontradoover on Github.