В чому сенс NSAssert?


155

Я маю це запитати, оскільки: Єдине, що я визнаю, це те, що якщо твердження не вдасться, додаток виходить з ладу. Це причина, чому слід використовувати NSAssert? Або яка ще користь від цього? І чи правильно розміщувати NSAssert вище, ніж будь-яке припущення, яке я вказую в коді, як функція, яка ніколи не повинна отримувати -1 як парам, але може бути -0,9 або -1,1?

Відповіді:


300

Assert - це переконатися, що значення є таким, яким воно повинно бути. Якщо твердження не вдається, це означає, що щось пішло не так, і додаток закривається. Однією з причин використовувати assert буде, якщо у вас є якась функція, яка не буде вести себе або створюватиме дуже погані побічні ефекти, якщо один з параметрів, переданих їй, не є якимось певним значенням (або діапазоном значень), ви можете поставити заяву, щоб зробити впевнений, що цінність - це те, чого ви очікуєте, і якщо це не так, то щось насправді не так, і додаток закривається. Assert може бути дуже корисним для налагодження / тестування одиниць, а також коли ви надаєте рамки, які не дозволяють користувачам робити "злі" речі.


9
Ви повинні вийняти NSAssert для звільнення. Для цього є прапор часу на компіляцію.
Barry Wark

127
> Ви повинні вийняти NSAssert для випуску. Це дискусійно. Я завжди випускаю свої програми з увімкненими твердженнями, і це стандартна практика для багатьох програм, Apple, наприклад, робить це. Як тільки у вашій програмі виявлено ненормальний стан, ви повинні вийти з ладу. Ви можете отримати трасування стека, де сталася помилка, тоді як якщо ви відключите твердження, ви можете зіпсувати пам'ять та / або дані користувача, і проблему буде важко налагодити.
Майк Веллер

18
Зауважте, що XCode 4 має NS_BLOCK_ASSERTIONS, визначені за замовчуванням у конфігураціях випуску. Я думаю, якщо ви не зміните, що ваш звільнений код не буде містити NSAssert: s.
Джоні

16
Якщо я правильно розумію, який сенс залишати їх (у версії до випуску)? Чому б не замінити NSAssert заявою if, а якщо (трапиться щось жахливе), то поінформуйте користувача (або зробіть щось, що знаходиться під вашим контролем), а не просто вийти з ладу і залишити користувача, цікаво, що сталося ... Або я щось пропускаю?
Гік

11
Марно витрачати час розробника на те, щоб піти шляхом кожного виняткового випадку, який не повинен відбуватися за звичайних обставин. Це передбачає продумання відповідних способів інформування користувача про кожну з них та / або зробити додаток достатньо надійним, щоб очікувати роботу після їх появи. Більш практичний підхід - це збій програми та виправлення помилки, виявленої у звіті про збій, та випуск нової версії. Сказавши це, важливо переконатися у відсутності втрати даних у будь-якій такій ситуації. Це все ж слід забезпечити, але це набагато менше роботи.
trss

20

Я не можу реально розмовляти з NSAssert, але думаю, що це працює аналогічно твердженню C ().

assert () використовується для забезпечення семантичного контракту у вашому коді. Що це означає, запитаєте ви?

Ну, це як ви сказали: якщо у вас є функція, яка ніколи не повинна отримувати -1, ви можете стверджувати () примусово виконувати таке:

void gimme_positive_ints (int i) {
  стверджувати (i> 0);
}

А тепер ви побачите щось подібне в журналі помилок (або STDERR):

Твердження i> 0 не вдалося: файл example.c, рядок 2

Таким чином, він не тільки захищає від потенційно поганих входів, але й записує їх корисним, стандартним способом.

О, і, принаймні, у C assert () був макросом, тому ви можете переосмислити assert () як неоперативний код у своєму випуску. Я не знаю, чи так це з NSAssert (або навіть затверджувати () більше), але це було дуже корисно для складання цих чеків.


2
Так, NSAssert також є макросом.
Мартін Вікман

18

NSAssertдає більше, ніж просто збій програми. Він повідомляє вам клас, метод та рядок, де відбулося твердження. Усі твердження також можна легко деактивувати за допомогою NS_BLOCK_ASSERTIONS. Таким чином, роблячи його більш придатним для налагодження. З іншого боку, викидання NSExceptionєдиного збою додаток. Він також не повідомляє про місцезнаходження винятку, і його не можна відключити так просто. Дивіться різницю на зображеннях нижче.

Додаток виходить з ладу, оскільки твердження також спричиняє виняток, оскільки в документації NSAssert зазначено:

