Est-ce une bonne idée d'utiliser Optional.orElseGet pour faire une logique d'exploitation forestière

lapkritinis:

Je veux utiliser en option pour le traitement des valeurs nulles, la partie « délicate » que je ne peux pas penser à ce qui est la meilleure façon de le faire - est que je veux faire l'exploitation forestière si la valeur est nulle. Je peux y arriver avec le code suivant - mais il se sent maladroit.

(Mise à jour: J'ai posté ma propre réponse, avec option de Java 9)

Disons que ressemble ce code:

// logLine.getSomeProperty returns Optional<String>

List<LogDetails> logDetails = logLine.getSomeProperty()
    .map(this::extractLogDetails)
    .orElseGet(() -> logError(logLine));
List<LogDetails> extractLogDetails(String s) {
    List<LogDetails> logDetails = new ArrayList<>();
    String sp = "(?:([A-Z0-9]{5,7})-([A-Z0-9]{9})-(.{4}))"; 
    Pattern p = Pattern.compile(sp, Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher(s);
    while (m.find()) {
        logDetails.add(new LogDetails(m.group(1), m.group(2), m.group(3)));
    }
    return logDetails;
}
List<LogDetails> logError(LogLine logLine) {
    log.error("Error while ... {} ", logLine));
    persistence.setErrorStatus(logLine, FAILED_PARSING);
    return new ArrayList<>();
}

Il ferait ce que je veux, mais j'ai plusieurs « problèmes » avec elle.

  • Je l' ai trouvé étrange, cette méthode appelée orElseGetest utilisée pour les erreurs de journalisation.
  • Je pourrais remplacer orElseGet avec orElseThrow et il logError et ne jetez rien - que je ne aime pas non plus.
  • méthode logError retourne la liste que je ne l'utilise et il fait un peu bizarre de retourner quelque chose de méthode qui devrait être vide.
  • Il suffit qu'il doit y avoir une meilleure façon
  • Les cas où someProperty n'est pas nulle, mais il n'y a aucun matchs - je voudrais vous connecter aussi bien, mais pour que je besoin d'une autre ligne de code pour vérifier si logDetails.size() == 0
JBX:

Le orElseGetest pas vraiment destiné comme un mécanisme de gestion des erreurs, mais comme un moyen de générer une valeur par défaut différente dans le cas où l' Optionalinstance ne porte pas tout.

Si vous voulez vérifier si le Optionalest vide explicitement, il suffit d' utiliser le Optional.isPresent()chèque, et faire le logError()dans ce cas.

Ce que vous devez penser d' abord, si le Optionalest vide, que voulez - vous faire? En plus de se connecter l'erreur, voulez - vous procéder à une liste vide?

Si oui, vous pourriez alors avoir quelque chose comme ceci:

List<LogDetails> logDetails = logLine.getSomeProperty()
    .map(this::extractLogDetails)
    .orElseGet(Collections::emptyList);

Après quoi, vous pourriez faire:

if (logDetails.isEmpty()) {
  logError(logline);
}

Sinon, si vous ne voulez pas avoir une liste vide du tout, vous pouvez garder les choses au niveau optionnel. De cette façon, les deux cas où le getSomeProperty()vide ou lorsque la liste générée est vide sont traités de la même manière.

Optional<List<LogDetails>> logDetailsOpt = logLine.getSomeProperty() 
                       .map(this::extractLogDetails)
                       .filter(list -> !list.isEmpty());

if (!logDetailsOpt.isPresent()) {
  logError(logLine);
}

Dans les deux cas, logError()ne devrait pas retourner quoi que ce soit. Il fait ce qu'il vise à faire en son nom, enregistrer l'erreur.

Plutôt que d' essayer de la fonctionnalité abuser de Optional, essayer de faire vos intentions dans votre code clair. Il y a plus de valeur dans la lisibilité.

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=236004&siteId=1
conseillé
Classement