¿Es posible alcanzar el estado de error absoluto cero para el software a gran escala?

71

Estoy hablando de más de 20-30 millones de líneas de código, software a escala y complejidad de Autodesk Maya, por ejemplo.

Si congela el desarrollo todo el tiempo que sea necesario, ¿puede realmente corregir todos los errores hasta que simplemente no haya un solo error, si tal cosa pudiera ser verificada por las computadoras? ¿Cuáles son los argumentos a favor y en contra de la existencia de un sistema libre de errores?

Debido a que existe la idea de que cada corrección que haces crea más errores, pero no creo que sea cierto.

Por errores me refería a los errores tipográficos más simples en la interfaz de usuario, a errores preventivos más serios que no tienen solución. Por ejemplo, una función de secuencia de comandos particular calcula las normales incorrectamente. Además, incluso cuando hay soluciones, el problema todavía tiene que ser solucionado. Por lo tanto, podría decir que puede hacer esto en particular manualmente en lugar de usar la función proporcionada, pero esa función aún debe corregirse.

Joan Venge
fuente
11
"me dijeron algunos de los mejores programadores", no me parecen los mejores programadores. Suenan como los mejores hackers. Una de las RESPONSABILIDADES PRINCIPALES de un programador es comprender qué hace su código y cómo afecta al sistema en su conjunto. Es por eso que tenemos TDD, patrones de diseño, etc. Si esto no se puede hacer, el sistema es basura: el proceso de desarrollo se realizó de manera caótica, desordenada, indisciplinada y poco científica.
Vector
51
Si aún no sabe que existe un error, ¿sigue siendo un error?
Blrfl
55
@Blrf: Más importante aún, si el usuario final no sabe que hay un error, ¿existe?
mattnz
40
“Hay dos formas de construir un diseño de software. Una forma es hacerlo tan simple que obviamente no haya deficiencias. Y la otra forma es hacerlo tan complicado que no haya deficiencias obvias. ”- CAR Hoare
Andrew Lewis
55
Lo es, pero mucha gente no quiere que se cuestionen sus creencias fundamentales.
Joan Venge

Respuestas:

92

Como Mikey mencionó, escribir código sin errores no es el objetivo. Si eso es lo que estás buscando, entonces tengo una muy mala noticia para ti.

El punto clave es que está subestimando enormemente la complejidad del software.

Lo primero es lo primero: está ignorando el panorama general de cómo se ejecuta su programa. No se ejecuta de forma aislada en un sistema perfecto. Incluso el más básico de los programas "Hello World" se ejecuta en un sistema operativo y, por lo tanto, incluso el más simple de los programas es susceptible a errores que puedan existir en el sistema operativo.

La existencia de bibliotecas lo hace más complejo. Si bien los sistemas operativos tienden a ser bastante estables, las bibliotecas son una bolsa mixta cuando se trata de estabilidad. Algunos son maravillosos Otros ... no tanto ... Si desea que su código esté 100% libre de errores, entonces también deberá asegurarse de que cada biblioteca con la que se ejecute esté completamente libre de errores, y muchas veces esto simplemente no es posible. Es posible que no tenga el código fuente.

Luego hay hilos para pensar. La mayoría de los programas a gran escala usan hilos por todo el lugar. Tratamos de tener cuidado y escribir hilos de tal manera que no se produzcan condiciones de carrera y punto muerto, pero simplemente no es posible probar todas las combinaciones posibles de código. Para probar esto de manera efectiva, necesitaría examinar cada orden posible de los comandos que pasan por la CPU. No he hecho los cálculos en este caso, pero sospecho que enumerar todos los juegos posibles de Ajedrez sería más fácil.

Las cosas van de lo difícil a lo imposible cuando miramos la máquina en sí. Las CPU no son perfectas. La RAM no es perfecta. Los discos duros no son perfectos. Ninguno de los componentes dentro de una máquina está diseñado para ser perfecto, está diseñado para ser "lo suficientemente bueno". Incluso un programa perfecto eventualmente fallará debido a un problema de la máquina. No hay nada que puedas hacer para detenerlo.

En pocas palabras: ¿Puedes escribir "Software libre de errores"?

NO

Cualquiera que te diga lo contrario no tiene idea.

Simplemente intente escribir software que sea fácil de entender y mantener. Una vez que hayas hecho eso, puedes llamarlo un día.


EDITAR: Algunas personas comentaron sobre un excelente punto que había pasado por alto por completo: el compilador.

A menos que esté escribiendo en ensamblado, es completamente posible que el compilador estropee su código (incluso si demuestra que su código es "perfecto").

Una lista de errores en GCC, uno de los compiladores más utilizados: http://gcc.gnu.org/bugzilla/buglist.cgi?product=gcc&component=c%2B%2B&resolution=---

