Si los cálculos de la computadora son deterministas, ¿por qué el software de la computadora a menudo es determinista y tiene errores?

Las computadoras son deterministas, pero los programadores a menudo no pueden predecir correctamente los resultados de un programa. Ejemplo simple:

a = inicio
mientras que a! = end do
a + = 1
fin

Esto funciona bien si start es menor que end; pero si sucede que cometo un error, y el inicio es mayor que el final, la computadora hará un bucle (determinista) para siempre.

Otra fuente de comportamiento indeterminado es si algunas de las entradas a un programa o función no son predecibles. A veces, lo que sucede depende de la relación de tiempo precisa entre las diferentes entradas, o qué parte de un mensaje se corrompe por el ruido; o tal vez está haciendo algo crítico con el tiempo, y el recolector de basura decide ejecutarlo, bloqueando el programa principal durante unos pocos milisegundos. Una gran cantidad de programación en tiempo real y diseño de protocolo de comunicaciones trata de asegurarse de que pase lo que pase, el protocolo / programa actúa de manera predecible.

Finalmente, hay funciones matemáticas como, por ejemplo, la función de Ackermann, que son completamente deterministas, pero impredecibles en el sentido de que es difícil o imposible predecir una entrada arbitraria cuando o si el resultado convergerá.

TL; DR: ¡determinista no significa predecible!

Debido a que el proceso en el que se organizan esos cálculos deterministas son muy a menudo defectuosos.

Un software solo hace exactamente lo que le pediste. Si lo que pidió es defectuoso, el resultado es defectuoso. Hay alguna realidad o estado que usted, el programador, no tuvo en cuenta. Te lo perdiste en tu algoritmo. Te perdiste en tu estructura de datos. Te lo perdiste en tus pruebas.

Agregue a esto la complejidad de los grandes sistemas de software, y obtendrá un software ‘defectuoso’.

Es muy difícil dar cuenta de antemano de todos los posibles estados que encontrará en el código. Es casi imposible dar cuenta de todos los escenarios en los que se utilizará el código … y, por lo tanto, debe probarse.

Incluso cuando retransmite en bibliotecas y API conocidas, siempre parece haber algún escenario, algún estado en el que el código ‘confiable’ puede fallar.

E incluso si descubrió que su código está construido y probado “perfectamente”, solo tengo que ponerlo en el espacio, dejar que un par de chips sean golpeados por los rayos cósmicos, y obtendrá estados indefinidos para los que su software nunca esperó.

Tal vez haya oído hablar de la “Ley de Murphy”: si algo puede salir mal, saldrá mal.

Bueno, Murphy era optimista.

Todo el código fallará. Un ingeniero de software acepta esta realidad y diseña el sistema para acomodarlo y recuperarlo, con daños e interrupciones mínimos. Nunca se trata de “si” fallará, simplemente “cuándo” falla …

Porque no está dispuesto a pagar por un software de calidad. La mayoría del software está hecho lo suficientemente bueno como para ejecutarse en circunstancias de idea, luego se mejora para detectar los errores más estúpidos y horribles y luego se envía a los clientes sabiendo que todavía hay miles de formas en que podría fallar. Podría mejorarse, pero nadie quiere pagar el dinero extra.

Los mainframes de IBM, por ejemplo, tienen dos CPU y dos palos de RAM. Puede quitar la CPU sin apagar la computadora y aún así no se bloqueará. Esta confiabilidad cuesta alrededor de $ 1,000,000 y es más lenta que una computadora portátil que cuesta $ 1,000. El software también es sólido como una roca pero feo.

Veamos un programa simple que le pregunta su nombre y fecha de nacimiento y le dice su edad. Simple, ¿verdad? Bueno, las siguientes cosas podrían fallar o hacer que el programa esté mal:

  • ¿Soporta entrada Unicode?
  • ¿En qué formato está la fecha? EE. UU., Reino Unido o ISO
  • ¿Su sistema admite fechas de Tailandia o solo fechas occidentales?
  • Son los números ingresados ​​en ASCII o un número Unicode. ¿Cuántos sistemas de números quieres admitir?
  • ¿El programa es de 32 o 64 bits?
  • ¿Ha verificado si la RAM es válida o podría haber sido corregida?
  • ¿Estás escribiendo tu propia biblioteca de fecha / hora o estás usando la que está integrada en el sistema operativo?
  • ¿Su biblioteca de fechas admite años bisiestos, horario de verano, el error Y2K? ¿Has probado todos ellos para verificar que funciona?
  • ¿Has comprobado que el programa no está dañado antes de ejecutarse?

Espero que te dé una idea de lo que se requiere para probar todo. La mayoría de los programas simplemente asumen que funcionará, verifica si hay errores obvios y luego lo repara si se rompe.

Los cálculos son deterministas, pero el número de posibles escenarios de la vida real es muy, muy grande. Y los humanos, siendo humanos, sin mencionar que están limitados por el tiempo y el presupuesto, solo pueden probar tantas combinaciones.

Por ejemplo, los desarrolladores prueban una nueva aplicación en Windows 7, 8 y 10, en un procesador Intel y un procesador AMD. Y funciona.

Pero hay literalmente millones de combinaciones de CPU / GPU / RAM / Motherboard / OS / otras SW no probadas. Estos componentes personalizables, a todos los efectos prácticos, hacen que las aplicaciones actúen de manera no determinista.

Una vez, una empresa estadounidense tenía una aplicación que funcionó perfectamente durante años, pero cuando la usé, me dio un error y se bloqueó. ¿Por qué?

Porque soy europeo y uso el formato DMY, mientras que ellos usaron el formato MDY. Y siempre funcionó en todas sus computadoras con formato MDY.