style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Vavr Try.of

En el post anterior revisamos de forma rapida como hacer tipos que combinen monads para hacer cosas interesantes, como el evitar errores por posibles nulos, en los comentarios de @ezamudio nos podemos dar cuenta que Java ya implementa eso del fromNullable con Optional, pero deja de lado las excepciones y pues intente extender los tipos Right y Left para manejar y encadenar Excepciones.

Pero me encontré una librería, la cual es mejor estudiar en lugar de tratar de crear nuestros tipos una y otra vez, esta librería es vavr, tiene cosas muy interesantes entre ellas, manejo de excepciones de una forma funcional, precisamente lo que estaba tratando de hacer.

Vamos a ver como “esquivar” las excepciones con ayuda de programación funcional.

Supongamos que tenemos un archivo /opt/config.json que contiene la configuración del puerto tcp de nuestra app:

{
  "port": 8080
}

Entonces nuestra aplicación necesita leer el archivo, parsearlo y obtener el valor del puerto; usando la librería json-simple, el código quedaría algo así:

Integer defaultPort = 8000;
Integer port;
try {
    JSONObject config = (JSONObject) new JSONParser().parse(new FileReader("/opt/config.json"));
    port = (Integer) config.get("port");
} catch (FileNotFoundException e) {
    e.printStackTrace();
    port = defaultPort;
} catch (ParseException e) {
    e.printStackTrace();
    port = defaultPort;
}
System.out.println(port);

La salida de esto es 8080 si el archivo se encuentra y el JSON esta formado correctamente, en caso contrario imprime 8000, nada del otro mundo ha funcionado así desde hace como 10 años, pero… y si no me interesa manejar las excepciones o no me gusta ese código o ya no quiero escribir código estilo JSE 7, pues tenemos la alternativa, usando vavr el código anterior queda así:

Integer defaultPort = 8000;
Integer port = Try.of(() -> (JSONObject) new JSONParser().parse(new FileReader("/opt/config.json")))
        .map(j -> (Integer) j.get("port"))
        .getOrElse(defaultPort);
System.out.println(port);

Simplemente usamos el tipo Try.of mandamos la función que podría lanzar excepciones y como es un monad, podemos hacer map sobre map sobre map las veces que queramos (esta vez solo una), verifica que funciona, cambiando el nombre del archivo o haciendo el contenido un Json invalido.

Algunos diran, si me gusto el código… pero yo quiero manejar las excepciones, Try.of también te permite manejar las excepciones:

Integer defaultPort = 8000;

Function<Exception, Integer> handleException = t -> {
    t.printStackTrace();
    return defaultPort;
};

Integer port = Try.of(() -> (JSONObject) new JSONParser().parse(new FileReader("/opt/config.json")))
        .map(j -> (Integer) j.get("port"))
        .recover(x -> Match(x).of(
                Case($(instanceOf(FileNotFoundException.class)), handleException),
                Case($(instanceOf(ParseException.class)), handleException)
        )).get();
System.out.println(port);

Hay código duplicado, pero solo es para mostrar que podríamos usar una función para FileNotFoundException y otra función para ParseException, aunque aquí use el mismo handler.

Esta librería me gusto mucho porque no solo tiene Option, Try.of, Either (Result en Rust); sino que también tiene Tuples, Composición, aplicación parcial y currying entre otras monerías. Ya podré decir que ya no escribiré código en JSE 7, que hay que decir también, a muchos les gusta por no mencionar la estabilidad que tiene, lo repito: el primer bloque de código de este post no ha cambiado en casi diez años, y tanto un experto en Java como un recién iniciado pueden entenderlo sin mayores problemas.

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">