Riwalk
fuente
8
La respuesta sigue siendo "no", porque siempre habrá "errores" en los que algo funciona, simplemente no como a un cliente o propietario del producto le gustaría que funcionara. Algunos de nosotros podríamos llamar a estas solicitudes de características, o solicitudes para cambiar el comportamiento o agregar funcionalidad, pero para la persona que está molesta por algún "error" todos los días, lo que les molesta es un error. (Esa es una forma larga de decir que algunos errores están en el ojo del espectador). El CÓDIGO LIBRE DE ERRORES es imposible. Apunte a un código que sea lo suficientemente bueno para cumplir con el propósito previsto.
rápidamente_abr
66
Iré un paso más allá: el código puede tener defectos latentes, por ejemplo, es posible que tenga un código que no se ajusta adecuadamente al rango de verificación de una entrada. Si la entrada es por alguna razón afortunada, nunca está fuera de rango, el error nunca se manifiesta. Luego, un día, durante el mantenimiento o los cambios en las funciones, ese código se llama desde otro lugar que SIEMPRE lo ejercita con un valor fuera de rango. El error ahora se manifiesta, pero estuvo allí todo el tiempo. Puedes tener grados de locura en todo esto, pero la eliminación de toda posibilidad de error aún es imposible.
rápidamente_abr
11
@ JohnR.Strohm No estoy seguro de por qué cree que el programa 'modulador de flujo de mensajes', un programa con 556 líneas de código, tiene algo que ver con una pregunta sobre un sistema teórico de 20 millones de líneas. Excepto, tal vez, demostrar que, por difícil que fuera probar la corrección del pequeño programa, sería astronómicamente más difícil demostrar la corrección de uno masivo.
Eric King
9
Si bien la pregunta original no lo hizo, me gustaría señalar que existe una diferencia gigantesca entre "teóricamente posible" y "prácticamente posible". Si bien una base de código de 20 millones de líneas sin errores es teóricamente posible, es casi seguro que sea una imposibilidad práctica en el mercado actual. Quién sabe lo que nos depara el futuro.
Eric King
44
@ JohnR.Strohm Debería leer el periódico con más cuidado. Se dicen a sí mismos: lo que It is important to note, however, that even all of these steps provide no guarantee of absolute security. It is tempting to believe that a formally specified and proved program should be absolutely correct, but there are several reasons why a proved program may not behave exactly as expected.significa que no se puede probar que esté libre de errores, sino que es menos probable que tenga errores. Más bien como TDD.
Izkata
27

Matemáticamente PODRÍA ser posible escribir software 'sin errores' de tal complejidad, dependiendo de cómo se defina 'error'. Demostrar que PODRÍA ser matemáticamente posible, mediante el diseño de un sistema de prueba que ejerza cada línea de código de todas las formas posibles, todos los casos de uso posibles. Pero no estoy seguro: si se trata de un sistema que realiza cálculos complejos, puede encontrarse con un 'problema de infinito' ...

Hablando prácticamente, en un sistema del tamaño y alcance del que estás hablando, esto es IMPOSIBLE . Podría llevar 1000 años escribir un sistema tan 'libre de errores' y escribir un sistema para demostrar que tomaría exponencialmente más tiempo: tendría que encontrar todos los casos de uso posibles y escribir un sistema que probaría cada uno, y no creo que haya una manera de determinar que realmente ha cubierto todos los casos de uso en un sistema del tamaño y alcance del que está hablando en algo que se parezca a un período de tiempo razonable.

En mi opinión, su pregunta está un poco mal dirigida: nuestro objetivo como desarrolladores no es escribir software 'sin errores'. Nuestro objetivo es escribir software utilizable, flexible y fácilmente mantenible .

Utilizable: el sistema cumple los requisitos esenciales para los que fue diseñado. Puede haber errores, pero estarán en 'casos extremos': valores atípicos o molestias, no errores que comprometan los fundamentos del sistema, robustos.

Mantenible: los errores pueden aislarse y repararse fácilmente y NO crear nuevos errores.

Flexible: su sistema es fácil de cambiar y expandir sin un rediseño significativo y tiempo de inactividad: la mayoría de los cambios requieren simplemente agregar una nueva clase o módulo que se adapte a sus patrones y marco ya bien diseñados.

Buenas prácticas de diseño, buenas prácticas de control, buen trabajo en equipo, desarrolladores concienzudos: esa es la fórmula del BUEN SOFTWARE . (no PERFECTO , pero BUENO )

