¿Diferencia entre "condición previa" y "afirmar" en rápido?

105

¿Cuál es la diferencia entre precondition(condition: Bool, message: String)y assert(condition: Bool, message: String)en Swift?

Ambos me parecen iguales. ¿En qué contexto debemos usar uno sobre el otro?

Chao Ruan
fuente

Respuestas:

125

assertes para verificaciones de cordura durante las pruebas, mientras que preconditiones para protegerse contra cosas que, si suceden, significarían que su programa simplemente no podría continuar de manera razonable.

Entonces, por ejemplo, puede poner un assertcálculo que tenga resultados razonables (dentro de algunos límites, por ejemplo), para encontrar rápidamente si tiene un error. Pero no querrá enviarlo con eso, ya que el resultado fuera del límite podría ser válido y no crítico, por lo que no debería bloquear su aplicación (suponga que solo la está usando para mostrar el progreso en una barra de progreso).

Por otro lado, comprobar que un subíndice en una matriz es válido cuando se busca un elemento es un precondition. No hay una acción siguiente razonable que deba realizar el objeto de matriz cuando se le solicite un subíndice no válido, ya que debe devolver un valor no opcional.

Texto completo de los documentos (intente hacer clic en la opción asserty preconditionen Xcode):

Condición previa

Compruebe una condición necesaria para avanzar.

Use esta función para detectar condiciones que deben evitar que el programa continúe incluso en el código de envío.

  • En patios de recreo y compilaciones -Onone (el valor predeterminado para la configuración de depuración de Xcode): si se conditionevalúa como falso, detiene la ejecución del programa en un estado depurable después de la impresión message.

  • En -O builds (el valor predeterminado para la configuración de lanzamiento de Xcode): si se conditionevalúa como falso, detiene la ejecución del programa.

  • En -Ounchecked construye, conditionno se evalúa, pero el optimizador puede asumir que sería evaluar a true. No cumplir con esa suposición en las compilaciones no comprobadas es un error de programación grave.

Afirmar

Aserción tradicional de estilo C con un mensaje opcional.

Utilice esta función para las comprobaciones de cordura internas que están activas durante las pruebas pero que no afectan el rendimiento del código de envío. Para comprobar el uso no válido en las versiones de la versión; ver precondition.

  • En patios de recreo y compilaciones -Onone (el valor predeterminado para la configuración de depuración de Xcode): si se conditionevalúa como falso, detiene la ejecución del programa en un estado depurable después de la impresión message.

  • In -O builds (el valor predeterminado para la configuración de lanzamiento de Xcode), conditionno se evalúa y no hay efectos.

  • En -Ounchecked construye, conditionno se evalúa, pero el optimizador puede asumir que sería evaluar a true. No cumplir con esa suposición en las compilaciones no comprobadas es un error de programación grave.

Velocidad aerodinámica
fuente
2
"Pero no querría enviarlo con eso, ya que el resultado fuera del límite podría ser válido y no crítico, por lo que no debería bloquear su aplicación", eso es muy vago para mí. ¿Podría incluir un ejemplo exacto? Quizás algún código.
Cariño
2
Respondiendo a su pregunta, personalmente utilizo afirmaciones para detectar cosas que simplemente no deberían suceder en mi compilación mientras lo escribo y lo pruebo. Imagine una declaración de guardia que lea JSON donde data["name"]no existe, pero debería. Tener una aserción dentro de la guardia..else {} me ayudaría a detectar mi error al fallar y llevarme al problema. De manera similar, si este código estuviera en producción, la aserción no bloquearía el programa, y ​​cualquier código de respaldo que usé ( return nil) se haría cargo.
Alec O
1
¿No debería comprobar el índice y no hacer nada en lugar de bloquear toda la aplicación?
Iulian Onofrei
Sí, debería comprobar el índice, pero todo el mundo se equivoca a veces, y el uso de afirmaciones le ayuda a darse cuenta de que debería haber comprobado el índice cuando lo olvidó.
Victor Engel
90

Encontré Swift afirma: el manual faltante es útil

                        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

