J'ai utilisé Spring Boot pour développer un projet shell utilisé pour envoyer des e-mails, par exemple
sendmail -from foo@bar.com -password foobar -subject "hello world" -to aaa@bbb.com
Si les arguments from
et password
manquent, j'utilise un expéditeur et un mot de passe par défaut, par exemple [email protected]
et 123456
.
Donc, si l'utilisateur transmet l' from
argument, il doit également passer l' password
argument et vice versa. Autrement dit, soit les deux sont non nuls, soit les deux sont nuls.
Comment puis-je vérifier cela avec élégance?
Maintenant ma voie est
if ((from != null && password == null) || (from == null && password != null)) {
throw new RuntimeException("from and password either both exist or both not exist");
}
From
adresse e-mail n'est pas toujours le nom d'authentification SMTP.Réponses:
Il existe un moyen d'utiliser l' opérateur
^
( XOR ):La
if
condition sera vraie si une seule variable est nulle.Mais je pense qu'en général, il est préférable d'utiliser deux
if
conditions avec des messages d'exception différents. Vous ne pouvez pas définir ce qui a mal tourné en utilisant une seule condition.Il est plus lisible et beaucoup plus facile à comprendre, et il suffit d'un peu de frappe supplémentaire.
la source
!=
deux bools?!=
. L'esprit soufflé. Et c'est un nombre très élevé de votes positifs dans le commentaire. Et, pour ajouter de la qualité à ce commentaire, oui, je pense également qu'il est préférable de donner un message d'erreur différent pour différents cas d'erreur, car l'utilisateur saura mieux comment corriger l'erreur.if
clauses - le message dans l'exception le documente bien (j'ai édité la question, mais elle n'apparaîtra pas avant d'être acceptée)Eh bien, il semble que vous essayez de vérifier si la condition de «nullité» des deux est la même ou non. Vous pouvez utiliser:
Ou rendez-le plus explicite avec des variables d'assistance:
la source
^
fait. :-)^
dit "Hé, mes opérandes sont des booléens" d'une manière qui!=
ne le fait pas. (Bien que cet effet soit malheureusement diminué par la nécessité de vérifier "mes opérandes pourraient être numériques, et je ne serais peut-être pas un opérateur relationnel à ce stade", ce que j'accorde est un inconvénient). Votre statut de héros intact, malgré votre désaccord avec moi :-)from
etpassword
doivent être tous les deux nuls ou tous deux non nuls". C'est peut-être juste moi et mon inexpérience, mais je préfère la solution la plus lisible comme dans la réponse de @ stig-hemmer, même si cela coûte encore 3 lignes de code. Je suppose que je ne comprends tout simplement pas immédiatementbool != bool
- ce n'est pas intuitif.^
opérateur est un opérateur au niveau du bit; cela n'implique en fait pas que ses opérandes sont booléens. L'opérateur booléen xor estxor
.Personnellement, je préfère le lisible à l'élégant.
la source
IllegalArgumentException
au lieu d'un nuRuntimeException
)Mettez cette fonctionnalité dans une méthode à 2 arguments avec la signature:
Cela économise de l'espace dans la méthode qui vous intéresse et la rend plus lisible. Il n'y a rien de mal avec les noms de méthode légèrement verbeux et il n'y a rien de mal avec les méthodes très courtes.
la source
((from == null) != (password == null))
c'est très simple à comprendre aussi. Il y a quelque chose qui ne va pas avec les méthodes inutiles.Une solution Java 8 serait à utiliser
Objects.isNull(Object)
, en supposant une importation statique:Pour Java <8 (ou si vous n'aimez pas utiliser
Objects.isNull()
), vous pouvez facilement écrire votre propreisNull()
méthode.la source
from == null != password == null
garde tout sur le même cadre de la pile, mais en utilisantObjects.isNull(Object)
inutilement pousse et fait éclater deux cadres. Objects.isNull (Object) est là parce que 'Cette méthode existe pour être utilisée comme prédicat' (c'est-à-dire dans les flux).Objects.isNull()
- vous pouvez écrire le vôtre si vous préférez - mais en ce qui concerne la lisibilité, je pense qu'ilisNull()
est préférable d' utiliser . De plus vous avez besoin entre parenthèses supplémentaires pour rendre le simple , la compilation d'expression:from == null != (password == null)
.(val == null)
est tellement la facilité fournie dans le but de comparer avec null, j'ai du mal à surmonter deux grosses invocations de méthode qui me regardent en face, même si la méthode est assez fonctionnelle, intégrable et bien- nommé. Mais c'est juste moi. J'ai décidé récemment que je suis un peu bizarre.Voici une solution générale pour n'importe quel nombre de vérifications nulles
Les usages
la source
Puisque vous voulez faire quelque chose de spécial (utilisez les valeurs par défaut) lorsque l'expéditeur et le mot de passe sont absents, gérez-le d'abord.
Après cela, vous devriez avoir à la fois un expéditeur et un mot de passe pour envoyer un e-mail; lancer une exception si l'un ou l'autre est manquant.
Un avantage supplémentaire est que, si l'une de vos valeurs par défaut est nulle, cela sera également détecté.
Cela dit, en général, je pense que l'utilisation de XOR devrait être autorisée lorsque c'est l'opérateur dont vous avez besoin. Il est une partie de la langue, pas seulement un truc qui fonctionne à cause d'un compilateur bug Arcane.
Une fois, j'ai eu un cow-orker qui a trouvé l'opérateur ternaire trop déroutant à utiliser ...
la source
Je voudrais suggérer une autre alternative, comment j'écrirais réellement ce morceau de code:
Cela me semble être la manière la plus naturelle d'exprimer cette condition qui la rend facile à comprendre pour quelqu'un qui pourrait avoir à la lire à l'avenir. Cela vous permet également de donner des messages de diagnostic plus utiles et de traiter le mot de passe inutile comme moins sérieux et il est facile de modifier ce qui est plutôt probable pour une telle condition. Par exemple, vous découvrirez peut-être que donner un mot de passe comme argument de ligne de commande n'est pas la meilleure idée et que vous voudrez peut-être autoriser la lecture du mot de passe à partir de l'entrée standard si l'argument est manquant. Ou vous pouvez ignorer silencieusement l'argument de mot de passe superflu. Des changements comme ceux-ci ne vous obligeraient pas à tout réécrire.
De plus, il n'exécute que le nombre minimum de comparaisons, donc ce n'est pas plus cher que les alternatives plus "élégantes" . Bien que les performances soient très peu probables, un problème ici, car le démarrage d'un nouveau processus est déjà beaucoup plus coûteux qu'une vérification de null supplémentaire.
la source
Je pense qu'une manière correcte de gérer cela est de considérer trois situations: à la fois «de» et «mot de passe» sont fournis, aucun n'est fourni, un mélange des deux est fourni.
Il semble que la question d'origine veuille interrompre le flux s'il s'agit d'une entrée incorrecte, mais ils devront ensuite répéter une partie de la logique plus tard. Peut-être qu'une bonne déclaration de lancer pourrait être:
la source
Voici un moyen relativement simple qui n'implique aucun Xor og long ifs. Cependant, cela vous oblige à être un peu plus détaillé, mais vous pouvez utiliser les exceptions personnalisées que j'ai suggérées pour obtenir un message d'erreur plus significatif.
la source
Personne ne semble avoir mentionné l' opérateur ternaire :
Fonctionne bien pour vérifier cette condition particulière, mais ne généralise pas bien au-delà de deux variables.
la source
^
,!=
avec deux bools ou deuxif
sa == null ? (b == null? "both null" : "a null while b is not") : (b ==null? "b null while a is not")
Comme je vois vos intentions, il n'est pas nécessaire de toujours vérifier les deux nullités exclusives mais de vérifier si
password
est nul si et seulement sifrom
n'est pas nul. Vous pouvez ignorer l'password
argument donné et utiliser votre propre valeur par défaut sifrom
est null.Écrit en pseudo doit être comme ceci:
la source
password
sans fournirfrom
, il peut avoir l'intention de remplacer le mot de passe, mais conserver le compte par défaut. Si l'utilisateur fait cela, c'est une instruction invalide et il doit en être informé. Le programme ne doit pas continuer comme si l'entrée était valide, et essayer d'utiliser le compte par défaut avec un mot de passe que l'utilisateur n'a pas spécifié. Je jure sur des programmes comme ça.Je suis surpris que personne n'ait mentionné la solution simple de créer
from
et depassword
champs d'une classe et de passer une référence à une instance de cette classe:Ici
from
peut être nul ou non nul et s'il n'est pas nul, ses deux champs ont des valeurs non nulles.Un avantage de cette approche est que l'erreur de rendre un champ mais pas l'autre champ nul est déclenchée là où le compte est initialement obtenu, pas lorsque le code utilisant le compte s'exécute. Au moment où le code utilisant le compte est exécuté, il est impossible que les données soient invalides.
Un autre avantage de cette approche est plus lisible car elle fournit plus d'informations sémantiques. En outre, il est probable que vous ayez besoin du nom et du mot de passe ensemble à d'autres endroits, de sorte que le coût de la définition d'une classe supplémentaire s'amortit sur plusieurs utilisations.
la source
new Account(null, null)
lancera un NPE même si un compte avec à la fois un nom nul et un mot de passe est toujours valide.null
place d'unAccount
. Vous ne passeriez pasnull
auAccount
constructeur.