Vector
fuente
3
"Probarlo PODRÍA ser matemáticamente posible, diseñando un sistema de prueba que ejercite cada línea de código de todas las formas posibles, todos los casos de uso posibles".: Tal programa no existe en general (¡y esto se puede probar!). Por lo tanto, no existe un algoritmo general para probar la corrección.
Giorgio
3
Corrección: Se ha logrado un software libre de errores, COMPLETO CON LA PRUEBA MATEMÁTICA FORMAL DE CORRECCIÓN. Fue hecho en 1982. Google "modulador de flujo de mensajes".
John R. Strohm
66
@ JohnR.Strohm: No es cierto. Aquí hay una sola cita: hay varios documentos y varios lugares donde abordan inquietudes similares: "Una pregunta que surge con frecuencia es" ¿Ha verificado el verificador? "Quizás, sorprendentemente, esta pregunta metamatemática a menudo la formulan los ingenieros, no simplemente por personas puntiagudas. académicos. Por supuesto, si una máquina alguna vez responde la pregunta "¿Alguna vez mientes?", la respuesta no será más informativa que cuando un humano contesta la pregunta ".
Vector
1
Quise decir que no hay un algoritmo general que funcione para cualquier programa de entrada y cualquier especificación de entrada. Solo puede manejar casos específicos (por ejemplo, su ejemplo).
Giorgio el
1
@Giorgio: por lo tanto, en mi opinión, seguir buenas prácticas de diseño es mucho más importante que preocuparse por la corrección matemática: diseñe su código para asegurarse de que pueda integrarse bien y cumplir con lo que ya existe, y sea lo suficientemente robusto como para manejar fácilmente los defectos cuando salir a la luz (que lo harán).
Vector
27

De acuerdo con este artículo, el software a bordo para el transbordador espacial estuvo muy cerca: las últimas tres versiones del programa de línea 420,000 tenían solo un error cada una. El software fue mantenido por un grupo de 260 hombres y mujeres. Un gran número de estas personas eran verificadores, cuyo único propósito era encontrar errores.

La actualización del software para permitir que el transbordador navegue con satélites de posicionamiento global impactó solo el 1.5% del programa, o 6,366 líneas de código. Las especificaciones para ese cambio corrían 2.500 páginas. Las especificaciones para el programa general llenaron 30 volúmenes y corrieron 40,000 páginas, o un promedio de diez líneas de código por página de la especificación.

El presupuesto no fue un problema: a $ 35 millones por año, podían permitirse hacer las cosas bien.

tcrosley
fuente
25
Un error detectado cada uno. ¿Quién sabe cuántos errores no detectados? :)
Andres F.
8
Ese "un error" fue un caso especial. El Shuttle fue diseñado originalmente, y el software especificado, para dos brazos de robot. El "error" fue que todavía había código allí para soportar el segundo brazo.
John R. Strohm
44
+1 Corrió sin errores para 135 misiones de 1981 a 2011
MarkJ
55
@ Mark J: probablemente no sabríamos si el transbordador espacial en realidad no tenía errores. Cada misión del transbordador espacial es constantemente monitoreada por cientos de personas, y cualquier error en la codificación habría sido corregido / anulado manualmente.
Lie Ryan
2
@LieRyan Que muestra muy bien una gran propiedad de los sistemas robustos: si no fallan catastróficamente y siempre permiten ajustes manuales, puede usar sistemas redundantes (como los del centro de control) para hacer el trabajo. Por supuesto, esto solo tiene sentido si tiene sistemas tan redundantes y si realmente puede garantizar la corrección y la coherencia. En una aplicación comercial típica, un bloqueo suele ser preferible a operar en un estado inconsistente: es la diferencia entre una molestia y, por ejemplo, enviar dinero al tipo equivocado. O recibir dinero sin que sea enviado ...
Luaan
15

Esencialmente, no, pero deberías hacer tu mejor esfuerzo de todos modos. Explicaré por qué (o simplemente salte a la conclusión si no tiene suficiente paciencia)

Considere un problema tan trivial como la implementación de la búsqueda binaria. Una implementación muy popular tenía un error que no se detectó durante aproximadamente dos décadas. Si veinte líneas tardan veinte años en liberarse de errores y se usan ampliamente e incluso se supone que son correctas, ¿podemos esperar que un gran programa esté libre de errores?

¿Cuántos errores podemos esperar que tenga un gran programa de todos modos? Un número que encontré fue "10 defectos por 1000 líneas" (Code Complete 2nd edition, página 517 - simplemente usé un ejemplo, sin citar ningún dato) Eso nos da alrededor de 200 000 a 300 000 errores en su software. Afortunadamente, tenemos formas de mejorar la calidad del programa. Se sabe que las pruebas unitarias, las revisiones de códigos y las pruebas manuales comunes reducen la cantidad de errores. Aún así, el número seguirá siendo alto.

Si pudiéramos resolver el 95% de todos los errores, sería increíble. Y, sin embargo, todavía tendríamos entre 10 000 y 15 000 errores en el software.

Afortunadamente, dado que el software es ampliamente utilizado (y, por lo tanto, ampliamente probado), se encontrarán errores. Entonces, gradualmente obtendremos menos errores. Sin embargo, menos errores también significan que los restantes son más difíciles de encontrar, así que no esperes una curva lineal en la corrección de errores. Los últimos errores va a ser muy difícil de encontrar y podrían no ser detectados por varios años (suponiendo que están cada vez encontrados).

También parece estar asumiendo erróneamente que si el software no cambia, no aparecerán nuevos errores. Si el software depende de bibliotecas de terceros, las nuevas versiones pueden romper algunas características, introduciendo nuevos errores a pesar de que el código de la aplicación sigue siendo el mismo. Los nuevos sistemas operativos también pueden romper una aplicación que anteriormente funcionaba perfectamente (consulte Windows Vista para ver un ejemplo popular). Considere también los errores del compilador, etc.