Після виклику обробник твердження друкує повідомлення про помилку, що включає назви методу та класів (або ім'я функції). Потім виникає виняток NSInternalInconsistencyException.

NSAssert:

Журнали після твердження

NSException:

Журнали після виключення


NSExceptionНадає безліч можливостей для налаштування вихідного сигналу він повертається по reasonі userInfoпараметрам. Немає причини, щоб ви не могли додати назву класу, селектор, інформацію про рядки та інше, що вам потрібно додати, щоб допомогти з налагодженням. IMHO, ви використовуєте NSAssertдля налагодження під час розробки, але відключаєте їх для доставки; ви кидаєте, NSExceptionякщо хочете залишити твердження в коді доставки.
markeissler

17

Крім того, що всі говорили вище, поведінка за замовчуванням NSAssert()(на відміну від C assert()) - це викид винятку, який можна зловити і впоратися. Наприклад, Xcode робить це.


Чи є більше про те, як ми можемо зловити та поправити виняток?
Gon

1
Винятки, що стосуються какао, НЕ фактично "підлягають споживанню та обробці". Якщо контроль проходить через функцію яблука взагалі в будь-якому місці дерева викликів, поведінка не визначена. Винятки складаються виключно для повідомлення про помилки (ака, критерії та ін.), А не для загального використання, як у Java.
Михайло

9

Просто для уточнення, як хтось згадував, але не повністю пояснений, причиною використання та використання тверджень замість того, щоб просто створити спеціальний код (наприклад, робити ifs та створити виняток для поганих даних), є те, що ствердження повинні бути відключені для виробничих додатків.

Розробляючи та налагоджуючи, увімкнено твердження, що дозволяють вам виявляти помилки. Програма зупиняється, коли твердження буде оцінено як помилкове. Але, компілюючи для виробництва, компілятор опускає код твердження і фактично ЗРОБИТИ СВОЮ ПРОГРАМУ ШВИДКО швидше. До того часу, сподіваємось, ви виправили всі помилки. Якщо у вашій програмі все ще є помилки під час виробництва (коли твердження вимкнено і програма "пропускає" твердження), ваша програма, ймовірно, закінчиться збоєм у якийсь інший момент.

З довідки NSAssert: "Твердження вимкнено, якщо визначено макрос препроцесора NS_BLOCK_ASSERTIONS." Отже, просто поставте макрос у свою ціль розповсюдження [лише].


6

NSAssert(та його еквівалент stdlib assert) мають виявляти помилки програмування під час розробки. У вас ніколи не повинно бути твердження, яке не дає змоги у виробництві (випущеному) додатку. Тож ви можете стверджувати, що ви ніколи не передаєте від'ємне число методу, який вимагає позитивного аргументу. Якщо твердження колись виходить з ладу під час тестування, у вас є помилка. Якщо, однак, передане значення введено користувачем, вам потрібно зробити належну перевірку введення, а не покладатися на твердження у виробництві (ви можете встановити #define для версій версій, які вимикаються NSAssert*.


2
+1, тому що ваша відповідь має для мене найбільш сенс! Використання NSAssert має більше сенсу, якщо його для розробки використовувати, а не після виходу. Користувач, який вводить значення, яке не дозволено, повинен супроводжуватися помилкою інтерфейсу користувача, а не NSAssert, що завершує роботу програми. Туман очистився!
pnizzle

3

Твердження зазвичай використовуються для забезпечення наміченого використання певного методу чи логічного фрагмента. Скажімо, ви писали метод, який обчислює суму двох більших за нуль цілих чисел. Для того, щоб переконатися, що метод завжди використовувався за призначенням, ви, ймовірно, поставите твердження, яке перевіряє цю умову.

Коротка відповідь: вони вимагають, щоб ваш код використовувався лише за призначенням.


3

Варто зазначити, що окрім перевірки часу виконання, програмування затвердження є важливою умовою, яка використовується при розробці коду за контрактом.

Більше інформації про предмет затвердження та оформлення за контрактом можна знайти нижче:

Затвердження (розробка програмного забезпечення)

Дизайн за контрактом

Програмування з твердженнями

Дизайн за контрактом, за прикладом [М'яка обкладинка]


2

Щоб повністю відповісти на його питання, суть будь-якого типу твердження полягає у допомозі налагодження. Цінніше ловити помилки біля їх джерела, а потім ловити їх у відладчику, коли вони викликають збої.

Наприклад, ви можете передавати значення функції, яка очікує значення в певному діапазоні. Функція може зберігати значення для подальшого використання, а для подальшого використання додаток збоїв. Стек викликів, що бачиться в цьому сценарії, не відображатиме джерело поганого значення. Краще спіймати погану цінність, як з’ясовується, щоб з’ясувати, хто передає погану цінність і чому.


-3

NSAssertзробити збій програми, коли він відповідає умові. Якщо це не відповідає умові, виконуються наступні заяви. Знайдіть EX нижче:

Я просто створив додаток, щоб перевірити, що це за завдання NSAssert:

    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self testingFunction:2];
}

-(void)testingFunction: (int)anNum{
    // if anNum < 2 -> the app will crash
    // and the NSLog statement will not execute
    // that mean you cannot see the string: "This statement will execute when anNum < 2"
    // into the log console window of Xcode
    NSAssert(anNum >= 2, @"number you enter less than 2");
    // If anNum >= 2 -> the app will not crash and the below 
    // statement will execute
    NSLog(@"This statement will execute when anNum < 2");
}

у мій код додаток не вийде з ладу. І тестовий випадок:

  • anNum > = 2 -> Додаток не вийде з ладу, і ви побачите рядок журналу: "Цей оператор виконується, коли anNum <2", у вікно консолі журналу outPut
  • anNum <2 -> Додаток вийде з ладу, і ви не можете побачити рядок журналу: "Цей оператор виконується, коли anNum <2"

1
У вас це навпаки. "NSAssert робить збій програми, коли він відповідає умові. Якщо він не відповідає умові, виконуються наступні заяви". NSAssert вибиває програму, якщо вона НЕ відповідає умові, і виконує нормально, якщо вона відповідає умові.
Джо Там

Додаток виходить з ладу та повідомляє журнал, коли воно не відповідає умові, інакше воно виконується далі.
Правін С.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.