92 votes

Quel est l'intérêt de la classe facultative de Guava ?

J'ai récemment lu des articles à ce sujet et vu des personnes utiliser cette classe, mais dans la plupart des cas, l'utilisation de la classe null aurait aussi bien fonctionné, si ce n'est plus intuitivement. Quelqu'un peut-il fournir un exemple concret où Optional réaliserait quelque chose qui null ne pourrait pas ou d'une manière beaucoup plus propre ? La seule chose à laquelle je pense est de l'utiliser avec Maps qui n'acceptent pas null mais même cela pourrait être fait avec un "mappage" latéral de la valeur de null. Quelqu'un peut-il me fournir un argument plus convaincant ? Merci.

157voto

Louis Wasserman Points 67557

Membre de l'équipe Guava ici.

L'inconvénient le plus important de null est qu'il n'est pas évident de savoir ce qu'il doit signifier dans un contexte donné : il n'a pas de nom illustratif. Il n'est pas toujours évident que null signifie "pas de valeur pour ce paramètre" -- ou encore, en tant que valeur de retour, cela signifie parfois "erreur", ou même "succès" ( !!), ou simplement "la réponse correcte est rien". Optional est souvent le concept que vous entendez réellement lorsque vous rendez une variable nullable, mais pas toujours. Lorsque ce n'est pas le cas, nous vous recommandons d'écrire votre propre classe, similaire à la classe Optional mais avec un système de dénomination différent, afin de clarifier ce que vous voulez vraiment dire.

Mais je dirais que le plus grand avantage de Optional n'est pas dans la lisibilité : l'avantage est qu'il est à l'abri des erreurs. Il vous oblige à penser activement au cas absent si vous voulez que votre programme compile, puisque vous devez déballer activement le code de l'option Optional et traiter ce cas. Avec Null, il est extrêmement facile d'oublier des choses, et bien que FindBugs soit utile, je ne pense pas qu'il aborde le problème aussi bien. Ceci est particulièrement pertinent lorsque vous retournez des valeurs qui peuvent ou non être "présentes". Vous (et d'autres) êtes beaucoup plus susceptibles d'oublier que other.method(a, b) pourrait retourner un null que vous risquez d'oublier que a pourrait être null lorsque vous mettez en œuvre other.method . Retourner à Optional rend impossible pour les appelants d'oublier ce cas, puisqu'ils doivent déballer l'objet eux-mêmes.

Pour ces raisons, nous vous recommandons d'utiliser Optional comme type de retour pour vos méthodes, mais pas nécessairement dans vos arguments de méthode.

(Ceci est d'ailleurs totalement tiré de la discussion ici .)

9voto

Sebastien Lorber Points 9682

On dirait vraiment que le Maybe Modèle de monade de Haskell.

Vous devriez lire ce qui suit, Wikipedia Monade (programmation fonctionnelle) :

Et lire De l'option à la monade avec Guava sur Le blog de Kerflyn, qui traite de l'option de la goyave utilisée comme monade :


Edit : Avec Java8, il y a un Facultatif intégré qui a des opérateurs monadiques comme flatMap . Ce sujet a été controversé, mais il a finalement été mis en œuvre.

Voir http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html

public Optional<String> tryFindSimilar(String s)  //...

Optional<Optional<String>> bad = opt.map(this::tryFindSimilar);
Optional<String> similar =       opt.flatMap(this::tryFindSimilar);

Le site flatMap est essentiel pour permettre les opérations monadiques, et permet d'enchaîner facilement des appels qui renvoient tous des résultats optionnels.

Pensez-y, si vous avez utilisé le map opérateur 5 fois, vous vous retrouveriez avec un Optional<Optional<Optional<Optional<Optional<String>>>>> tout en utilisant flatMap vous donnerait Optional<String>

Depuis Java8, je préfère ne pas utiliser l'option de Guava qui est moins puissante.

6voto

j2emanue Points 3456

L'une des bonnes raisons de l'utiliser est qu'elle rend les nullités très significatives. Au lieu de renvoyer un null qui pourrait signifier beaucoup de choses (comme une erreur, un échec, un vide, etc.), vous pouvez donner un "nom" à votre null. Regardez cet exemple :

définissons un POJO de base :

class PersonDetails {

String person;
String comments;

public PersonDetails(String person, String comments) {
    this.person = person;
    this.comments = comments;
}

public String getPerson() {
    return person;
}

public String getComments() {
    return comments;
}

}

Utilisons maintenant cette simple POJO :

public Optional<PersonDetails> getPersonDetailstWithOptional () {

  PersonDetails details = null; /*details of the person are empty but to the caller this is meaningless,
  lets make the return value more meaningful*/

    if (details == null) {
      //return an absent here, caller can check for absent to signify details are not present
        return Optional.absent();
    } else {
      //else return the details wrapped in a guava 'optional'
        return Optional.of(details);   
    }
}

Maintenant, évitons d'utiliser null et faisons nos vérifications avec Optional pour que ce soit significatif.

public void checkUsingOptional () {

    Optional<PersonDetails> details = getPersonDetailstWithOptional();

    /*below condition checks if persons details are present (notice we dont check if person details are null,
    we use something more meaningful. Guava optional forces this with the implementation)*/
    if (details.isPresent()) {

      PersonDetails details = details.get();

        // proceed with further processing
        logger.info(details);

    } else {
        // do nothing
        logger.info("object was null"); 
    }

    assertFalse(details.isPresent());
}

Ainsi, en fin de compte, il s'agit d'un moyen de rendre les valeurs nulles significatives et de réduire l'ambiguïté.

5voto

raisercostin Points 1489

L'avantage le plus important de l'option est qu'elle ajoute plus de détails au contrat entre l'implémenteur et l'appelant d'une fonction. Pour cette raison, il est utile à la fois pour les paramètres et le type de retour.

Si vous faites la convention de toujours avoir Optional pour d'éventuels objets nuls, vous apportez des clarifications supplémentaires à des cas comme celui-ci :

  1. Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)

    Le contrat spécifie clairement qu'il y a une chance qu'un résultat ne soit pas retourné, mais montre également qu'il fonctionnera avec from et to comme absent.

  2. Optional<Integer> maxPrime(Optional<Integer> from, Integer to)

    Le contrat précise que l'adhésion est facultative. absent peut avoir une signification particulière, comme commencer à partir de 2. Je peux m'attendre à ce qu'une valeur nulle pour la valeur to entraînera une exception.

L'avantage de l'utilisation de l'option est que le contrat devient à la fois descriptif (similaire à l'option @NotNull ) mais aussi formelle puisque vous devez écrire du code .get() pour faire face à Optional .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X