Différence entre «précondition» et «affirmer» dans swift?

105

Quelle est la différence entre precondition(condition: Bool, message: String)et assert(condition: Bool, message: String)dans Swift?

Les deux me ressemblent. Dans quel contexte devons-nous utiliser l'un sur l'autre?

Chao Ruan
la source

Réponses:

125

assertest pour les vérifications de cohérence pendant les tests, alors que preconditionpour se prémunir contre des choses qui, si elles se produisent, signifieraient que votre programme ne pourrait tout simplement pas raisonnablement continuer.

Ainsi, par exemple, vous pourriez mettre un assertsur un calcul ayant des résultats raisonnables (dans certaines limites, par exemple), pour trouver rapidement si vous avez un bogue. Mais vous ne voudriez pas expédier avec cela, car le résultat hors limite peut être valide et non critique, vous ne devriez donc pas planter votre application (supposons que vous l'utilisiez simplement pour afficher la progression dans une barre de progression).

D'autre part, vérifier qu'un indice sur un tableau est valide lors de la récupération d'un élément est un precondition. Il n'y a pas de prochaine action raisonnable pour l'objet tableau à effectuer lorsqu'on lui demande un indice non valide, car il doit renvoyer une valeur non facultative.

Texte intégral de la documentation (essayez de cliquer sur option assertet preconditiondans Xcode):

Condition préalable

Vérifiez une condition nécessaire pour avancer.

Utilisez cette fonction pour détecter les conditions qui doivent empêcher le programme de continuer même avec le code d'expédition.

  • Dans les terrains de jeux et les builds -Onone (valeur par défaut pour la configuration de débogage de Xcode): si la valeur est conditionfalse, arrête l'exécution du programme dans un état déboguable après l'impression message.

  • Dans les builds -O (valeur par défaut pour la configuration Release de Xcode): si la valeur est conditionfalse, arrêtez l'exécution du programme.

  • Dans les builds -Ounchecked, conditionn'est pas évalué, mais l'optimiseur peut supposer qu'il serait évalué à true. Le non-respect de cette hypothèse dans les versions -Ounchecked est une grave erreur de programmation.

Affirmer

Affirmation traditionnelle de style C avec un message facultatif.

Utilisez cette fonction pour les vérifications internes de l'intégrité qui sont actives pendant les tests mais qui n'affectent pas les performances du code d'expédition. Pour vérifier l'utilisation non valide dans les versions de version; voir precondition.

  • Dans les terrains de jeux et les builds -Onone (valeur par défaut pour la configuration de débogage de Xcode): si la valeur est conditionfalse, arrête l'exécution du programme dans un état déboguable après l'impression message.

  • Dans les builds -O (la valeur par défaut pour la configuration Release de Xcode), conditionn'est pas évalué et il n'y a pas d'effets.

  • Dans les builds -Ounchecked, conditionn'est pas évalué, mais l'optimiseur peut supposer qu'il serait évalué à true. Le non-respect de cette hypothèse dans les versions -Ounchecked est une grave erreur de programmation.

Vitesse de l'air
la source
2
"Mais vous ne voudriez pas expédier avec cela, car le résultat hors limite pourrait être valide, et non critique, donc ne devrait pas planter votre application", c'est très vague pour moi. Pouvez-vous inclure un exemple exact? Peut-être du code.
Honey
2
En réponse à votre question, j'utilise personnellement des assertions pour détecter des choses qui ne devraient tout simplement pas se produire dans ma version pendant que je l'écris et la teste. Imaginez une instruction de garde lisant JSON là où data["name"]n'existe pas, mais cela devrait. Avoir une affirmation à l'intérieur de la garde..else {} m'aiderait à attraper mon erreur en plantant et en m'amenant au problème. De même, si ce code était en production, l'assert ne ferait pas planter le programme, et le code de sauvegarde que j'ai utilisé ( return nil) prendrait le relais.
Alec O du
1
Ne devriez-vous pas vérifier l'index et ne rien faire au lieu de planter toute l'application?
Iulian Onofrei
Oui, vous devriez vérifier l'index, mais tout le monde dérape parfois, et l'utilisation des assertions vous aide à réaliser que vous auriez dû vérifier l'index lorsque vous avez oublié.
Victor Engel
"Mais vous ne voudriez pas expédier avec cela, car le résultat hors limite peut être valide, et non critique donc ne devrait pas planter votre application". Vous pouvez envoyer votre application avec autant d'assertions que vous le souhaitez. Swift n'évalue tout simplement pas vos conditions dans le bloc d'assertion dans l'application de publication
Akshansh Thakur
90

J'ai trouvé les affirmations de Swift - le manuel manquant était utile

                        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

Et de discussions intéressantes sur Swift Evolution

- assert: vérification de votre propre code pour les erreurs internes

- condition préalable: pour vérifier que vos clients vous ont donné des arguments valides.

En outre, vous devez faire attention à ce qu'il faut utiliser, voir assertionFailure et Optimization Level

onmyway133
la source
Pouvez-vous expliquer la différence entre votre propre code et votre client? Quant au client, voulez-vous dire comme insérer des nombres là où une chaîne est attendue? Cela ne devrait-il pas être traité avec une simple gestion des erreurs?
Honey
@Honey Je pense qu'il parle des arguments / résultats de l'appel d'API réseau ou des propres plugins du client.
Chen Li Yong
Le client serait quelqu'un utilisant votre code, disons que vous écrivez une bibliothèque et qu'un programmeur transmet des données invalides. Vous ne voudriez pas continuer gracieusement car cela pourrait être considéré comme une grave erreur de programmation. Vous ne devriez probablement jamais planter sur des données d'API de mise en réseau non valides, car cela n'est pas utile pour l'utilisateur.
bompf
@ onmyway133: Je pense que le Xcode De QuickHelp, precondition()et preconditionFailure()sont ayant les mêmes comportements . La différence entre ces fonctions est la suivante: preconditionbesoin d'une condition à l'intérieur, tout preconditionFailuresimplement jeter.
nahung89
12

Le preconditionest actif en mode version, donc lorsque vous expédiez votre application et que la condition préalable a échoué, l'application se terminera. Assertfonctionne uniquement en mode débogage par défaut.

J'ai trouvé cette excellente explication pour l'utiliser sur NSHipster:

Les assertions sont un concept emprunté à la logique classique. En logique, les assertions sont des déclarations sur des propositions dans une preuve. En programmation, les assertions dénotent des hypothèses que le programmeur a faites sur l'application à l'endroit où elles sont déclarées.

Lorsqu'elles sont utilisées en tant que préconditions et postconditions, qui décrivent les attentes sur l'état du code au début et à la fin de l'exécution d'une méthode ou d'une fonction, les assertions forment un contrat. Les assertions peuvent également être utilisées pour appliquer des conditions au moment de l'exécution, afin d'empêcher l'exécution lorsque certaines conditions préalables échouent.

Greg
la source
Les assertions peuvent être activées et désactivées à l'aide d'un indicateur de compilateur; ils peuvent être actifs dans le code expédié.
Pétur Ingi Egilsson
6

condition préalable

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

Vérifiez une condition nécessaire pour avancer.

  1. Utilisez cette fonction pour détecter les conditions qui doivent empêcher le programme de continuer même avec le code d'expédition.
  2. Dans les terrains de jeux et les builds -Onone (valeur par défaut pour la configuration de débogage de Xcode): si la condition est évaluée à false, arrêtez l'exécution du programme dans un état déboguable après l'impression du message.
  3. Dans les builds -O (valeur par défaut pour la configuration Release de Xcode): si la condition est évaluée à false, arrêtez l'exécution du programme.
  4. Dans les versions -Ounchecked, la condition n'est pas évaluée, mais l'optimiseur peut supposer qu'elle serait évaluée à true. Le non-respect de cette hypothèse dans les versions -Ounchecked est une grave erreur de programmation.

affirmer

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

Affirmation traditionnelle de style C avec un message facultatif.

  1. Utilisez cette fonction pour les vérifications internes de l'intégrité qui sont actives pendant les tests mais qui n'affectent pas les performances du code d'expédition. Pour vérifier l'utilisation non valide dans les versions de version; voir la condition préalable.

  2. Dans les terrains de jeux et les builds -Onone (valeur par défaut pour la configuration de débogage de Xcode): si la condition est évaluée à false, arrêtez l'exécution du programme dans un état déboguable après l'impression du message.

  3. Dans les builds -O (valeur par défaut pour la configuration Release de Xcode), la condition n'est pas évaluée et il n'y a aucun effet
  4. Dans les versions -Ounchecked, la condition n'est pas évaluée, mais l'optimiseur peut supposer qu'elle serait évaluée à true. Le fait de ne pas satisfaire cette hypothèse dans les versions -Ounchecked est une erreur de programmation sérieuse
13e fantôme
la source
0

Je voulais juste ajouter mes 2 cents. Vous pouvez ajouter autant d'assertions dans votre code que vous le souhaitez. Vous pouvez envoyer votre code avec ces assertions. Swift n'évalue PAS ces blocs de code pour les applications de production. Ceux-ci ne sont évalués qu'en cas de mode débogage.

Ajout d'un lien de documentation

Joindre également une image de swift.org

entrez la description de l'image ici

Notez également que ce n'est pas le cas avec les conditions préalables. Le code livré avec des conditions préalables plantera et l'application se terminera si les conditions préalables ne sont pas évaluées comme vraies.

En bref, les assertions sont destinées au débogage, mais peuvent être expédiées sans impact sur la production. Les assertions seront évaluées en mode débogage mais pas en production.

Et

Les conditions préalables permettent de s'assurer que des événements inattendus ne se produisent pas dans l'environnement de production. Ces conditions sont évaluées et mettront fin à votre application au cas où elles seraient jugées fausses

Akshansh Thakur
la source