¿Qué constituye un error? Wikipedia tiene esto que decir:
Un error de software es un error, falla, falla o falla en un programa o sistema de computadora que hace que produzca un resultado incorrecto o inesperado, o que se comporte de manera no intencionada.
Incorrecto, inesperado y no intencionado tienen mucho espacio para el error humano, y de hecho lo vemos con algunas clases de errores. Los requisitos cambian con el tiempo; y la gente los malinterpreta o los recuerda mal. Los nuevos partidos los reinterpretan y, para empezar, se les comunica mal: “¡el programa debe hacer lo que quiero, no lo que dije!”
Para ilustrar, incluso el ejemplo trivial de ‘printf (“hola mundo”); no está libre de errores si el programa tenía la intención de imprimir una nueva línea al final, sin mencionar el estado de salida que debería tener. ¿Qué pasa si la pila está llena? ¿Qué pasa si stdout no está disponible? ¿Qué sucede si libc está vinculado dinámicamente y la nueva versión tiene errores? ¿El programa también tiene errores porque no funciona a su alrededor? ¿Qué sucede si el compilador elige implementar printf recursivamente y “hello world” es lo suficientemente largo como para volar la pila sin optimizaciones de llamadas de cola? ¿Qué pasa si el optimizador tiene errores?
- ¿Alguien puede dar una prueba o explicación de [matemáticas] \ frac12 + \ left (\ frac12 \ right) ^ 2 + \ left (\ frac12 \ right) ^ 3 + \ left (\ frac12 \ right) ^ 4 = \ frac12 \ frac {1 – \ left (\ frac12 \ right) ^ 4} {1 – \ frac12} [/ math]?
- ¿Cuál es la prueba matemática del principio de incertidumbre?
- Cómo probar el teorema binomial
- Cómo comenzar a desarrollar pruebas elementales para teoremas
- ¿Existe una prueba simple o intuitiva de que los tetraedros regulares idénticos no pueden llenar el espacio? ¿Por qué este hecho no es contrarrestado por la observación de que esferas de tamaño idéntico pueden ocupar uniformemente (como balas de cañón) el espacio?
Es difícil razonar en un lenguaje tan informal como el C. Es difícil asegurarse de no depender de un comportamiento indefinido o de hacer supuestos que no están claramente capturados en sus requisitos. E incluso con un lenguaje mucho más formal como Haskell, ¡los requisitos específicos para el desarrollador pueden no comunicarse tan formalmente!
Al igual que con los sistemas físicos, muchas comunidades de software, especialmente aquellas basadas en lenguajes menos formales e imperativos, han puesto a prueba la mayor parte de su esfuerzo. Esta es una lente útil: la prueba de software es una especie de experimento, que otorga peso empírico a favor o en contra de alguna hipótesis. Pero en última instancia, como en las ciencias, los resultados empíricos no pueden probar, solo pueden falsificar.
Cuanto más software esté presente, más pruebas se requieren; y cuantas más interacciones puedan tener. (Esta es una de las razones por las que las pruebas unitarias se ven facilitadas por interfaces más estrechas: menos interacciones significan menos casos extremos para probar). el tamaño de la base del código; y cuanto más se enreden las diferentes unidades, más rápido se eleva. Citando a Dijkstra [EWD340]:
Se ha sugerido que hay algún tipo de ley de la naturaleza que nos dice que la cantidad de esfuerzo intelectual que se necesita aumenta con el cuadrado de la duración del programa. Pero, gracias a Dios, nadie ha podido probar esta ley. Y esto se debe a que no tiene por qué ser cierto. . . . Tiendo a asumir, hasta ahora no desmentido por la experiencia, que mediante la aplicación adecuada de nuestros poderes de abstracción, el esfuerzo intelectual necesario para concebir o comprender un programa no necesita crecer más que proporcionalmente a la duración del programa.
Por lo tanto, la aplicación cuidadosa de la abstracción puede reducir la complejidad del software; pero si su conjetura es precisa (y ciertamente ha sido confirmada por mi experiencia), nunca se puede reducir por debajo de alguna proporción lineal.
Por lo tanto, la respuesta debe depender de la cantidad de razonamiento manual y automático (por ejemplo, solucionadores de pruebas) realizado; la cantidad de pruebas manuales y automáticas realizadas; el nivel de comprensión e integridad de los requisitos; y el profundo conocimiento del entorno implementado del programa. Además, dado que muchos de estos cambiarán con el tiempo, cualquier respuesta que pueda encontrar probablemente sea obsoleta para cuando la encuentre.
O, para citar la observación de Guy English:
Si tuviera cuatro errores y luego solucionara un error, ¿cuántos errores tendría?
No, tendrías una cantidad totalmente indeterminada de errores.
Por lo tanto, es difícil hablar de “100% libre de errores”. Es mucho más fácil, y mucho más útil, hablar de “lo suficientemente confiable dado nuestro conocimiento actual”. Y seguir adelante con el razonamiento, las pruebas y la corrección.