520 votes

Pourquoi ne pas utiliser Java 8 facultatif dans les arguments?

J'ai lu sur de nombreux sites Web Optionnel doit être utilisé comme un type de retour et de ne pas les utilisés dans la méthode des arguments. J'ai du mal à trouver une raison logique. Par exemple, j'ai un morceau de la logique qui a 2 paramètres facultatifs. Donc je pense qu'il serait judicieux d'écrire ma signature de la méthode comme ceci (solution 1):

public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
    // my logic
}

De nombreuses pages web spécifier l'Option ne doit pas être utilisé comme méthode d'arguments. C'est dans cet esprit que je pouvais utiliser la méthode suivante signature et ajouter un clair Javadoc commentaire précisant les arguments peut-être nulle en espérant futurs responsables va lire la javadoc et, par conséquent, effectuer toujours null vérifications avant d'utiliser les arguments (solution 2):

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

Sinon je pourrais remplacer ma méthode avec 4 méthodes publiques de fournir une interface plus conviviale et plus évident p1 et p2 sont en option (solution 3):

public int calculateSomething() {
    calculateSomething(null, null);
}

public int calculateSomething(String p1) {
    calculateSomething(p1, null);
}

public int calculateSomething(BigDecimal p2) {
    calculateSomething(null, p2);
}

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

Maintenant, j'ai essayer d'écrire le code de la classe qui invoque cette pièce de la logique pour chaque approche. J'ai d'abord récupérer les 2 paramètres d'entrée à partir d'un autre objet qui renvoie options et puis je invoquer calculateSomething. Donc si la solution 1 est utilisé le code d'appel devrait ressembler à ceci:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);

si la solution 2 est utilisé le code d'appel devrait ressembler à ceci:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

si la solution 3 est utilisé, je pouvais utiliser le code ci-dessus ou que je pouvais utiliser la suite (mais ses une quantité importante plus de code):

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p1, p2);
    } else {
        result = myObject.calculateSomething(p1);
    }
} else {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p2);
    } else {
        result = myObject.calculateSomething();
    }
}

Donc ma question est pourquoi est-il considéré comme une mauvaise pratique pour utiliser les Options comme des arguments de méthode comme dans la solution 1? Il semble être le plus lisible solution pour moi et le rend plus évident que les paramètres pourraient être vide ou null pour les futurs responsables. (Je suis conscient que les concepteurs de Facultatif destiné à être utilisé uniquement comme un type de retour, mais je ne peux pas trouver toutes les raisons logiques de ne pas l'utiliser dans ce scénario)

270voto

Joop Eggen Points 30166

Oh, ceux de codage styles sont à prendre avec un peu de sel.

  1. (+) En passant une Option suite à une autre méthode, sans aucune analyse sémantique; laissant que de la méthode, est tout à fait bien.
  2. (-) À l'aide des paramètres Optionnels, causant la logique conditionnelle à l'intérieur de la méthodes est littéralement contre-productif.
  3. (-) Avoir besoin pour emballer un argument Optionnel, est sous-optimale pour le compilateur, et n'inutile d'emballage.
  4. (-) En comparaison à nullable paramètres en Option est plus coûteuse.

En général: en Option unifie les deux états, qui ont à être élucidé. Donc mieux adapté pour le résultat que l'entrée, de la complexité du flux de données.

111voto

Mark Perry Points 81

Il n'y a presque pas de bonnes raisons pour ne pas utiliser en Option dans les paramètres. Les arguments contre cette reposent sur des arguments d'autorité (voir Brian Goetz - son argument est que nous ne pouvons pas appliquer non null options) ou que les arguments Facultatifs peuvent être null (essentiellement le même argument). Bien sûr, toute référence en Java peuvent être nulles, nous devons encourager les règles appliquées par le compilateur, non-programmeurs de mémoire (ce qui est problématique et n'est pas à l'échelle).

Langages de programmation fonctionnelle encourager les paramètres Facultatifs. Une des meilleures façons de l'aide c'est d'avoir plusieurs paramètres facultatifs et à l'aide de liftM2 pour utiliser une fonction, en supposant que les paramètres ne sont pas vides et au retour d'une option (voir http://www.functionaljava.org/javadoc/4.4/functionaljava/fj/data/Option.html#liftM2-fj.F-). Java 8 a malheureusement mis en œuvre très limitée de la bibliothèque de l'appui en option.

Comme les programmeurs Java nous ne doit être utiliser la valeur null pour interagir avec d'anciennes bibliothèques.

12voto

llogiq Points 156

Ce conseil est une variante de l'être aussi explicite que possible sur les intrants et le plus précis possible concernant les sorties" règle du pouce.

Habituellement, si vous avez une méthode qui prend une plaine valeur non nulle, vous pouvez mapper sur l' Optional, de sorte que la plaine de la version est strictement plus spécifique concernant les entrées. Cependant , il ya un tas de raisons possibles pour lesquelles vous voulez avoir besoin d'un Optional argument néanmoins:

  • vous voulez que votre fonction pour être utilisé en conjonction avec une autre API renvoie un Optional
  • Votre fonction doit retourner quelque chose d'autre qu'un vide Optional si la valeur donnée est vide
  • Vous pensez que Optional est tellement génial que celui qui utilise votre API devrait être nécessaire pour apprendre à ce sujet ;-)

12voto

Makoto Points 23751

Le modèle avec Optional est pour l'une afin d'éviter de revenir null. Il est toujours parfaitement possible de passer en null pour une méthode.

Alors que ce ne sont pas vraiment encore fait, vous pouvez utiliser la JSR-308 style annotations pour indiquer si vous acceptez ou non null valeurs dans la fonction. Notez que vous devez avoir le droit de l'outillage pour identifier réellement, et qu'il faudrait fournir plus de statique, que d'un cadre d'exécution de la politique, mais il pourrait l'aider.

public int calculateSomething(@NotNull final String p1, @NotNull final String p2) {}

0voto

Kieran Points 84

Les options ne sont pas conçues à cette fin, comme l’a bien expliqué Brian Goetz .

Vous pouvez toujours utiliser @Nullable pour indiquer qu'un argument de méthode peut être null. L'utilisation d'une option ne vous permet pas vraiment d'écrire plus précisément votre logique de méthode.

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