Blocco try-catch fluente [chiuso]

Sep 23 2020

Ho molto di questo codice di tipo nella mia app:

String authUserId = null;

try {
  authUserId = webTokenService.readUserIdFromToken(app.getMasterKey(), authToken);
} catch (Exception e) {
  // do nothing
}

Con ogni frammento l'obiettivo è assegnare un valore se il metodo non ha generato, nullo in caso contrario. E sebbene il codice sopra funzioni, sembra certamente ridondante e non semplificato.

Quale libreria Java può rendere questo codice più fluido? Piace:

String authUserId = Try<String>.of(try -> {
   return webTokenService.readUserIdFromToken(app.getMasterKey(), authToken);
});

o qualcosa di più semplice.

AGGIORNARE:

Utilizzo della libreria Vavr

<dependency>
  <groupId>io.vavr</groupId>
  <artifactId>vavr</artifactId>
  <version>0.10.3</version>
</dependency>

Risolto con:

String authUserId = Try.of(() -> webTokenService.readUserIdFromToken(app.getMasterKey(), authToken)).get();

Risposte

1 flaxel Sep 23 2020 at 02:55

Se si ingoia completamente l'eccezione, questa non è davvero la migliore pratica . C'è un bell'articolo sull'eccezione di Baeldung:

Quanto sopra è chiamato deglutire un'eccezione. Il più delle volte, sarebbe un po 'meschino per noi farlo perché non risolve il problema e impedisce anche ad altro codice di essere in grado di risolvere il problema.

Ho trovato una libreria che implementa questo comportamento. Tuttavia, non è stato mantenuto per un po 'di tempo. Per questo motivo preferirei raccomandare Vavr . È ancora necessario gestire l'eccezione. Un ulteriore tutorial è disponibile anche da Baeldung . Nella documentazione c'è un piccolo esempio di divisione di due numeri:

int divide(int dividend, int divisor) {
    return dividend / divisor;
}

Try<Integer> divide(Integer dividend, Integer divisor) {
    return Try.of(() -> dividend / divisor);
}
2 rzwitserloot Sep 23 2020 at 03:22

Dato che ingoiare silenziosamente le eccezioni è stupido, nessuna.

È del tutto banale scrivere una cosa del genere da soli:

class ShootMyselfInLegToolkit {
    @FunctionalInterface
    public interface PermissiveSupplier<T> {
        T supply() throws Exception;
    }

    public <T> T ohMyLegs(PermissiveSupplier<T> supplier) {
        try {
            return supplier.supply();
        } catch (Exception itHurts) {
            return null; // dear lord.
        }
    }
}

Se vuoi davvero metterlo in una biblioteca, con tutti i mezzi.

Le librerie funzionali un po 'meno sciocche funzionano in questo modo: fornisci sia un fornitore (permissivo - jufSupplier di java non può farlo) che un gestore di eccezioni, quindi sembra:

Tool.tryGet(() -> Files.readAllLines(Paths.get("foo.txt")), ioex -> { code to handle the exception });

Non devi solo andare: Ehi, niente parentesi, quindi non premo mai Invio, e quindi questo è 'meno righe di codice' e quindi, 'più semplice', è ... beh, un modo molto strano di pensare che hai Là.

Che cosa significa, nelle tue parole, "fluente"? Riconosco il termine applicato ai metodi setter, getter e builder e significa: "Nessun prefisso get / set". Questo ovviamente non si applica qui, quindi pensi chiaramente che significhi qualcos'altro. Non è nelle specifiche java lang, quindi forse elaborato.

Non riesco a vedere come tutte queste cose siano più semplici da capire o più facili da programmare, a parte gli sciocchi combattimenti di stile. Penso che la maggior parte sarebbe d'accordo sul fatto che introdurre un sacco di librerie pazze SOLO perché trovi lo stile comunemente usato nella comunità java aberrante - questa è una brutta via d'uscita. Scrivere codice in modo non idiomatico è una cattiva idea, indipendentemente dal linguaggio e indipendentemente da quanto odi lo stile comune. Usa semplicemente una lingua diversa o modifica i tuoi gusti di stile. Più facile a dirsi che a farsi, forse, ma comunque - l'idea migliore, di gran lunga.