No está claro si las herramientas de prueba de código realmente pueden resolver el problema del software con errores. Ciertamente no es posible resolver el problema de detención de ningún programa, pero podría ser posible demostrar que un programa se comporta como se especifica ... ¿Pero entonces qué? Tal vez el programa de prueba tiene un error. Tal vez la especificación en sí tiene un error.

Claramente, podemos reducir en gran medida la cantidad de errores, pero es muy poco probable que lleguemos a cero.

Debido a que existe la noción de que cada corrección que haces crea más errores, pero no creo que sea cierto.

(énfasis añadido)

Estás en lo correcto. Esta afirmación está mal. Aquí hay un ejemplo:

int main() {
    int x[10];
    x[10] = 8; //Buffer overflow here
    return 0;
}

Ahora, arreglemos este error:

int main() {
    int x[11];
    x[10] = 8; //No buffer overflow here
    return 0;
}

¿Ver? Arreglamos un error y no introdujimos nuevos.

Sin embargo, es cierto que cada vez que arregla un error corre el riesgo de crear uno nuevo, aunque este riesgo puede mitigarse (por ejemplo, con pruebas unitarias).

Digamos que por cada 100 errores que soluciono, accidentalmente introduzco uno nuevo. Entonces, si corrijo 10 000 errores, presento 100 nuevos errores. Y si corrijo esos nuevos errores, presento un error. ¿Y qué? El programa ahora tiene 9 999 errores menos, por lo que probablemente sea mejor de lo que era (suponiendo que el nuevo error no sea 10 000 veces peor que los anteriores).

Además, arreglar un error puede exponer otros nuevos. Pero esos errores también pueden repararse. Si haces las cosas bien, eventualmente el software estará en un mejor estado del que comenzó.

Algunos programadores principales me dijeron que es mejor no corregir muchos errores debido a la noción que mencioné en el OP.

Este comportamiento es negligente. Si hay un error y puedes arreglarlo. Hazlo. Por supuesto, debe hacer todo lo posible para evitar agregar nuevos, pero si introduzco un pequeño error por cada 10 errores graves que soluciono, esa no es una razón válida para dejar de corregirlos. De hecho, es una buena razón para seguir arreglando errores .

Así que menos errores que arregles, menos errores volverán a ti en el futuro

Cuantos menos errores solucione, más errores permanecerán en su software, lo que molestará a sus usuarios. De hecho, no "volverán a ti en el futuro". No volverán porque nunca se fueron en primer lugar. La noción de "volver" está relacionada con las regresiones. Nuevamente, es posible reducir el riesgo de regresiones.

Algunos errores no se pueden corregir porque se usaron tanto que la gente comenzó a depender de ellos y corregir el error rompería el programa para esos usuarios. Sucede. Sin embargo, ¿pueden realmente considerarse errores en ese caso?

La mentalidad de "arreglar un error, hacer un error" podría estar relacionada con ese monstruo horrible , un código que es tan ilegible e imposible de mantener que simplemente tocarlo crea errores. Si tiene un monstruo en su base de código, es posible que primero necesite des-monstruificarlo antes de hacer algo.

Finalmente, si eres un programador terrible, existe el riesgo de que cualquier cosa que toques cree nuevos errores. Obviamente, esto pondría nerviosos a los programadores senior. Sin embargo, decir "No hagas nada. No toques nada. Ni siquiera respires". Probablemente no sea la forma correcta de crear un ambiente de trabajo saludable. La educación es mejor.

Conclusión:

  • El software que sigue obteniendo toneladas de nuevas características, pero sin correcciones de errores, inevitablemente apestará.
  • El software que obtiene un número moderado de nuevas características pero soluciona sus errores tiene más posibilidades de ser utilizable.
  • Los que intentan tener pocos errores tienen (en promedio) menos errores que los que no les importan.
  • No es razonable esperar que un programa finalmente se vuelva libre de errores.
  • Los programadores senior no son necesariamente competentes.
  • Arregla tus errores.
  • Adopte metodologías que mejoren la calidad de su software.
