web-dev-qa-db-fra.com

Meilleure pratique pour renvoyer plusieurs valeurs en Java?

Aujourd'hui, j'ai ajouté un contrôle de sécurité supplémentaire derrière mes formulaires de connexion, pour ralentir les attaques par force brute. J'ai plusieurs formulaires de connexion et j'ai créé une fonction Nice facile à appeler qui effectue toutes les vérifications et renvoie ensuite le résultat.

public static ValidateLoginResult validateLogin(HttpServletRequest request, String email, String password) {

Le problème est que le résultat n'est pas une valeur unique, le résultat se compose de:

boolean ok
String errorMessage
boolean displayCaptcha

Pour cela, j'ai créé une nouvelle classe. Tout fonctionne bien.

Mais j'ai souvent des fonctions utilitaires pratiques qui renvoient plusieurs valeurs et commencent à trouver un peu ennuyeux de créer une nouvelle classe pour le résultat à chaque fois.

Existe-t-il une meilleure façon de renvoyer plusieurs valeurs? Ou suis-je juste paresseux? :)

29
TinusSky

Non, ce type de structure n'existe pas nativement en Java, mais vous pouvez regarder bibliothèque JavaTuples qui peut répondre à vos besoins et fournir une solution assez élégante. Utilisant un Triplet<Boolean, String, Boolean>

16
gma

Je ne suis pas sûr de la "meilleure pratique" mais une option pragmatique est de renvoyer un Map<String, String>? Par exemple.

myMap.put("result", "success");
myMap.put("usernameConfirmed", "bigTom");

return myMap;

Mouche probablement face à un million de principes OO mais je vous entends vouloir éviter une prolifération des classes de résultats.

Vous pouvez également utiliser Map<String, Object> et soyez plus strict avec les contrôles de type sur les objets stockés: chaînes, booléens, dates, etc.

5
Brian

Vous pouvez définir un Pair<A, B> classe et un Triplet<A, B, C> class, et cela résoudrait le problème du retour des valeurs 2 et 3 tout en assurant la sécurité du type. Dans ce cas particulier, la signature pourrait être

public static boolean validateLogin(HttpServletRequest request,
            String email, String password, Pair<Message, Boolean> outputIfOk);

Ou encore mieux, dans un contexte de servlet, il peut être judicieux de définir certains attributs de demande bien documentés.

Si vous avez besoin de classes spéciales pour renvoyer des résultats très souvent, vous pouvez très probablement refactoriser ces classes pour partager un ancêtre commun (par exemple, avoir un RequestStatus qui inclut les champs "ok" et "message").

En dehors de cela, oui, vous êtes paresseux - les classes personnalisées seront toujours plus auto-documentées que les paires et les triplets.

5
tucuxi

Je ne peux pas vraiment penser à un moyen meilleur, plus propre et plus orienté objet de renvoyer plusieurs valeurs d'une fonction que de les encapsuler dans une classe.

Idéalement, les multiples valeurs que vous souhaitez renvoyer font conceptuellement partie de la même classe, il est donc logique de les regrouper de cette façon; si ce n'est pas le cas, vous devriez probablement décomposer votre fonction en quelques fonctions plus petites qui renvoient chacune des valeurs dont vous avez besoin en dehors de la fonction elle-même.

Pour autant que je sache, certains IDE ont également des fonctionnalités pour aider à encapsuler plusieurs valeurs dans une classe: par exemple, Eclipse a Refactor --> Extract class...

4
Raibaz

Vous pouvez renvoyer un tableau Object [], Java autoboxes donc son plus facile à utiliser. Si c'est juste pour un transfert à courte distance, pourquoi pas.

mais c'est facile à écrire et à utiliser.

là encore, une classe interne statique est rapidement créée et si vous la placez juste à côté de la méthode qui la renvoie, vous savez également où la trouver (généralement près de l'origine)

1
NikkyD

Je ferais probablement le chemin de la classe moi-même, mais selon ce que vous voulez que la fonction retourne, vous pourrez peut-être vous en sortir en retournant une sorte de conteneur de valeurs.

0
DannyMac92