Ich habe Spring Boot verwendet, um ein Shell-Projekt zu entwickeln, mit dem E-Mails gesendet werden, z
sendmail -from foo@bar.com -password foobar -subject "hello world" -to aaa@bbb.com
Wenn die Argumente from
und password
fehlen, verwende ich einen Standardabsender und ein Standardkennwort, z . B. [email protected]
und 123456
.
Wenn der Benutzer das from
Argument übergibt , muss er auch das password
Argument übergeben und umgekehrt. Das heißt, entweder sind beide nicht null oder beide sind null.
Wie überprüfe ich das elegant?
Jetzt ist mein Weg
if ((from != null && password == null) || (from == null && password != null)) {
throw new RuntimeException("from and password either both exist or both not exist");
}
From
E-Mail-Adresse ist nicht immer der SMTP-Authentifizierungsname.Antworten:
Es gibt eine Möglichkeit, den Operator
^
( XOR ) zu verwenden:Die
if
Bedingung ist wahr, wenn nur eine Variable null ist.Aber ich denke, normalerweise ist es besser, zwei
if
Bedingungen mit unterschiedlichen Ausnahmemeldungen zu verwenden. Sie können nicht mit einer einzigen Bedingung definieren, was schief gelaufen ist.Es ist besser lesbar und viel einfacher zu verstehen, und es erfordert nur ein wenig zusätzliche Eingabe.
quelle
!=
?!=
. Verblüfft. Und das ist eine sehr hohe Anzahl von Upvotes im Kommentar. Und um diesem Kommentar Qualität zu verleihen, denke ich auch, dass es besser ist, unterschiedliche Fehlermeldungen für unterschiedliche Fehlerfälle zu geben, da der Benutzer besser weiß, wie er den Fehler korrigieren kann.if
Klauseln rechtfertigt - die Nachricht in der Ausnahme dokumentiert es gut (ich habe die Frage bearbeitet, aber sie wird erst angezeigt, wenn sie angenommen wurde)Nun, es hört sich so an, als würden Sie versuchen zu überprüfen, ob die "Null" -Zustand der beiden gleich ist oder nicht. Du könntest benutzen:
Oder machen Sie es mit Hilfsvariablen expliziter:
quelle
^
. :-)^
heißt nur "Hey, meine Operanden sind Boolesche Werte" auf eine Weise, die!=
dies nicht tut. (Obwohl dieser Effekt leider durch die Notwendigkeit verringert wird, nach "Meine Operanden sind möglicherweise numerisch und ich bin zu diesem Zeitpunkt möglicherweise kein Vergleichsoperator" zu suchen, ist dies ein Nachteil.) Ihr Heldenstatus unvermindert, obwohl Sie nicht mit mir übereinstimmen :-)from
undpassword
beide müssen null sein oder beide dürfen nicht null sein". Vielleicht bin das nur ich und meine Unerfahrenheit, aber ich bevorzuge die besser lesbare Lösung wie in der Antwort von @ stig-hemmer, auch wenn sie weitere 3 Codezeilen kostet. Ich glaube , ich einfach nicht sofort bekommenbool != bool
- es ist nicht intuitiv.^
Operator ist ein bitweiser Operator. es bedeutet eigentlich nicht, dass seine Operanden boolesch sind. Der boolesche xor-Operator istxor
.Ich persönlich bevorzuge lesbar gegenüber elegant.
quelle
IllegalArgumentException
anstelle einer nacktenRuntimeException
)Fügen Sie diese Funktionalität in eine 2-Argument-Methode mit der Signatur ein:
Dies spart Platz in der eigentlichen Methode, an der Sie interessiert sind, und macht sie lesbarer. An leicht ausführlichen Methodennamen ist nichts auszusetzen, und an sehr kurzen Methoden ist nichts auszusetzen.
quelle
((from == null) != (password == null))
, das ist auch sehr einfach zu verstehen. Mit nicht nützlichen Methoden stimmt etwas nicht.Unter der
Objects.isNull(Object)
Annahme eines statischen Imports wäre eine Java 8-Lösung zu verwenden :Für Java <8 (oder wenn Sie es nicht mögen
Objects.isNull()
) können Sie einfach Ihre eigeneisNull()
Methode schreiben .quelle
from == null != password == null
Hält alles auf dem gleichen Frame des Stapels,Objects.isNull(Object)
drückt aber unnötig zwei Frames und knallt sie. Objects.isNull (Object) ist vorhanden, weil 'Diese Methode existiert, um als Prädikat verwendet zu werden' (dh in Streams).Objects.isNull()
- Sie können Ihre eigenen schreiben, wenn Sie es vorziehen -, aber was die Lesbarkeit betrifft, denke ich, dass die VerwendungisNull()
besser ist. Darüber hinaus benötigen Sie zusätzliche Klammern, damit der einfache Ausdruck kompiliert werden kann :from == null != (password == null)
.(val == null)
ist es so sehr die Möglichkeit , mit Null zu vergleichen, dass es mir schwer fällt, über zwei Aufrufe der großen Fettmethode hinwegzukommen, die mich ins Gesicht starren, selbst wenn die Methode ziemlich funktional, inlinierbar und gut ist. genannt. Das bin aber nur ich. Ich habe vor kurzem entschieden, dass ich ein bisschen seltsam bin.Hier ist eine allgemeine Lösung für eine beliebige Anzahl von Nullprüfungen
Verwendet
quelle
Da Sie etwas Besonderes tun möchten (Standardeinstellungen verwenden), wenn sowohl Absender als auch Kennwort fehlen, behandeln Sie dies zuerst.
Danach sollten Sie sowohl einen Absender als auch ein Passwort haben, um eine E-Mail zu senden. eine Ausnahme auslösen, wenn eine fehlt.
Ein zusätzlicher Vorteil ist, dass, sollte einer Ihrer Standardeinstellungen null sein, dies ebenfalls erkannt wird.
Trotzdem denke ich im Allgemeinen , dass die Verwendung von XOR zulässig sein sollte, wenn dies der Operator ist, den Sie benötigen. Es ist ein Teil der Sprache, nicht nur ein Trick, der aufgrund eines arkanen Compiler-Fehlers funktioniert.
Ich hatte einmal einen Kuh-Orker, der den ternären Operator zu verwirrend fand, um ihn zu benutzen ...
quelle
Ich möchte eine andere Alternative vorschlagen, wie ich diesen Code tatsächlich schreiben würde:
Für mich scheint dies der natürlichste Weg zu sein, diesen Zustand auszudrücken, der es für jemanden, der ihn in Zukunft möglicherweise lesen muss, leicht verständlich macht. Außerdem können Sie hilfreichere Diagnosemeldungen geben und das unnötige Kennwort als weniger schwerwiegend behandeln, und es ist einfach zu ändern, was für einen solchen Zustand eher wahrscheinlich ist. Das heißt, Sie stellen möglicherweise fest, dass die Angabe eines Kennworts als Befehlszeilenargument nicht die beste Idee ist, und möchten möglicherweise das Lesen des Kennworts aus der Standardeingabe optional zulassen, wenn das Argument fehlt. Oder Sie möchten das überflüssige Kennwortargument stillschweigend ignorieren. Änderungen wie diese würden nicht erfordern, dass Sie das Ganze neu schreiben.
Außerdem werden nur die Mindestanzahl von Vergleichen ausgeführt, sodass es nicht teurer ist als die "eleganteren" Alternativen. Obwohl die Leistung hier sehr unwahrscheinlich ist, ist das Starten eines neuen Prozesses bereits viel teurer als eine zusätzliche Nullprüfung.
quelle
Ich denke, ein korrekter Weg, um damit umzugehen, besteht darin, drei Situationen zu betrachten: Sowohl 'von' als auch 'Passwort' werden bereitgestellt, keine werden bereitgestellt, eine Mischung aus beiden wird bereitgestellt.
Es hört sich so an, als ob die ursprüngliche Frage den Fluss unterbrechen möchte, wenn es sich um eine falsche Eingabe handelt, aber dann müssen sie später einen Teil der Logik wiederholen. Vielleicht könnte eine gute Wurfaussage sein:
quelle
Hier ist ein relativ unkomplizierter Weg, bei dem kein Xor oder langwieriges Wenn erforderlich ist. Es erfordert jedoch, dass Sie etwas ausführlicher sind, aber auf der anderen Seite können Sie die von mir vorgeschlagenen benutzerdefinierten Ausnahmen verwenden, um eine aussagekräftigere Fehlermeldung zu erhalten.
quelle
Niemand scheint den ternären Operator erwähnt zu haben :
Funktioniert gut zum Überprüfen dieser bestimmten Bedingung, verallgemeinert sich jedoch nicht weit über zwei Variablen hinaus.
quelle
^
,!=
mit zwei bools oder zweiif
sa == null ? (b == null? "both null" : "a null while b is not") : (b ==null? "b null while a is not")
Wie ich Ihre Absichten sehe, besteht nicht die Notwendigkeit, immer beide exklusiven Nullen zu überprüfen, sondern zu prüfen, ob
password
genau dann null ist, wennfrom
nicht null ist. Sie können das angegebenepassword
Argument ignorieren und Ihren eigenen Standard verwenden, wennfrom
null ist.In Pseudo geschrieben muss so sein:
quelle
password
ohnefrom
Angabe liefert , möglicherweise beabsichtigt hat, das Kennwort zu überschreiben, aber das Standardkonto beibehält. Wenn der Benutzer dies tut, handelt es sich um eine ungültige Anweisung, die ihm mitgeteilt werden sollte. Das Programm sollte nicht so fortfahren, als ob die Eingabe gültig wäre, und versuchen Sie, das Standardkonto mit einem Kennwort zu verwenden, das der Benutzer nicht angegeben hat. Ich schwöre bei solchen Programmen.Ich bin überrascht, dass niemand die einfache Lösung erwähnt hat, eine Klasse zu erstellen
from
undpassword
Felder zu erstellen und einen Verweis auf eine Instanz dieser Klasse zu übergeben:Hier
from
kann null oder nicht null sein, und wenn es nicht null ist, haben beide Felder nicht null Werte.Ein Vorteil dieses Ansatzes besteht darin, dass der Fehler, ein Feld, aber nicht das andere Feld auf Null zu setzen, dort ausgelöst wird, wo das Konto ursprünglich abgerufen wurde, und nicht, wenn der Code, der das Konto verwendet, ausgeführt wird. Zum Zeitpunkt der Ausführung des Codes, der das Konto verwendet, ist es unmöglich, dass die Daten ungültig sind.
Ein weiterer Vorteil dieses Ansatzes ist besser lesbar, da er mehr semantische Informationen liefert. Es ist auch wahrscheinlich, dass Sie den Namen und das Kennwort an anderen Stellen zusammen benötigen, sodass sich die Kosten für die Definition einer zusätzlichen Klasse über mehrere Verwendungen amortisieren.
quelle
new Account(null, null)
eine NPE ausgelöst wird, obwohl das Konto mit dem Nullnamen und dem Kennwort noch gültig ist.null
anstelle von ein verwendenAccount
. Sie würden nichtnull
an denAccount
Konstruktor übergeben.