Разница между "предварительным условием" и "утверждать" в быстрой?

В чем разница между precondition(condition: Bool, message: String) а также assert(condition: Bool, message: String) в Свифте?

Они оба выглядят одинаково для меня. В каком контексте мы должны использовать один над другим?

6 ответов

Решение

assert для проверки работоспособности во время тестирования, тогда как precondition предназначен для защиты от вещей, которые, если они произойдут, будут означать, что ваша программа просто не сможет разумно продолжаться.

Так, например, вы можете положить assert на некоторых вычислениях, имеющих ощутимые результаты (скажем, в определенных пределах), чтобы быстро найти, есть ли у вас ошибка. Но вы не захотите использовать его с этим, так как результат за пределами допустимого может быть действительным и не критичным, поэтому не должен вызывать сбой вашего приложения (предположим, вы просто использовали его для отображения прогресса в индикаторе выполнения).

С другой стороны, проверка правильности индекса в массиве при извлечении элемента является precondition, Не существует разумного следующего действия для объекта массива при запросе недопустимого индекса, поскольку он должен возвращать необязательное значение.

Полный текст из документов (попробуйте щелкнув по опции assert а также precondition в Xcode):

непременное условие

Проверьте необходимое условие для продвижения вперед.

Используйте эту функцию для обнаружения условий, которые должны препятствовать выполнению программы даже в коде доставки.

  • В игровых площадках и -Onone сборках (по умолчанию для конфигурации отладки Xcode): если condition принимает значение false, останавливает выполнение программы в состоянии отладки после печати message,

  • In -O builds (по умолчанию для конфигурации выпуска Xcode): если condition оценивается как ложное, остановить выполнение программы.

  • В проверенных сборках, condition не оценивается, но оптимизатор может предположить, что он оценит true, Несоблюдение этого предположения в сборках -Ounchecked является серьезной ошибкой программирования.

утверждать

Традиционный стиль C утверждает с дополнительным сообщением.

Используйте эту функцию для внутренних проверок работоспособности, которые активны во время тестирования, но не влияют на производительность кода доставки. Проверять недопустимое использование в сборках Release; увидеть precondition,

  • В игровых площадках и -Onone сборках (по умолчанию для конфигурации отладки Xcode): если condition принимает значение false, останавливает выполнение программы в состоянии отладки после печати message,

  • В -O сборки (по умолчанию для конфигурации выпуска Xcode), condition не оценивается, и нет никаких эффектов.

  • В проверенных сборках, condition не оценивается, но оптимизатор может предположить, что он оценит true, Несоблюдение этого предположения в сборках -Ounchecked является серьезной ошибкой программирования.

Я нашел, что Свифт утверждает - отсутствующее руководство будет полезным

                        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

И из интересных дискуссий о Swift Evolution

- assert: проверка собственного кода на наличие внутренних ошибок

- предварительное условие: для проверки того, что ваши клиенты дали вам действительные аргументы.

Кроме того, вы должны быть осторожны с тем, что использовать, см. AssertionFailure и уровень оптимизации

precondition активен в режиме релиза, поэтому, когда вы отправляете свое приложение и предварительное условие не выполнено, приложение будет прервано.Assert по умолчанию работает только в режиме отладки.

Я нашел это отличное объяснение, когда использовать его на NSHipster:

Утверждения - это понятие, заимствованное из классической логики. В логике утверждения - это утверждения о предложениях в доказательстве. В программировании утверждения обозначают предположения, сделанные программистом относительно приложения в том месте, где они объявлены.

При использовании в качестве предварительных условий и постусловий, которые описывают ожидания относительно состояния кода в начале и в конце выполнения метода или функции, утверждения формируют контракт. Утверждения также можно использовать для принудительного выполнения условий во время выполнения, чтобы предотвратить выполнение при сбое определенных предварительных условий.

предварительное условие

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

Проверьте необходимое условие для продвижения вперед.

  1. Используйте эту функцию для обнаружения условий, которые должны препятствовать выполнению программы даже в коде доставки.
  2. В игровых площадках и сборках -Onone (по умолчанию для конфигурации отладки Xcode): если условие оценивается как ложное, остановите выполнение программы в состоянии отладки после печати сообщения.
  3. В сборках -O (по умолчанию для конфигурации выпуска Xcode): если условие оценивается как ложное, остановить выполнение программы.
  4. В сборках -Ounchecked условие не оценивается, но оптимизатор может предположить, что оно будет иметь значение true. Несоблюдение этого предположения в сборках -Ounchecked является серьезной ошибкой программирования.