luiscubal
fuente
+1: Estaba buscando el ejemplo de búsqueda binaria, me golpearon;) Si 20 líneas de código ampliamente discutido y circulado contenían un error durante 20 años, ¿cuánto tiempo necesitarías para una base de código de 20 millones de líneas que en la mayoría de las pocas docenas de personas ocupadas que mirarán?
scrwtp
Gracias. Me pregunto si ese error de búsqueda binaria (que nunca he escuchado antes) está relacionado con que la gente copie pegando mucho código sin pensar mucho. Además, si tenemos tantos errores que son suficientes incluso para enumerarlos, ¿quizás las herramientas y prácticas que estamos utilizando no son óptimas?
Joan Venge
1
@JoanVenge Cité ese ejemplo para mostrar lo difícil que puede ser encontrar errores. En este caso, el pegado de copias era lo correcto , ya que se demostró que era correcto y la implementación escrita desde cero probablemente tendría más errores. Las herramientas y prácticas que nosotros, como industria en general, estamos utilizando ciertamente no son óptimas. Las mejores prácticas son fáciles de ignorar y los malos hábitos son fáciles de mantener. En última instancia, los errores siempre existirán porque los humanos no son perfectos. Pero podemos reducir la cantidad de errores haciendo nuestro mejor esfuerzo e insistiendo en una educación de alta calidad.
luiscubal
77
Creo que el error en el código de búsqueda binario demuestra cuán compleja es esta pregunta. El error subyacente en la búsqueda fue un posible desbordamiento de enteros en una adición. Tales "errores" son omnipresentes porque la mayoría de la gente confía en una suposición implícita (y ocasionalmente incorrecta) de que las entradas no serán lo suficientemente grandes como para causar un desbordamiento. ¿Es realmente un error o simplemente un contrato de interfaz mal documentado? ¿Cuándo fue la última vez que seleccionó el rango que verificó los sumandos en una suma de enteros o el desbordamiento después del hecho?
Charles E. Grant
44
Sus servidores de ejemplo resaltan una observación bastante obvia sobre el lenguaje de programación y la calidad de la herramienta. Un compilador de calidad de producción para un lenguaje robusto debería haberse negado a compilar su primer ejemplo, devolviendo en su lugar un error fatal de compilación. Que incluso es POSIBLE compilar una abominación así le dice todo lo que necesita saber sobre la calidad de esas herramientas y la viabilidad de su uso para entregar software libre de errores.
John R. Strohm
12

Las razones para no escribir programas libres de errores son principalmente económicas.

No son métodos matemáticos para demostrar la exactitud de un programa. En un curso de informática de alta calidad se mencionarán. Hay lenguajes de programación inventados especialmente para este propósito. En teoría, la programación sin errores es posible.

Sí, existe un hardware imperfecto que a veces puede cambiar un valor de bit porque un neutrino disparado desde una supernova distante hace millones de años acaba de golpear su procesador en el lugar correcto. Bien, cada teoría tiene sus supuestos y abstracciones. Pero suponiendo que el procesador funcione como se anuncia, existen herramientas matemáticas para asegurarse de que el programa también funcione correctamente.

Algunas respuestas muy votadas en este tema son engañosas. Por ejemplo, el teorema de incompletitud de Gödel y el problema de detención solo implican que no se puede tener, por ejemplo, una herramienta automatizada que decida la corrección o incorrección de cualquier programa. Pero no queremos decidir la corrección de ningún programa, solo queremos una prueba de la corrección de un programa específico .

(Analógicamente, solo porque no pueda escribir un programa para decidir automáticamente la verdad de un teorema matemático, eso no significa que no pueda probar un teorema matemático específico ).

El problema, en cambio, es este:

Aunque en teoría es posible escribir un programa libre de errores, hacerlo sería muy costoso . Escribir un código con una prueba de su corrección es más complicado que simplemente tirar algo a la pared para ver si se pega. Incluso si "ver si se pega" se realiza mediante pruebas unitarias; y muchos programadores ni siquiera se molestan en hacer eso. La mayoría de los programadores ni siquiera sabrían cómo hacerlo, lo que significa que, como empresa, tendrías que contratar a otros más caros.

Considerando todos los costos, un cliente típico está más contento con un software barato que funciona bien el 99% del tiempo (y el 99.9% del tiempo después de instalar actualizaciones adicionales) que tener un software quizás mil veces más costoso que funciona bien el 100% del tiempo. el tiempo. Además, el cliente quiere tener este software ahora , y no en diez o veinte años.

Por lo tanto, las personas a sabiendas producen software que tiene alguna posibilidad de errores, tratando de alcanzar la combinación óptima donde los errores no son demasiado frecuentes y no demasiado serios, y la producción es lo suficientemente rápida y barata. La combinación que proporciona la mayor ganancia en la vida real. (A veces, incluso significa lanzar un software lleno de errores antes de que sus competidores publiquen algo, y solo lanzar una versión 2.0 más decente cuando sus competidores están listos para lanzar su primera versión decente).

Si congela el desarrollo todo el tiempo que sea necesario, ¿puede realmente corregir todos los errores hasta que simplemente no haya un solo error, si tal cosa pudiera ser verificada por las computadoras?

Matemáticamente hablando, podrías. Económicamente hablando, ¿por qué alguien haría eso? Significaría gastar unos veinte años y unos pocos millones de dólares. Mientras tanto, los clientes querrían nuevas funciones y sus aplicaciones congeladas no podrían proporcionarlas. Entonces, en el momento en que su versión perfecta esté lista, el mercado ya está ocupado por sus competidores.

