Unterschied zwischen "Voraussetzung" und "Behauptung" in kurzer Zeit?

105

Was ist der Unterschied zwischen precondition(condition: Bool, message: String)und assert(condition: Bool, message: String)in Swift?

Beide sehen für mich gleich aus. In welchem ​​Kontext sollten wir einen über den anderen verwenden?

Chao Ruan
quelle

Antworten:

125

assertdient zur Überprüfung der geistigen Gesundheit während des Testens, während preconditiones zum Schutz vor Dingen dient, die bedeuten würden, dass Ihr Programm in diesem Fall nicht angemessen fortgesetzt werden kann.

So können Sie beispielsweise eine assertBerechnung mit vernünftigen Ergebnissen durchführen ( z. B. innerhalb einiger Grenzen), um schnell festzustellen, ob Sie einen Fehler haben. Aber Sie möchten damit nicht versenden, da das Out-of-Bound-Ergebnis möglicherweise gültig und nicht kritisch ist und Ihre App nicht abstürzen sollte (nehmen Sie an, Sie haben es nur verwendet, um den Fortschritt in einem Fortschrittsbalken anzuzeigen).

Wenn Sie jedoch überprüfen, ob ein Index in einem Array gültig ist, wenn Sie ein Element abrufen, ist dies a precondition. Es gibt keine vernünftige nächste Aktion für das Array - Objekt zu nehmen , wenn für einen ungültigen Index gefragt, denn es muss einen nicht-optionalen Wert zurück.

Volltext aus den Dokumenten (versuchen Sie es mit einem Optionsklick assertund preconditionin Xcode):

Voraussetzung

Überprüfen Sie eine notwendige Bedingung, um Fortschritte zu erzielen.

Verwenden Sie diese Funktion, um Bedingungen zu erkennen, die verhindern müssen, dass das Programm auch im Versandcode fortgesetzt wird.

  • In Spielplätzen und -Onone-Builds (die Standardeinstellung für die Debug-Konfiguration von Xcode): Wenn conditionsie als falsch ausgewertet wird, stoppen Sie die Programmausführung nach dem Drucken in einem debuggbaren Zustand message.

  • In -O-Builds (Standardeinstellung für die Release-Konfiguration von Xcode): Wenn der conditionWert false ist, beenden Sie die Programmausführung.

  • In -Ounchecked baut, conditionwird nicht ausgewertet, aber der Optimierer annehmen kann , dass es würde zu bewerten true. Die Nichterfüllung dieser Annahme in -Ounchecked Builds ist ein schwerwiegender Programmierfehler.

Behaupten

Traditionelle Bestätigung im C-Stil mit einer optionalen Nachricht.

Verwenden Sie diese Funktion für interne Sicherheitsüberprüfungen, die während des Tests aktiv sind, jedoch die Leistung des Versandcodes nicht beeinträchtigen. So überprüfen Sie, ob die Verwendung in Release-Builds ungültig ist; siehe precondition.

  • In Spielplätzen und -Onone-Builds (die Standardeinstellung für die Debug-Konfiguration von Xcode): Wenn conditionsie als falsch ausgewertet wird, stoppen Sie die Programmausführung nach dem Drucken in einem debuggbaren Zustand message.

  • In -O-Builds (die Standardeinstellung für die Release-Konfiguration von Xcode) conditionwird nicht ausgewertet und es gibt keine Auswirkungen.

  • In -Ounchecked baut, conditionwird nicht ausgewertet, aber der Optimierer annehmen kann , dass es würde zu bewerten true. Die Nichterfüllung dieser Annahme in -Ounchecked Builds ist ein schwerwiegender Programmierfehler.

Fluggeschwindigkeit
quelle
2
"Aber Sie würden damit nicht versenden wollen, da das Out-of-Bound-Ergebnis möglicherweise gültig und nicht kritisch ist und Ihre App nicht abstürzen sollte", ist das für mich sehr vage. Können Sie uns bitte ein genaues Beispiel geben? Vielleicht etwas Code.
Honig
2
Als Antwort auf Ihre Frage verwende ich persönlich Asserts, um Dinge zu erfassen, die in meinem Build einfach nicht passieren sollten, während ich sie schreibe und teste. Stellen Sie sich eine Guard-Anweisung vor, die JSON liest, wo data["name"]sie nicht existiert, aber sollte. Eine Behauptung innerhalb der Wache zu haben ... sonst {} würde mir helfen, meinen Fehler zu erkennen, indem ich abstürze und mich zum Problem bringe. Wenn dieser Code in Produktion wäre, würde die Zusicherung das Programm nicht zum Absturz bringen, und der von mir verwendete Sicherungscode ( return nil) würde ebenfalls übernehmen.
Alec O
1
Sollten Sie nicht den Index überprüfen und nichts tun, anstatt die gesamte App zum Absturz zu bringen?
Iulian Onofrei
Ja, Sie sollten den Index überprüfen, aber jeder rutscht manchmal aus, und die Verwendung von Asserts hilft Ihnen zu erkennen, dass Sie den Index hätten überprüfen sollen, wenn Sie ihn vergessen haben.
Victor Engel
90

Ich fand Swift Asserts - das fehlende Handbuch hilfreich

                        debug   release   release