утверждать

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

Традиционный стиль C утверждает с дополнительным сообщением.

  1. Используйте эту функцию для внутренних проверок работоспособности, которые активны во время тестирования, но не влияют на производительность кода доставки. Проверять недопустимое использование в сборках Release; Смотрите предварительное условие.

  2. В игровых площадках и сборках -Onone (по умолчанию для конфигурации отладки Xcode): если условие оценивается как ложное, остановите выполнение программы в состоянии отладки после печати сообщения.

  3. В сборках -O (по умолчанию для конфигурации выпуска XCode) условие не оценивается, и нет никаких эффектов
  4. В сборках -Ounchecked условие не оценивается, но оптимизатор может предположить, что оно будет иметь значение true. Неспособность удовлетворить это предположение в сборках -Ounchecked является серьезной ошибкой программирования

Просто хотел добавить свои 2 цента. Вы можете добавить в свой код столько утверждений, сколько захотите. Вы можете отправить свой код с этими утверждениями. Swift НЕ оценивает эти блоки кода для производственных приложений. Они оцениваются только в случае режима отладки.

Добавление ссылки на документацию

Также прикрепляю изображение с swift.org

Также обратите внимание, что это не относится к предварительным условиям. Код, поставляемый с предварительными условиями, выйдет из строя, и приложение прекратит работу, если предварительные условия не будут оценены как истинные.

Короче говоря, утверждения предназначены для отладки, но могут быть отправлены без ущерба для производства. Утверждения будут оцениваться в режиме отладки, но не в продакшене.

А также

Предварительные условия предназначены для предотвращения непредвиденных ситуаций в производственной среде. Эти условия оцениваются и завершат работу вашего приложения, если они будут признаны ложными.

iOS утверждает против предусловия против фатального

Главное правило:

      1. -O(-O, -Osize) - compile out(do not execute) `assert` and `assertionFailure`
2. -Ounchecked(as `SWIFT_OPTIMIZATION_LEVEL = -Ounchecked` or `SWIFT_DISABLE_SAFETY_CHECKS` = true) 
 2.1 set `condition: true` into `assert(condition: true)` and `precondition(condition: true)` that is why app is not terminated
 2.2 optimizer is free to assume that `assertionFailure` and `preconditionFailure` code are never called

Ошибка выглядит так

      Experiments2/ViewController.swift:20: Assertion failed: Some error
2022-12-11 15:17:28.772447+0200 Experiments2[95061:10414104] Experiments2/ViewController.swift:20: Assertion failed: Some error
  1. assert(condition: Bool, message: String)
  2. assertionFailure(message: String)
  3. precondition(condition: Bool, message: String)
  4. preconditionFailure(message: String) -> Never
  5. fatalError(message: String) -> Never

Neverсоздать предупреждение о времени сборки

      Will never be executed

[Уровень оптимизации (SWIFT_OPTIMIZATION_LEVEL)]

      |                                   | -Onone    |                    -O                     |                 -O -Ounchecked                    |                   -Ounchecked                     |
|--------------------------------   |:------:   |:----------------------------------------: |:----------------------------------------------:   |:----------------------------------------------:   |
| assert(condition: false)          |  TRUE     |       FALSE -O (compile out assert)       |          FALSE -O (compile out assert)            |      FALSE -Ounchecked (condition == true)        |
| assertionFailure                  |  TRUE     | FALSE -O (compiled out assertionFailure)  |    FALSE  -O (compile out assertionFailure)       | TRUE or FALSE -Ounchecked(may never be called)    |
| precondition(condition: false)    |  TRUE     |                   TRUE                    |      FALSE -Ounchecked (condition == true)        |      FALSE -Ounchecked (condition == true)        |
| preconditionFailure               |  TRUE     |                   TRUE                    | TRUE or FALSE -Ounchecked(may never be called)    | TRUE or FALSE -Ounchecked(may never be called)    |
| fatalError                        |  TRUE     |                   TRUE                    |                      TRUE                         |                      TRUE                         |
      TRUE - app is terminated
FALSE - app is not terminated
Другие вопросы по тегам