Razonar económicamente está bien. Vivimos en un mundo donde el dinero y el tiempo son importantes. Pero solo porque no hacemos algo por razones económicas, no deberíamos decir tonterías sobre cómo eso no se puede hacer, incluso en teoría. Quién sabe ... tal vez en unos pocos años vamos a tener algunos nuevos lenguajes de programación y herramientas que podrían hacer la corrección demostrando fácil .

Viliam Búr
fuente
Gracias, aunque desearía que la mayoría del software funcionara el 99% del tiempo, la mayoría de los grandes que uso como el OP, son extremadamente defectuosos. Pero creo que el monopolio y la compra de competidores también influyen en esto. Pero entiendo tu punto.
Joan Venge
1
"Caro" es relativo. Compare el costo de encontrar y corregir los errores con el costo de, por ejemplo, una máquina de radioterapia que mata a varios pacientes y mutila a otros. (Google "Therac 25".)
John R. Strohm
6

No.

David Hilbert propuso su segundo problema de matemáticas en 1900, que esencialmente le pedía al mundo que probara que la aritmética funcionaba según lo previsto. Más tarde propuso " el problema Entscheidungs ", que preguntaba algo similar en términos lógicos. El " primer teorema de incompletitud " de Kurt_Gödel demostró en 1931 que ninguna teoría de la aritmética elemental podría ser consistente y completa. La representación de Alan Turing del problema de Entscheidung como " el problema de detención " trasladó el tema directamente al corazón de esta pregunta, donde demostró que es imposible probar si un programa se ejecutará hasta su finalización o no. Dado que la indeciabilidad, también es imposible probar si un programa tiene algún error o no.

Nada de eso libera a los programadores practicantes entre nosotros de no luchar por ningún error. Simplemente significa que no podemos tener éxito en general.

Ross Patterson
fuente
9
La indecidibilidad solo se aplica en general: hay programas para los que no puede probar ni la corrección ni la incorrección. Pero para un programa específico dado, la corrección (o más a menudo: incorrección) a menudo se puede probar. Esto supone que tiene una especificación de lenguaje formal y un compilador probadamente correcto; este último no existe para ningún lenguaje de programación de alto nivel, aunque CompCert se acerca.
Daniel
+1 por citar los antecedentes teóricos relevantes. ¡Todavía no sabía que el "Entscheidungsproblem" se llama igual en inglés que en alemán!
Peopleware
55
De acuerdo con Daniel El desafío es sobre una sola instancia; El problema de detención se ocupa de todas las instancias posibles. Trivialmente se int main() { return 0; } detiene y está libre de errores.
MSalters
1
El problema de detención no dice que sea imposible probar si un programa se ejecutará hasta su finalización; dice que existen programas para los cuales es imposible probar. Los programas cotidianos regulares no están en esta clase. "Si bien la prueba de Turing muestra que no puede haber un método o algoritmo general para determinar si los algoritmos se detienen, las instancias individuales de ese problema pueden ser susceptibles de ataque. Dado un algoritmo específico, a menudo se puede demostrar que se debe detener cualquier entrada, y, de hecho, los informáticos a menudo lo hacen como parte de una prueba de corrección ".
Endolith
6

Errare humanum est

Incluso si escribe código con un lenguaje formal, como el método B , que puede usar para demostrar matemáticamente que se cumplen los requisitos,

Incluso si usa un lenguaje de especificación formal,

Siempre hay un paso humano que consiste en extraer las necesidades del usuario de uno o más cerebros a una computadora.

Este paso humano es propenso a errores, y el gusano está en la manzana.

Mouviciel
fuente
1
¿Sigue siendo un error cuando un programa hace lo que se le pidió, en lugar de lo que se pretendía?
MSalters
Creo que es ..
Joan Venge
44
@MSalters - Por supuesto que lo es. No desde un punto de vista contractual, pero al final el cliente no ha resuelto su problema. ¿Volarías en un avión cuyas computadoras hacen lo que piden pero no lo que pretenden?
mouviciel
3

Una proporción justa de los "errores" que he encontrado podrían describirse más adecuadamente como desajustes entre el diseño del sistema y las expectativas del cliente.

Ahora, ya sea que llamemos a estos errores o no, es académico, pero el hecho es que una buena parte del trabajo de mantenimiento surge como resultado directo de una comunicación imperfecta y las expectativas cambiantes de los clientes.

Incluso si un sistema es técnicamente, probablemente "correcto" en el sentido de cumplir con una especificación (por improbable que pueda ser para un software comercial del mundo real), aún tendrá el problema de hacer coincidir la función del software con la de su cliente. expectativas cambiantes y mal definidas.

En breve:

No.

William Payne
fuente
+1 Un desarrollador y un cliente pueden tener puntos de vista muy diferentes sobre lo que define un 'error'.
GrandmasterB
Pero, ¿qué pasa si el desarrollador también es el usuario? En general, encuentro el mejor software de esas personas en términos de usabilidad, ya que saben exactamente cómo debería funcionar algo, etc.
Joan Venge
2