function                -Onone  -O       -Ounchecked
assert()                YES     NO        NO
assertionFailure()      YES     NO        NO**
precondition()          YES     YES       NO
preconditionFailure()   YES     YES       YES**
fatalError()*           YES     YES       YES

Und aus interessanten Diskussionen über Swift Evolution

- assert: Überprüfen Sie Ihren eigenen Code auf interne Fehler

- Voraussetzung: um zu überprüfen, ob Ihre Kunden Ihnen gültige Argumente gegeben haben.

Außerdem müssen Sie bei der Verwendung vorsichtig sein, siehe assertionFailure und Optimization Level

onmyway133
quelle
Können Sie den Unterschied zwischen eigenem Code und Client erläutern? Was den Client betrifft, meinen Sie das Einfügen von Zahlen, bei denen ein String erwartet wird? Sollte das nicht mit einer einfachen Fehlerbehandlung behandelt werden?
Honig
@Honey Ich denke, er meint über die Argumente / Ergebnisse von Netzwerk-API-Aufrufen oder Client-eigenen Plugins.
Chen Li Yong
Der Client ist jemand, der Ihren Code verwendet. Angenommen, Sie schreiben eine Bibliothek und ein Programmierer übergibt ungültige Daten. Sie möchten nicht ordnungsgemäß fortfahren, da dies als schwerwiegender Programmierfehler angesehen werden kann. Sie sollten wahrscheinlich niemals mit ungültigen Netzwerk-API-Daten abstürzen, da dies für den Benutzer sehr wenig hilfreich ist.
Bompf
@ onmyway133: Von der Xcode Schnellhilfe, denke ich precondition()und preconditionFailure()sind die gleichen Verhaltensweisen aufweisen . Der Unterschied zwischen diesen Funktionen ist: preconditionBenötigen Sie eine Bedingung im Inneren, während Sie preconditionFailureeinfach wegwerfen.
nahung89
12

Das preconditionist im Release-Modus aktiv, sodass Sie die App beenden, wenn Sie Ihre App versenden und die Vorbedingung fehlschlägt. Assertfunktioniert standardmäßig nur im Debug-Modus.

Ich habe diese großartige Erklärung gefunden, wann ich sie auf NSHipster verwenden soll:

Behauptungen sind ein Konzept, das der klassischen Logik entlehnt ist. Behauptungen sind in der Logik Aussagen über Sätze innerhalb eines Beweises. Bei der Programmierung bezeichnen Behauptungen Annahmen, die der Programmierer über die Anwendung an dem Ort gemacht hat, an dem sie deklariert wurden.

In der Eigenschaft von Vor- und Nachbedingungen, die Erwartungen an den Status des Codes zu Beginn und am Ende der Ausführung einer Methode oder Funktion beschreiben, bilden Zusicherungen einen Vertrag. Assertions können auch verwendet werden, um Bedingungen zur Laufzeit zu erzwingen, um die Ausführung zu verhindern, wenn bestimmte Voraussetzungen fehlschlagen.

Greg
quelle
Zusicherungen können mithilfe eines Compiler-Flags aktiviert und deaktiviert werden. Sie können im Versandcode aktiv sein.
Pétur Ingi Egilsson
6

Voraussetzung

func precondition(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)

Überprüfen Sie eine notwendige Bedingung, um Fortschritte zu erzielen.

  1. Verwenden Sie diese Funktion, um Bedingungen zu erkennen, die verhindern müssen, dass das Programm auch im Versandcode fortgesetzt wird.
  2. In Spielplätzen und -Onone-Builds (die Standardeinstellung für die Debug-Konfiguration von Xcode): Wenn die Bedingung als falsch ausgewertet wird, stoppen Sie die Programmausführung nach dem Drucken der Nachricht in einem debuggbaren Zustand.
  3. In -O-Builds (Standardeinstellung für die Release-Konfiguration von Xcode): Wenn die Bedingung als falsch ausgewertet wird, stoppen Sie die Programmausführung.
  4. In -Ounchecked Builds wird die Bedingung nicht ausgewertet, aber der Optimierer kann davon ausgehen, dass sie als wahr ausgewertet wird. Die Nichterfüllung dieser Annahme in -Ounchecked Builds ist ein schwerwiegender Programmierfehler.

behaupten

func assert(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)

Traditionelle Bestätigung im C-Stil mit einer optionalen Nachricht.

  1. Verwenden Sie diese Funktion für interne Sicherheitsüberprüfungen, die während des Tests aktiv sind, jedoch die Leistung des Versandcodes nicht beeinträchtigen. So überprüfen Sie, ob die Verwendung in Release-Builds ungültig ist; siehe Voraussetzung.

  2. In Spielplätzen und -Onone-Builds (die Standardeinstellung für die Debug-Konfiguration von Xcode): Wenn die Bedingung als falsch ausgewertet wird, stoppen Sie die Programmausführung nach dem Drucken der Nachricht in einem debuggbaren Zustand.

  3. In -O-Builds (die Standardeinstellung für die Release-Konfiguration von Xcode) wird die Bedingung nicht ausgewertet und es gibt keine Auswirkungen
  4. In -Ounchecked Builds wird die Bedingung nicht ausgewertet, aber der Optimierer kann davon ausgehen, dass sie als wahr ausgewertet wird. Die Nichterfüllung dieser Annahme in -Ounchecked Builds ist ein schwerwiegender Programmierfehler
13. Geist
quelle