Como ingeniero de software, escribo mucho código para productos industriales. Cosas relativamente complicadas con clases, hilos, algunos esfuerzos de diseño, pero también algunos compromisos para el rendimiento. Realizo muchas pruebas, y estoy cansado de probar, así que me interesé en las herramientas de prueba formales, como Coq, Isabelle ... ¿Podría usar una de estas para probar formalmente que mi código está libre de errores y listo? ¿con eso? - pero cada vez que reviso una de estas herramientas, me alejo convencido de que son utilizables para la ingeniería de software cotidiana. Ahora, eso solo podría ser yo, y estoy buscando consejos / opiniones / ideas sobre eso :-)
Específicamente, tengo la impresión de que hacer que una de estas herramientas funcione para mí requeriría una gran inversión para definir adecuadamente al probador los objetos, métodos ... del programa en consideración. Entonces me pregunto si el probador no se quedaría sin energía dado el tamaño de todo con lo que tendría que lidiar. O tal vez tendría que deshacerme de los efectos secundarios (esas herramientas de prueba parecen funcionar realmente bien con lenguajes declarativos), y me pregunto si eso daría como resultado un "código probado" que no podría usarse porque no sería rápido o suficientemente pequeño. Además, no tengo el lujo de cambiar el idioma con el que trabajo, tiene que ser Java o C ++: no puedo decirle a mi jefe que voy a codificar en OXXXml de ahora en adelante, porque es el único idioma en que puedo probar la exactitud del código ...
¿Podría alguien con más experiencia en herramientas de prueba formal comentar? Nuevamente, me ENCANTARÍA usar una herramienta de prueba formal, creo que son geniales, pero tengo la impresión de que están en una torre de marfil que no puedo alcanzar desde la zanja de Java / C ++ ... (PS: I también LOVE Haskell, OCaml ... no me hagas una idea equivocada: soy un fanático de los lenguajes declarativos y las pruebas formales, solo estoy tratando de ver cómo podría hacer que esto sea realmente útil para la ingeniería de software)
Actualización: Dado que esto es bastante amplio, intentemos las siguientes preguntas más específicas: 1) ¿hay ejemplos de uso de probadores para probar la corrección de los programas industriales Java / C ++? 2) ¿Coq sería adecuado para esa tarea? 3) Si Coq es adecuado, ¿debería escribir el programa en Coq primero y luego generar C ++ / Java desde Coq? 4) ¿Podría este enfoque manejar optimizaciones de subprocesos y rendimiento?
Respuestas:
Trataré de dar una respuesta sucinta a algunas de sus preguntas. Tenga en cuenta que este no es estrictamente mi campo de investigación, por lo que parte de mi información puede estar desactualizada / incorrecta.
Hay muchas herramientas que están específicamente diseñadas para probar formalmente las propiedades de Java y C ++.
Sin embargo, necesito hacer una pequeña digresión aquí: ¿qué significa probar la corrección de un programa? El verificador de tipo Java prueba una propiedad formal de un programa Java, a saber, que ciertos errores, como agregar ay
float
anint
, ¡nunca pueden ocurrir! Me imagino que está interesado en propiedades mucho más fuertes, a saber, que su programa nunca puede entrar en un estado no deseado, o que la salida de una determinada función se ajusta a una determinada especificación matemática. En resumen, hay un amplio gradiente de lo que puede significar "probar que un programa es correcto", desde simples propiedades de seguridad hasta una prueba completa de que el programa cumple con una especificación detallada.Ahora voy a suponer que está interesado en probar propiedades sólidas sobre sus programas. Si está interesado en las propiedades de seguridad (su programa no puede alcanzar un cierto estado), entonces, en general, parece que el mejor enfoque es la verificación del modelo . Sin embargo, si desea especificar completamente el comportamiento de un programa Java, su mejor opción es utilizar un lenguaje de especificación para ese idioma, por ejemplo, JML . Existen dichos lenguajes para especificar el comportamiento de los programas en C, por ejemplo ACSL , pero no sé acerca de C ++.
Una vez que tenga sus especificaciones, debe probar que el programa cumple con esa especificación.
Para esto, necesita una herramienta que tenga una comprensión formal tanto de su especificación como de la semántica operativa de su lenguaje (Java o C ++) para expresar el teorema de adecuación , es decir, que la ejecución del programa respeta la especificación.
Esta herramienta también debería permitirle formular o generar la prueba de ese teorema. Ahora, ambas tareas (especificar y probar) son bastante difíciles, por lo que a menudo se separan en dos:
Una herramienta que analiza el código, la especificación y genera el teorema de adecuación. Como Frank mencionó, Krakatoa es un ejemplo de dicha herramienta.
Una herramienta que demuestra el teorema (s), de forma automática o interactiva. Coq interactúa con Krakatoa de esta manera, y hay algunas herramientas automatizadas poderosas como Z3 que también se pueden usar.
Un punto (menor): hay algunos teoremas que son demasiado difíciles de probar con métodos automáticos, y se sabe que los probadores de teoremas automáticos ocasionalmente tienen errores de solidez que los hacen menos confiables. Esta es un área donde Coq brilla en comparación (¡pero no es automático!).
Si desea generar código Ocaml, definitivamente escriba primero en Coq (Gallina), luego extraiga el código. Sin embargo, Coq es terrible para generar C ++ o Java, si es posible.
¿Pueden las herramientas anteriores manejar problemas de subprocesamiento y rendimiento? Probablemente no, los problemas de rendimiento y subprocesos se manejan mejor con herramientas diseñadas específicamente, ya que son problemas particularmente difíciles. No estoy seguro de tener alguna herramienta para recomendar aquí, aunque el proyecto PolyNI de Martin Hofmann parece interesante.
En conclusión: la verificación formal de los programas Java y C ++ del "mundo real" es un campo grande y bien desarrollado, y Coq es adecuado para partes de esa tarea. Puede encontrar una descripción general de alto nivel aquí, por ejemplo.
fuente
Me gustaría mencionar tres aplicaciones notables de métodos formales / herramientas de verificación formal en la industria o sistemas reales no triviales. Tenga en cuenta que tengo poca experiencia en este tema y solo los aprendo leyendo documentos.
La herramienta de código abierto Java Pathfinder (JPF para abreviar) lanzada por la NASA en 2005 es un sistema para verificar programas ejecutables de código de bytes Java (ver Java Pathfinder @ wiki ). Se ha utilizado para detectar inconsistencias en el software ejecutivo para el K9 Rover en la NASA Ames.
Este documento: Uso de la verificación de modelos para encontrar errores graves del sistema de archivos @ OSDI'04 muestra cómo usar la verificación de modelos para encontrar errores graves en los sistemas de archivos. Un sistema llamado FiSC se aplica a tres sistemas de archivos ampliamente utilizados y muy probados: ext3, JFS y ReiserFS, y se encuentran 32 errores graves. Ganó el Premio al Mejor Papel.
Este documento: Cómo Amazon Web Services utiliza métodos formales @ CACM'15 describe cómo AWS aplica métodos formales a sus productos como S3, DynamoDB, EBS y el administrador de bloqueo distribuido interno. Se centra en la herramienta TLA + de Lamport . Por cierto, Lamport ha usado intensamente su propia caja de herramientas TLA. A menudo da una verificación formal (bastante completa) en TLA de los algoritmos / teoremas propuestos por él mismo (así como por sus coautores) en los apéndices de los documentos.
fuente
Una especificación formal de un programa es (más o menos) un programa escrito en otro lenguaje de programación. Como resultado, la especificación ciertamente incluirá sus propios errores.
La ventaja de la verificación formal es que, dado que el programa y la especificación son dos implementaciones separadas, sus errores serán diferentes. Pero no siempre: una fuente común de errores, los casos pasados por alto, a menudo coincidirán. Por lo tanto, la verificación formal no es una panacea: aún puede pasar por alto un número no trivial de errores.
Una desventaja de la verificación formal es que puede imponer algo como el doble del costo de implementación, probablemente más (necesita un especialista en especificación formal y necesita usar las herramientas más o menos experimentales que vienen con él; eso no será barato )
Supongo que configurar casos de prueba y andamios para ejecutarlos automáticamente sería un mejor uso de su tiempo.
fuente
La verificación formal ahora es posible para los programas escritos en un subconjunto de C ++ diseñado para sistemas integrados críticos para la seguridad. Consulte http://eschertech.com/papers/CanCPlusPlusBeMadeAsSafeAsSpark.ppt para una breve presentación, y http://eschertech.com/papers/CanCPlusPlusBeMadeAsSafeAsSpark.pdf para obtener el artículo completo.
fuente
Haces algunas preguntas diferentes. Estoy de acuerdo en que parece que los métodos formales de verificación para aplicaciones industriales / comerciales no son tan comunes. ¡Sin embargo, uno debe darse cuenta de que muchos compiladores incorporan principios de "verificación formal" para determinar la corrección del programa! de alguna manera, si usa un compilador moderno, está utilizando gran parte del estado del arte en la verificación formal.
Usted dice "Estoy cansado de las pruebas" pero la verificación formal no es realmente un sustituto de las pruebas. en cierto modo es una variación en las pruebas.
Mencionas Java. Hay muchos métodos avanzados de verificación formal integrados en un programa de verificación de Java llamado FindBugs que, de hecho, pueden ejecutarse en grandes bases de código. Tenga en cuenta que aparecerá tanto "falsos positivos como falsos negativos" y los resultados deben ser revisados / analizados por un desarrollador humano. Pero tenga en cuenta que incluso si no está produciendo defectos funcionales reales, generalmente presenta "antipatrones" que de todos modos deben evitarse en el código.
No hace más mención de su aplicación particular que no sea "industrial". La verificación formal en la práctica tiende a depender de la aplicación particular.
Las técnicas de verificación formal parecen ser ampliamente utilizadas en EE para probar la corrección del circuito, por ejemplo, en el diseño de microprocesadores.
Aquí hay un ejemplo de una encuesta de herramientas de verificación formal en el campo de EE realizada por Lars Philipson .
fuente
Quizás, un verificador de modelos puede ser útil.
http://alloytools.org/documentation.html Alloy es un verificador de modelos.
Una buena presentación que explica el concepto de verificación de modelos con Alloy: https://www.youtube.com/watch?v=FvNRlE4E9QQ
En la misma familia de herramientas vienen las 'pruebas basadas en propiedades', todas intentan encontrar un contraejemplo para el modelo de especificación dado de su software.
fuente