Si tiene una especificación suficientemente estricta y restringida, es posible que pueda probar un programa libre de errores, pero solo basado en suposiciones no demostrables sobre el correcto funcionamiento de todo lo demás en el sistema. Esto da por sentado que no hay forma de demostrar que las especificaciones se considerarían correctas por quien planteó el problema original o por quien estaba utilizando el servicio.

ddyer
fuente
1

La sección No Bugs de Jim Shore me pareció una lectura muy útil sobre este tema. La forma corta: no es posible desarrollar sin producir errores, pero podemos trabajar de tal manera que los detectemos lo antes posible.

Durante la producción del código en sí. Por ejemplo, al escribir y ejecutar pruebas unitarias con frecuencia durante el desarrollo, constantemente nos aseguramos de que el código haga lo que se supone que debe hacer. Además, es útil reescribir perpetuamente el código existente de tal manera que exprese más claramente el comportamiento previsto del sistema.

En su caso, sin embargo, está hablando de una base de código ya existente con millones de líneas de código. Si desea obtener un sistema libre de errores de este tipo, primero debe saber qué es "un error" para este sistema. Puede escribir conjuntos de pruebas post-hoc que garanticen la funcionalidad del sistema (si aún no existe). La red de esas pruebas puede servir como una definición aproximada del comportamiento correcto del sistema. Pero cuanto más código tenga, más esfuerzo implicará en tales ejercicios. Por lo tanto, la mayoría de las empresas hacen un compromiso: viven con lo imperfecto, trabajan con listas de errores y mantenimiento para eliminar los errores más molestos del sistema.

rplantiko
fuente
1

Sobre la verificación por parte de la computadora.

Hay dos formas de verificar un programa usando una computadora. Uno está probando, el otro está usando un sistema de prueba.

Tan pronto como las pruebas exhaustivas no son posibles, las pruebas se vuelven incapaces de mostrar que un programa no tiene errores, solo que tiene algunos. (Y tiene el problema de demostrar que sus propias pruebas no están probando la presencia de errores).

Para usar un sistema de prueba, comienza con los requisitos formales (y ellos mismos pueden tener errores, con suerte el lenguaje utilizado para los requisitos será más adecuado para convencerse de que no hay errores allí que con un lenguaje de programación) y construir / probar con la ayuda de los sistemas de prueba de que el programa está libre de errores (y existe la cuestión de los errores en los sistemas de prueba, pero demostraron ser correctos). El estado actual de la técnica es un compilador para un subconjunto C (y el subconjunto no es académico, "CompCert admite todo el subconjunto MISRA-C 2004 de C, además de muchas características excluidas por MISRA").

Un programador
fuente
Para citar a Donald Knuth (de memoria): puede probar que un programa está libre de errores, pero eso no significa que no tenga errores :-)
gnasher729
1

No, porque las computadoras y el entorno de software en el que se ejecuta la aplicación continuarán cambiando incluso mientras el código esté congelado. El sistema operativo continúa evolucionando con parches y correcciones, así como los dispositivos y controladores. Justo cuando crees que has llegado al punto de que no hay errores conocidos, AMD o nVidia lanzarán una actualización del controlador de video que afecta la forma en que interactúas con el subsistema de video. Ahora su aplicación tiene defectos visuales (como parpadeo, parpadeo o reducción de la velocidad de fotogramas) para los clientes que tienen una determinada tarjeta de video o configuración (SLI? LOL).

Además del hardware y el sistema operativo, también hay una serie de productos de middleware debajo de las aplicaciones más importantes que también evolucionarán más allá de su control, y justo cuando obtiene su código en un estado de defecto cero, las capas debajo de EOL'ed.

La tecnología evoluciona, al igual que el negocio que aprovecha la tecnología, y la idea de "liberar" el código no es posible ni factible. La empresa que solicita un nuevo conjunto de características no responderá bien a "tenemos el código bloqueado mientras buscamos todos los errores conocidos y nadie informa un defecto de software válido en X meses". Incluso si el negocio compra esa línea, después de X meses preguntarán cómo van las nuevas funciones, y la respuesta no puede ser "decidimos extender la congelación porque Oracle acaba de lanzar un parche y necesitamos tomar X meses más para certificar eso ".

No, en algún momento la empresa buscará un equipo de desarrollo más flexible que respalde la necesidad de avanzar a la velocidad de la tecnología. Este es el problema fundamental que enfrentan los equipos de desarrollo modernos.

Thomas Carlisle
fuente
0

Sí, pero nunca lo sabrás con seguridad. Cuanto más busques, más encontrarás. Cuanto más pesado sea el sistema y más casos extremos se utilicen, más probable será que encuentre otro desajuste con la intención o especificación original. Esto implica que un error en sí mismo no es una cosa exacta y, a menudo, dependerá de la interpretación, de qué tan malo un individuo evalúa una anomalía percibida.

Es una cosa borrosa. Pocos sistemas se especifican hasta el último bit. Si un sistema funciona bien y los usuarios no tienen quejas (nada les molesta) y están totalmente adaptados a él, también puede llamarlo libre de errores.

Martin Maat
fuente
-2

