ios - Diseño por Contrato en Swift
design-by-contract (2)
¿Swift proporciona un soporte nativo de diseño por contrato? Entiendo que se puede hacer durante el tiempo de ejecución a través de aserciones, pero ¿podría hacerse durante el tiempo de compilación? O, ¿hay algún plugin / librería externo que haga esto?
EDITAR
Al decir "durante el tiempo de compilación Diseño por contrato", no quiero decir que la biblioteca sea un analizador estático todopoderoso que C # tiene . Sería suficiente para mí si fuera algo como el que iContract proporciona para Java. Veamos un ejemplo:
Un código DBC para la evaluación de la raíz cuadrada en Java usando iContract podría escribirse como:
/**
* @pre f >= 0.0
* @post Math.abs((return * return) - f) < 0.001
*/
public float sqrt(float f) { ... }
Ahora, esto mantiene mi contrato como parte de mi especificación de la API en lugar de una parte de su implementación, que creo que es una forma más limpia. La persona que llama sabrá cuáles son sus responsabilidades y la persona que llama está estableciendo sus expectativas, todo de una manera más clara. ¿Tenemos algo como esto en Swift?
TL; DR
Como @Tommy señala en los comentarios de tu pregunta, parece que la respuesta simple y sencilla a tu pregunta es "No, el tiempo de compilación DbC no es actualmente una característica de Swift".
¿Qué hay integrado en este momento?
Para el soporte integrado para este tipo de estrategia de diseño, actualmente tengo que mirar el tiempo de ejecución, me temo. Parece que Swift prefiere las aserciones en tiempo de ejecución para hacer cumplir las condiciones previas en la actualidad, aunque el lenguaje parece poner más énfasis en la seguridad en el momento de la compilación (más sobre esto más adelante). Las funciones globales assert
, assertionFailure
, precondition
y preconditionFailure
están diseñadas para ser rociadas generosamente en todo el código sin afectar el rendimiento de la versión de lanzamiento.
Las pruebas unitarias son, por supuesto, otra estrategia para verificar que los contratos de API se cumplen, pero estos deben ser pensados e implementados manualmente, y por lo tanto son propensos a errores.
Otra cosa que quizás es interesante observar es que entre la mejor documentación de soporte de comentarios de Swift 2, "require", "precondition" y "postcondition" son palabras clave de marcado reconocidas, de manera que se muestran prominentemente en la documentación de ayuda rápida:
/// - precondition: f >= 0.0
/// - postcondition: abs((return * return) - f) < 0.001
/// - returns: The square root of `f`.
func sqrt(f: Float) -> Float { ... }
Entonces, este énfasis en poder proporcionar una buena documentación para los contratos de API significa que el equipo de desarrollo de Swift se preocupa claramente por ello, y esto es un punto muerto hasta que incorporan algo en la sintaxis en el futuro, o significa que piensan ¿Este tipo de información pertenece a la documentación? Postulación inútil, tal vez. En cualquier caso, a pesar del hecho de que no es la DbC adecuada, creo que es una cosa que hay que tener en cuenta en este momento.
¿Qué puedo hacer al respecto ahora?
Con Objective-C, las macros podrían usarse para implementar básicamente DbC básica, sin embargo, la falta de macros en Swift significa que tendrías que recurrir a algún tipo de envoltorio basado en funciones / genéricos, que creo que se vería como un cuerpo realmente torpe.
El soporte de Xcode para agregar scripts personalizados a las fases de compilación de un objetivo, tal como lo sugiere @JonShier en los comentarios, es quizás lo más cercano a DbC automático y útil sin esperar a que el idioma (tal vez / tal vez no) introduzca tal característica. Con las palabras clave de marcado de documentación antes mencionadas, un script que analiza los comentarios de documentación para crear pruebas unitarias podría incorporarse retrospectivamente a proyectos con solo una pequeña cantidad de aprendizaje / esfuerzo por parte del usuario. Como dices, creo que esto podría hacer un proyecto muy interesante!
¿Será una característica incorporada en el futuro?
No está claro si la DbC nativa se incorporará o no a Swift en el futuro. Podría decirse que es una característica que se adapta bien a la misión del lenguaje Swift, es decir, promueve un código más seguro y reduce el riesgo de errores de tiempo de ejecución. Si se convierte en parte del lenguaje, sugeriría que sea más probable que los veamos aparecer como atributos de declaración que como marcado de comentario interpretado, por ejemplo:
@contract(
precondition = f >= 0.0,
postcondition = abs((return * return) - f) < 0.001
)
func sqrt(f: Float) -> Float { ... }
(¡Pero eso es solo una especulación, y de nada nos sirve ahora!)
Por lo que sé del tema, la DbC en tiempo de compilación puede ser un problema muy complejo. Pero quién sabe ... el trabajo en el analizador estático Clang ha demostrado que existe un deseo subyacente de arrastrar la identificación de los errores de tiempo de ejecución al tiempo de compilación. ¿Quizás este es el problema perfecto para poner en funcionamiento un analizador estático Swift en el futuro?
No lo soy si esto es lo que estás buscando, pero aquí hay una sugerencia que podrías probar. Si desea definir un protocolo donde pueda definir la firma de la función sqrt y dejar la implementación para que otras clases o estructuras lo implementen en un momento posterior, podría hacer algo como el código a continuación:
Nota: el sqrtf solo está usando la implementación del sistema aquí.
public protocol Math {
func sqrtf(f: Float) -> Float
}
struct NativeMath: Math {
func sqrtf(f: Float) -> Float {
return sqrt(f)
}
}
println(NativeMath().sqrtf(2))