Unsere Organisation hat eine erforderliche Codierungsregel (ohne Erklärung), die:
if… else if Konstrukte sollten mit einer else-Klausel beendet werden
Beispiel 1:
if ( x < 0 )
{
x = 0;
} /* else not needed */
Beispiel 2:
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
Für welchen Randfall ist dies ausgelegt?
Was mich auch über den Grund beunruhigt, ist, dass Beispiel 1 kein benötigt else
, Beispiel 2 jedoch. Wenn der Grund die Wiederverwendbarkeit und Erweiterbarkeit ist, sollte meiner Meinung else
nach in beiden Fällen verwendet werden.
assert(false, "should never go here")
Sinn machen könnteif (x < 0) { x = 0; } else { if (y < 0) { x = 3; }}
. Oder Sie könnten einfach solchen Regeln folgen, von denen viele dumm sind, einfach weil Sie dazu verpflichtet sind.< 0
Überprüfungen normal erscheint ), so dass die Behauptung geht um das Programm in dem wahrscheinlich häufigsten Fall zum Absturz zu bringen, in dem Werte in erwarteten Grenzen liegen.Antworten:
Wie in einer anderen Antwort erwähnt, stammt dies aus den MISRA-C-Codierungsrichtlinien. Der Zweck ist die defensive Programmierung, ein Konzept, das häufig in der geschäftskritischen Programmierung verwendet wird.
Das heißt, jeder
if - else if
muss mit einem endenelse
und jederswitch
muss mit einem endendefault
.Dafür gibt es zwei Gründe:
Selbstdokumentierender Code. Wenn Sie ein schreiben
else
, es aber leer lassen, bedeutet dies: "Ich habe das Szenario definitiv in Betracht gezogen, in dem wederif
nochelse if
wahr sind".Dort nicht zu schreiben
else
bedeutet: "Entweder habe ich das Szenario in Betracht gezogen, in dem wederif
nochelse if
wahr sind, oder ich habe völlig vergessen, es zu berücksichtigen, und hier in meinem Code befindet sich möglicherweise ein fetter Fehler."Stoppen Sie den außer Kontrolle geratenen Code. In unternehmenskritischer Software müssen Sie robuste Programme schreiben, die selbst das höchst Unwahrscheinliche berücksichtigen. So konnte man Code wie sehen
Dieser Code ist PC-Programmierern und Informatikern völlig fremd, macht aber in unternehmenskritischer Software durchaus Sinn, da er den Fall erfasst, in dem der "mybool" aus irgendeinem Grund beschädigt wurde.
In der Vergangenheit würden Sie eine Beschädigung des RAM-Speichers aufgrund von EMI / Rauschen befürchten. Dies ist heute kein großes Problem. Es ist weitaus wahrscheinlicher, dass Speicherbeschädigungen aufgrund von Fehlern an anderer Stelle im Code auftreten: Zeiger auf falsche Speicherorte, Fehler außerhalb des Bereichs, Stapelüberlauf, außer Kontrolle geratener Code usw.
In den meisten Fällen kommt Code wie dieser zurück, um sich selbst ins Gesicht zu schlagen, wenn Sie während der Implementierungsphase Fehler geschrieben haben. Das heißt, es kann auch als Debug-Technik verwendet werden: Das Programm, das Sie schreiben, teilt Ihnen mit, wann Sie Fehler geschrieben haben.
BEARBEITEN
In Bezug darauf, warum
else
nicht nach jedem einzelnen benötigt wirdif
:Ein
if-else
oderif-else if-else
deckt alle möglichen Werte ab, die eine Variable haben kann. Eine einfacheif
Aussage ist jedoch nicht unbedingt dazu da, alle möglichen Werte abzudecken, sondern wird viel breiter verwendet. Meistens möchten Sie nur eine bestimmte Bedingung überprüfen, und wenn sie nicht erfüllt ist, tun Sie nichts. Dann ist es einfach nicht sinnvoll, defensive Programme zu schreiben, um denelse
Fall abzudecken .Außerdem würde es den Code komplett überladen, wenn Sie
else
nach jedem einen leeren Code schreiben würdenif
.MISRA-C: 2012 15.7 gibt keine Begründung, warum
else
es nicht benötigt wird, es heißt nur:quelle
if/else if/else
kompiliert haben, was Sie erwarten? Und dann noch eine, um auch den vorherigen Prüfer zu überprüfen?mybool
sich um einen nicht-booleschen Typ, wie dies vor C der Fall warbool
; dann würde der Compiler die Annahme ohne zusätzliche statische Analyse nicht treffen). Und zum Thema "Wenn Sie ein anderes schreiben, es aber leer lassen, bedeutet dies:" Ich habe das Szenario definitiv in Betracht gezogen, wenn weder wenn noch sonst wahr ist ". Meine erste Reaktion ist die Annahme, dass der Programmierer vergessen hat, Code einzugeben der else-Block, sonst warum nur ein leerer else-Block da sitzen? Ein// unused
Kommentar wäre angebracht, nicht nur ein leerer Block.else
Block muss einen Kommentar enthalten, wenn kein Code vorhanden ist. Übliche Praxis für leerelse
ist ein einzelnes Semikolon plus ein Kommentar :else { ; // doesn't matter }
. Da es keinen Grund gibt, warum jemand sonst einfach ein eingerücktes, einzelnes Semikolon in einer eigenen Zeile eingeben würde. Eine ähnliche Vorgehensweise wird manchmal in leeren Schleifen angewendet :while(something) { ; // do nothing }
. (Code mit Zeilenumbrüchen natürlich. SO Kommentare erlauben sie nicht)Ihr Unternehmen hat die MISRA-Codierungsrichtlinien befolgt. Es gibt einige Versionen dieser Richtlinien, die diese Regel enthalten, jedoch aus MISRA-C: 2004 † :
In MISRA-C: 2012 , das die Version 2004 ersetzt und die aktuelle Empfehlung für neue Projekte darstellt, existiert dieselbe Regel, ist jedoch mit 15,7 nummeriert .
Beispiel 1: In einer einzelnen if-Anweisung muss der Programmierer möglicherweise n Bedingungen überprüfen und führt eine einzelne Operation aus.
Bei einer normalen Verwendung ist die Ausführung einer Operation nicht immer erforderlich, wenn sie
if
verwendet wird.Beispiel 2: Hier prüft der Programmierer n Anzahl von Bedingungen und führt mehrere Operationen aus. In regelmäßiger Anwendung
if..else if
ist wieswitch
Sie eine Operation wie Standard ausführen müssen können. Daherelse
ist eine Verwendung gemäß Misra-Standard erforderlich† Aktuelle und frühere Versionen dieser Veröffentlichungen können über den MISRA-Webstore ( via ) erworben werden.
quelle
else
Klausel nicht erreichbar ist? (Lassen Sie stattdessen die endgültige Bedingung weg, werfen Sie vielleicht einen Fehler?)Dieses Extra verringert die Codeabdeckung Ihres Programms.
Nach meiner Erfahrung mit der Portierung von Linux-Kernel oder Android-Code auf eine andere Plattform machen wir oft etwas falsch und in logcat sehen wir einige Fehler wie
quelle
__FILE__
und__LINE__
Makros sind nützlich , um den Quellort leicht zu finden , wenn die Nachricht gedruckt wird eh und je.Nur eine kurze Erklärung, da ich das alles vor ungefähr 5 Jahren gemacht habe.
Es gibt (bei den meisten Sprachen) keine syntaktische Anforderung, die
else
Anweisung "null" (und unnötig{..}
) einzuschließen , und in "einfachen kleinen Programmen" besteht keine Notwendigkeit. Aber echte Programmierer schreiben keine "einfachen kleinen Programme", und ebenso wichtig ist, dass sie keine Programme schreiben, die einmal verwendet und dann verworfen werden.Wenn man ein if / else schreibt:
es scheint alles einfach und man sieht kaum den Sinn des Hinzufügens
{..}
.Aber eines Tages, in einigen Monaten, muss ein anderer Programmierer (Sie würden niemals einen solchen Fehler machen!) Das Programm "verbessern" und eine Erklärung hinzufügen.
Plötzlich
doSomethingElse
vergisst irgendwie, dass es imelse
Bein sein soll.Sie sind also ein guter kleiner Programmierer und verwenden immer
{..}
. Aber du schreibst:Alles ist gut und schön, bis dieses neue Kind eine Mitternachtsmodifikation vornimmt:
Ja, es ist falsch formatiert, aber auch der halbe Code im Projekt, und der "automatische Formatierer" wird durch alle
#ifdef
Anweisungen durcheinander gebracht . Und natürlich ist der echte Code weitaus komplizierter als dieses Spielzeugbeispiel.Leider (oder auch nicht) bin ich seit ein paar Jahren nicht mehr in der Lage, also habe ich kein neues "echtes" Beispiel im Sinn - das oben Genannte ist (offensichtlich) erfunden und ein bisschen hokey.
quelle
Dies geschieht, um den Code für spätere Verweise besser lesbar zu machen und einem späteren Prüfer klar zu machen, dass die verbleibenden Fälle, die vom letzten behandelt werden
else
, keine Fälle sind, damit sie auf den ersten Blick nicht übersehen werden.Dies ist eine gute Programmierpraxis, die Code wiederverwendbar und erweiterbar macht .
quelle
Ich möchte die vorherigen Antworten ergänzen - und teilweise widersprechen. Während es sicherlich üblich ist, if-else zu verwenden, wenn es sich um einen Schalter handelt, der den gesamten Bereich denkbarer Werte für einen Ausdruck abdecken soll, ist keineswegs garantiert, dass ein Bereich möglicher Bedingungen vollständig abgedeckt ist. Das Gleiche gilt für das Switch-Konstrukt selbst, daher die Anforderung, eine Standardklausel zu verwenden, die alle verbleibenden Werte abfängt und, sofern dies nicht anderweitig erforderlich ist, als Assertionsschutz verwendet werden kann.
Die Frage selbst enthält ein gutes Gegenbeispiel: Die zweite Bedingung bezieht sich überhaupt nicht auf x (weshalb ich häufig die flexiblere if-basierte Variante der switchbasierten Variante vorziehe). Aus dem Beispiel geht hervor, dass x auf einen bestimmten Wert gesetzt werden sollte, wenn die Bedingung A erfüllt ist. Sollte A nicht erfüllt sein, wird Bedingung B getestet. Wenn es erfüllt ist, sollte x einen anderen Wert erhalten. Wenn weder A noch B erfüllt sind, sollte x unverändert bleiben.
Hier können wir sehen, dass ein leerer else-Zweig verwendet werden sollte, um die Absicht des Programmierers für den Leser zu kommentieren.
Andererseits kann ich nicht verstehen, warum es eine else-Klausel speziell für die neueste und innerste if-Anweisung geben muss. In C gibt es kein "else if". Es gibt nur wenn und sonst. Stattdessen sollte laut MISRA das Konstrukt auf diese Weise formal eingerückt werden (und ich hätte die öffnenden geschweiften Klammern auf ihre eigenen Linien setzen sollen, aber das gefällt mir nicht):
Wenn MISRA darum bittet, geschweifte Klammern um jeden Zweig zu setzen, widerspricht es sich selbst, indem es "wenn ... sonst wenn Konstrukte" erwähnt.
Jeder kann sich die Hässlichkeit tief verschachtelter Bäume vorstellen, siehe hier eine Randnotiz . Stellen Sie sich nun vor, dass dieses Konstrukt beliebig überall erweitert werden kann. Dann wird es absurd, am Ende nach einer else-Klausel zu fragen, aber nirgendwo anders.
Ich bin mir also sicher, dass die Leute, die die MISRA-Richtlinien entwickelt haben, das switch-like if-else-beabsichtigte Ziel hatten.
Am Ende kommt es darauf an, genau zu definieren, was mit einem "wenn ... sonst wenn Konstrukt" gemeint ist.
quelle
Der Hauptgrund ist wahrscheinlich die Codeabdeckung und das implizite andere: Wie verhält sich der Code, wenn die Bedingung nicht erfüllt ist? Für echte Tests benötigen Sie eine Möglichkeit, um festzustellen, ob Sie mit der Bedingung false getestet haben. Wenn jeder Testfall, den Sie haben, die if-Klausel durchläuft, kann Ihr Code aufgrund einer Bedingung, die Sie nicht getestet haben, Probleme in der realen Welt haben.
Einige Bedingungen können jedoch ordnungsgemäß wie in Beispiel 1 sein, z. B. in einer Steuererklärung: "Wenn das Ergebnis kleiner als 0 ist, geben Sie 0 ein." Sie müssen noch einen Test durchführen, bei dem die Bedingung falsch ist.
quelle
Logischerweise impliziert jeder Test zwei Zweige. Was machst du, wenn es wahr ist, und was machst du, wenn es falsch ist?
In den Fällen, in denen einer der Zweige keine Funktionalität hat, ist es sinnvoll, einen Kommentar hinzuzufügen, warum er keine Funktionalität benötigt.
Dies kann für den nächsten Wartungsprogrammierer von Vorteil sein. Sie sollten nicht zu weit suchen müssen, um zu entscheiden, ob der Code korrekt ist. Sie können den Elefanten irgendwie vorjagen .
Persönlich hilft es mir, da es mich zwingt, den anderen Fall zu betrachten und ihn zu bewerten. Es kann eine unmögliche Bedingung sein. In diesem Fall kann ich eine Ausnahme auslösen, da der Vertrag verletzt wird. Es kann harmlos sein. In diesem Fall kann ein Kommentar ausreichen.
Ihr Kilometerstand kann variieren.
quelle
Die meiste Zeit, wenn Sie nur eine einzige
if
Aussage haben, ist dies wahrscheinlich einer der Gründe wie:Beispiel
Aber wenn Sie dies tun
if .. else if
, ist dies wahrscheinlich einer der Gründe wie:Und falls Ihr
if .. else if
alle Möglichkeiten abdeckt, in diesem Fall Ihr letzterif (...)
nicht benötigt wird, können Sie ihn einfach entfernen, da zu diesem Zeitpunkt die einzig möglichen Werte diejenigen sind, die von dieser Bedingung abgedeckt werden.Beispiel
Und in den meisten dieser Gründe ist es möglich, dass etwas in keine der Kategorien in Ihrer Kategorie passt.
if .. else if
Daher muss es in einer abschließendenelse
Klausel behandelt werden. Die Behandlung kann über Verfahren auf Unternehmensebene, Benutzerbenachrichtigung, internen Fehlermechanismus erfolgen. ..etc.Beispiel
Diese letzte
else
Klausel ähnelt einigen anderen Dingen in Sprachen wieJava
undC++
, wie zum Beispiel:default
Fall in einer switch-Anweisungcatch(...)
das kommt nach allen spezifischencatch
Blöckenfinally
in einer try-catch-Klauselquelle
Unsere Software war nicht geschäftskritisch, aber wir haben uns aufgrund der defensiven Programmierung auch für diese Regel entschieden. Wir haben dem theoretisch nicht erreichbaren Code eine Wurfausnahme hinzugefügt (switch + if-else). Und es hat uns viele Male gerettet, da die Software schnell fehlgeschlagen ist, z. B. wenn ein neuer Typ hinzugefügt wurde und wir vergessen haben, ein oder zwei if-else oder switch zu ändern. Als Bonus war es super einfach, das Problem zu finden.
quelle
Nun, mein Beispiel beinhaltet undefiniertes Verhalten, aber manchmal versuchen einige Leute, ausgefallen zu sein und scheitern schwer. Schauen Sie sich das an:
Sie würden wahrscheinlich nie erwarten zu haben ,
bool
was nicht ist ,true
nochfalse
, aber es kann passieren. Persönlich glaube ich, dass dies ein Problem ist, das von einer Person verursacht wird, die sich entscheidet, etwas Besonderes zu tun, aber eine zusätzlicheelse
Aussage kann weitere Probleme verhindern.quelle
Ich arbeite derzeit mit PHP. Erstellen eines Registrierungsformulars und eines Anmeldeformulars. Ich benutze nur wenn und sonst. Nichts anderes, wenn oder irgendetwas, was unnötig ist.
Wenn der Benutzer auf die Schaltfläche "Senden" klickt -> wird mit der nächsten if-Anweisung fortgefahren ... Wenn der Benutzername weniger als "X" Zeichen enthält, wird eine Warnung ausgegeben. Wenn erfolgreich, überprüfen Sie die Passwortlänge und so weiter.
Es ist kein zusätzlicher Code erforderlich, z. B. ein anderer, wenn dies die Zuverlässigkeit der Serverladezeit beeinträchtigen könnte, um den gesamten zusätzlichen Code zu überprüfen.
quelle