Es posible entregar constantemente software libre de errores, dada una disciplina suficiente y una cultura de equipo compartida. (Y un código modular bien factorizado, un conjunto integral de pruebas automatizadas, inspección de defectos y adaptación de su proceso, y muchas otras cosas que requieren esfuerzo y humildad pero que se pagan mil veces)

Pero al hacer esto, generalmente no se propone construir un sistema de 20 MLOC. Si escribir su código libre de errores no es su objetivo, tampoco debería construir un sistema MLOC de muchos.

Mi propio razonamiento es el siguiente:

Alguna persona tiene una necesidad que cumplir. Alguna persona (posiblemente la misma, posiblemente una diferente) tiene un presupuesto para satisfacer la necesidad a través de software de escritura. Todas estas personas esperan obtener algún beneficio por su dinero.

La persona con un presupuesto pagará a algunas personas (posiblemente las mismas, posiblemente diferentes) llamadas programadores , para que estos programadores conviertan parte de su tiempo acordado en software que satisfaga la necesidad.

Por lo tanto, estos programadores trabajan para transformar el dinero de otra persona en software que satisfaga la necesidad. Es su responsabilidad poner este dinero en buen uso.

Esto tiene las siguientes implicaciones con respecto a su pregunta:

  • Dado que hay un error en el software, ¿lo solucionará? Necesita un programador para corregir un error, y el programador costará dinero. Un programador no puede decidir si gastar el dinero para hacerlo. Es el papel de la persona que tiene el presupuesto.
  • ¿Puedo construir un software 20MLOC desde cero sin dejar errores sin corregir al final? Bueno, establecer un 20MLOC requería la intención de gastar una enorme cantidad de dinero. Esto es financieramente tonto. Y no se construye en un día. Pero el software es para las necesidades de hoy, no para el mañana. Habrá un intento equivocado de paralelizar el desarrollo mediante la contratación de muchos programadores. Pero entonces, lo más probable es que no obtendrá una cultura compartida y se producirán errores, se producirán desperdicios y retrasos, y se acabará el dinero para solucionarlos. Todavía no he visto ningún sistema libre de errores de este tamaño. (He visto sistemas libres de errores y sistemas 20MLOC, pero no eran lo mismo)
  • Estoy a cargo de mantener un sistema 20MLOC que no escribí. ¿Podré llegar a cero errores conocidos? Esto no depende de los programadores. No pueden decidir corregir errores porque no es su dinero en juego. ¿Hay suficiente ROI para corregir los errores restantes? Bueno, el sistema ha existido desde hace algún tiempo, y los usuarios se han acostumbrado y utilizan las peculiaridades del sistema para su ventaja en su trabajo diario. Si corrige los errores por principio, la persona con el dinero podría tener que pagar para volver a desarrollar alguna característica no especificada que desapareció del sistema, lo que costó aún más dinero.

Se trata del dinero, y con razón.

Laurent LA RIZZA
fuente
-2

Si.

Pero como sabes, requiere demasiado esfuerzo para valer la pena.

Antes de que pueda defender mi respuesta, primero debemos definir qué es un error:

  • Un error es un comportamiento contrario a la especificación.
  • Sin embargo, las fallas en la especificación (por ejemplo, la ley 0 de robótica) no cuentan como errores de software.
  • Las características adicionales no cuentan como errores, a menos que la especificación lo prohíba.
  • En aras de la discusión, las contradicciones dentro de la especificación tampoco cuentan como errores de software.

Ahora, como ya sabrá, las buenas arquitecturas de software son modulares, de modo que cada módulo puede probarse en unidades (o probarse manualmente, o lo que sea) individualmente. A través de la disciplina y las pruebas cuidadosas, es posible escribir módulos individuales que no tengan errores.

"¡Pero espera!" Te escucho protestar, "¿Qué pasa si un comportamiento inesperado (pero no obstante correcto) de un módulo causa un error en otro?" Entonces el error está en el segundo módulo. Los módulos libres de errores se pueden tratar como API, y las API, como saben, requieren un poco de cuidado para usarse correctamente.

Escribir código a prueba de balas requiere un amplio conocimiento de los casos límite y la lógica de flujo por parte del desarrollador, y la mayoría de los desarrolladores de software no son lo suficientemente inteligentes como para aprender o simplemente no les importa. O más a menudo, están en una fecha límite.

"Pero dame un lugar donde pararme y moveré el mundo". - Arquímedes

Jonathan Graef
fuente
Requiere esfuerzo, pero que paga.
Laurent LA RIZZA
1
Si deja los errores de especificación fuera de la ecuación, todo su software se vuelve inútil: las especificaciones son solo herramientas para anotar las necesidades del usuario de una manera relativamente formal, pero al final es el usuario el que necesita ser satisfecho, no la especificación. Y crear la especificación es tan parte del desarrollo del software como escribir el código. Después de todo, una especificación formal completa describiría el comportamiento del sistema tal como lo hace el código final, la especificación simplemente no es eficientemente ejecutable.
cmaster