Y de discusiones interesantes sobre Swift Evolution

- afirmar: verificar su propio código para detectar errores internos

- condición previa: para comprobar que sus clientes le han dado argumentos válidos.

Además, debe tener cuidado con lo que debe usar, consulte assertionFailure y Optimization Level

onmyway133
fuente
¿Puede explicar la diferencia entre el código propio y el cliente? En cuanto a cliente, ¿te refieres a insertar números donde se espera una cadena? ¿No debería tratarse con un simple manejo de errores?
Cariño
@Honey Creo que se refiere a los argumentos / resultados de las llamadas a la API de red o los propios complementos del cliente.
Chen Li Yong
El cliente sería alguien que usa su código, digamos que está escribiendo una biblioteca y un programador pasa datos no válidos. No querrá continuar con gracia, ya que podría considerarse un error de programación grave. Probablemente nunca debería fallar en datos de API de red no válidos, ya que eso es muy inútil para el usuario.
Bompf
@ onmyway133: Desde Xcode QuickHelp, creo que precondition()y preconditionFailure()estamos teniendo los mismos comportamientos . La diferencia entre estas funciones es: preconditionnecesita una condición en el interior, mientras que preconditionFailuresimplemente se tira.
nahung89
12

El preconditionestá activo en el modo de lanzamiento, por lo que cuando envía su aplicación y falla la condición previa, la aplicación terminará. Assertfunciona solo en modo de depuración por defecto.

Encontré esta gran explicación sobre cuándo usarlo en NSHipster:

Las afirmaciones son un concepto tomado de la lógica clásica. En lógica, las afirmaciones son declaraciones sobre proposiciones dentro de una prueba. En programación, las afirmaciones denotan suposiciones que el programador ha hecho sobre la aplicación en el lugar donde se declaran.

Cuando se utilizan en la capacidad de precondiciones y poscondiciones, que describen expectativas sobre el estado del código al principio y al final de la ejecución de un método o función, las afirmaciones forman un contrato. Las afirmaciones también se pueden utilizar para hacer cumplir las condiciones en tiempo de ejecución, con el fin de evitar la ejecución cuando fallan ciertas condiciones previas.

Greg
fuente
Las afirmaciones se pueden habilitar y deshabilitar mediante un indicador de compilador; pueden estar activos en el código enviado.
Pétur Ingi Egilsson
6

condición previa

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

Compruebe una condición necesaria para avanzar.

  1. Use esta función para detectar condiciones que deben evitar que el programa continúe incluso en el código de envío.
  2. En patios de recreo y compilaciones -Onone (el valor predeterminado para la configuración de depuración de Xcode): si la condición se evalúa como falsa, detenga la ejecución del programa en un estado depurable después de imprimir el mensaje.
  3. In -O builds (el valor predeterminado para la configuración de lanzamiento de Xcode): si la condición se evalúa como falsa, detenga la ejecución del programa.
  4. En las compilaciones no comprobadas, la condición no se evalúa, pero el optimizador puede asumir que se evaluaría como verdadera. No cumplir con esa suposición en las compilaciones no comprobadas es un error de programación grave.

afirmar

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

Aserción tradicional de estilo C con un mensaje opcional.

  1. Utilice esta función para las comprobaciones de cordura internas que están activas durante las pruebas pero que no afectan el rendimiento del código de envío. Para comprobar el uso no válido en versiones de versiones; ver condición previa.

  2. En patios de recreo y compilaciones -Onone (el valor predeterminado para la configuración de depuración de Xcode): si la condición se evalúa como falsa, detenga la ejecución del programa en un estado depurable después de imprimir el mensaje.

  3. En -O compilaciones (el valor predeterminado para la configuración de lanzamiento de Xcode), la condición no se evalúa y no hay efectos
  4. En las compilaciones no comprobadas, la condición no se evalúa, pero el optimizador puede asumir que se evaluaría como verdadera. No satisfacer esa suposición en las compilaciones no comprobadas es un error de programación grave
13o fantasma
fuente