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.
fuente
Respuestas:
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=---
fuente
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.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 )
fuente
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.
fuente
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.
(énfasis añadido)
Estás en lo correcto. Esta afirmación está mal. Aquí hay un ejemplo:
Ahora, arreglemos este error:
¿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ó.
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 .
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:
fuente
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).
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 .
fuente
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.
fuente
int main() { return 0; }
detiene y está libre de errores.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.
fuente
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.
fuente
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.
fuente
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.
fuente
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").
fuente
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.
fuente
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.
fuente
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:
Se trata del dinero, y con razón.
fuente
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:
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
fuente