web-dev-qa-db-fra.com

Quel est l'intérêt de NSAssert, en réalité?

Je dois poser cette question, car: La seule chose que je reconnaisse, c'est que si l'assertion échoue, l'application se bloque. Est-ce la raison pour laquelle NSAssert? Ou quoi d'autre est l'avantage? Et est-il juste de placer un NSAssert juste au-dessus de toute hypothèse que je formule dans le code, comme une fonction qui ne devrait jamais recevoir un paramètre -1 mais un -0,9 ou -1,1?

153
HelloMoon

Assert est de s'assurer qu'une valeur est ce qu'elle est supposée être. Si une assertion échoue, cela signifie que quelque chose a mal tourné et que l'application se ferme. Une des raisons d'utiliser assert serait si vous avez une fonction qui ne se comportera pas ou créera de très mauvais effets secondaires si l'un des paramètres qui lui est transmis ne correspond pas exactement à une valeur (ou à une plage de valeurs) que vous pouvez mettre en forme. Assurez-vous que cette valeur correspond à ce que vous attendez et si ce n'est pas le cas, alors quelque chose ne va vraiment pas et l'application se ferme. Assert peut être très utile pour le débogage/les tests unitaires, ainsi que lorsque vous fournissez des cadres pour empêcher les utilisateurs de faire des choses "pervers".

298
Daniel

Je ne peux pas vraiment parler à NSAssert, mais j'imagine que cela fonctionne de la même manière que C's assert ().

assert () est utilisé pour imposer un contrat sémantique dans votre code. Qu'est-ce que cela signifie, demandez-vous?

Eh bien, c'est comme vous l'avez dit: si vous avez une fonction qui ne devrait jamais recevoir -1, vous pouvez avoir assert () appliquer cela:

 void gimme_positive_ints (int i) {
 assert (i> 0); 
} 

Et maintenant, vous verrez quelque chose comme ceci dans le journal des erreurs (ou STDERR):

 L'assertion i> 0 a échoué: exemple de fichier.c, ligne 2 

Ainsi, non seulement il protège contre les entrées potentiellement mauvaises, mais il les enregistre de manière utile et standard.

Oh, et au moins dans C, assert () était une macro, vous pouvez donc redéfinir assert () en tant que non-op dans votre code de version. Je ne sais pas si c'est le cas avec NSAssert (ou même assert () plus), mais il était très utile de compiler ces vérifications.

20
Mando Escamilla

Mis à part ce que tout le monde a dit ci-dessus, le comportement par défaut de NSAssert() (contrairement à assert() de C) consiste à lever une exception que vous pouvez capturer et gérer. Par exemple, Xcode le fait.

17
Jens Ayton

NSAssert vous donne plus que de planter l'application. Il vous indique la classe, la méthode et la ligne où l'assertion s'est produite. Toutes les assertions peuvent également être facilement désactivées à l'aide de NS_BLOCK_ASSERTIONS. Le rendant ainsi plus approprié pour le débogage. D'autre part, lancer un NSException ne bloque que l'application. Il ne dit pas non plus sur l'emplacement de l'exception et ne peut pas être désactivé si simplement. Voyez la différence dans les images ci-dessous.

L'application se bloque car une assertion génère également une exception, car documentation NSAssert indique:

Lorsqu'il est appelé, un gestionnaire d'assertion imprime un message d'erreur incluant les noms de méthode et de classe (ou le nom de la fonction). Il déclenche ensuite une exception NSInternalInconsistencyException.

NSAssert:

Logs after an assertion

NSException:

Logs after an exception

15

Pour clarifier, comme quelqu'un l'a mentionné mais pas complètement expliqué, la raison pour avoir et utiliser des assertions au lieu de simplement créer du code personnalisé (faire des ifs et lever une exception pour les données incorrectes, par exemple) est que les assertions DEVRAIENT être désactivés pour les applications de production.

Lors du développement et du débogage, les assertions sont activées pour que vous puissiez détecter les erreurs. Le programme s'arrête lorsqu'une assertion est évaluée comme fausse. Mais, lors de la compilation pour la production, le compilateur omet le code d'assertion et RENDRE VOTRE PROGRAMME PLUS RAPIDE. D'ici là, j'espère que vous avez corrigé tous les bugs. Si votre programme a encore des bogues en production (lorsque les assertions sont désactivées et que le programme "saute" les assertions), votre programme finira probablement par planter à un autre moment.

Dans l'aide de NSAssert: "Les assertions sont désactivées si la macro de préprocesseur NS_BLOCK_ASSERTIONS est définie." Donc, il suffit de mettre la macro dans votre cible de distribution [uniquement].

9
Ohad Kravchick

NSAssert (et son équivalent stdlib assert) doivent détecter les erreurs de programmation au cours du développement. Vous ne devriez jamais avoir une assertion qui échoue dans une application de production (publiée). Vous pouvez donc affirmer que vous ne transmettez jamais un nombre négatif à une méthode qui nécessite un argument positif. Si l'assertion échoue pendant le test, vous avez un bogue. Si, toutefois, la valeur transmise est entrée par l'utilisateur, vous devez effectuer une validation correcte de l'entrée plutôt que de vous fier à l'assertion en production (vous pouvez définir une #define pour les versions validées qui désactive NSAssert*.

6
Barry Wark

Il est intéressant de souligner que, outre la vérification à l'exécution, la programmation des assertions est une fonction importante utilisée lors de la conception de votre code par contrat.

Plus d'informations sur le sujet de l'assertion et de la conception par contrat sont disponibles ci-dessous:

Assertion (développement de logiciel)

Conception par contrat

Programmation avec assertions

Conception par contrat, par exemple [Broché]

3
Boon

Les assertions sont couramment utilisées pour imposer l'utilisation prévue d'une méthode ou d'un élément de logique particulier. Supposons que vous écriviez une méthode qui calcule la somme de deux entiers supérieurs à zéro. Pour vous assurer que la méthode a toujours été utilisée comme prévu, vous devrez probablement indiquer le test qui teste cette condition.

Réponse courte: Ils imposent que votre code ne soit utilisé que comme prévu.

3
Lounges

Pour répondre pleinement à sa question, l’intérêt de tout type d’assert est d’aider au débogage. Il est plus utile d’attraper les erreurs à leur source, puis de les attraper dans le débogueur quand elles provoquent des plantages.

Par exemple, vous pouvez transmettre une valeur à une fonction qui attend des valeurs dans une certaine plage. La fonction peut stocker la valeur pour une utilisation ultérieure et lors d'une utilisation ultérieure, l'application se bloque. La pile d'appels vue dans ce scénario n'indiquerait pas la source de la valeur incorrecte. Il vaut mieux attraper la mauvaise valeur car elle intervient pour savoir qui passe la mauvaise valeur et pourquoi.

2
Robert Hawkey