coding-style - paso - programa algoritmo de dijkstra
Comprender el estilo de programaciĆ³n de Mozart de Dijkstra (10)
Encontré este artículo sobre estilos de programación, visto por Edsger Dijsktra. Parafraseando rápidamente, la principal diferencia es Mozart, cuando la analogía se hace con la programación, entiende completamente (discutible) el problema antes de escribir cualquier cosa, mientras que Beethoven toma sus decisiones mientras escribe las notas en papel, creando muchas revisiones a lo largo del camino. Con la programación de Mozart, la versión 1.0 sería la única versión de software que debería apuntar a trabajar sin errores y con la máxima eficacia. Además, Dijkstra dice que el software que no está en ese nivel de refinamiento y estabilidad no debe ser lanzado al público.
Según sus puntos de vista, dos preguntas. ¿Es posible la programación de Mozart? ¿El software que escribimos hoy realmente se beneficiaría si adoptamos el estilo de Mozart en su lugar?
Mis pensamientos. Parece que, para abordar la creciente complejidad del software, hemos pasado de este método a cosas como desarrollo ágil, pruebas beta públicas y revisiones constantes, métodos que definen el desarrollo web, donde la velocidad es lo más importante. Pero cuando pienso en todas las revisiones que el software web puede realizar, especialmente durante el mantenimiento, cuando a menudo los parches se aplican sobre parches, para luego refinarlos a través de un tedioso proceso de refactorización, la forma de Mozart parece muy atractiva. Al menos disminuiría las molestas actualizaciones de software, por ejemplo, Digsby, Windows, iTunes, etc., muchas de las cuales son el resultado de vulnerabilidades imprevistas que requieren una nueva versión inmediata.
Editar: Consulte la respuesta a continuación para obtener una explicación más precisa de las opiniones de Dijsktra.
Bueno, no todos podemos ser tan buenos como Mozart, ¿verdad? Quizás la programación de Beethoven sea más fácil.
Creo que es posible parecer emplear la programación de Mozart. Conozco a una compañía, Blizzard, que no lanza un producto de software hasta que esté listo y listo. Esto no significa que Diablo 3 saltará completo y completo de la mente de alguien en una sesión de codificación deslumbrantemente brillante. Significa que así es como nos parecerá al resto de nosotros. Blizzard pondrá a prueba el diablo fuera de su juego internamente, no mostrándolo al resto del mundo hasta que se hayan resuelto todos los problemas. La mayoría de las empresas no adoptan este enfoque, prefiriendo lanzar software cuando es lo suficientemente bueno para resolver un problema, luego corregir errores y agregar funciones a medida que surgen. Este enfoque funciona (en diversos grados) para la mayoría de las empresas.
Si Apple adoptara la programación de "Mozart", hoy no existiría Mac OS X o iTunes.
Si Google adoptara la programación de "Mozart", no habría Gmail o Google Reader.
Si los desarrolladores de SO adoptaran la programación de "Mozart", hoy no existiría SO.
Si Microsoft adoptara la programación de "Mozart", hoy no habría Windows (bueno, creo que sería bueno).
Entonces la respuesta es simplemente NO. Nada es perfecto, y nada está destinado a ser perfecto, y eso incluye software.
Una historia clásica de Usenet, sobre una verdadera programación de Mozart.
Los programadores reales escriben en Fortran.
Tal vez lo hagan ahora, en esta época decadente de Lite beer, calculadoras de mano y software "fácil de usar", pero en los Good Old Days, cuando el término "software" sonaba divertido y las computadoras reales estaban hechas de tambores y tubos de vacío, Los programadores reales escribieron en código máquina. No Fortran. No es RATFOR. Ni siquiera el lenguaje ensamblador. Codigo de maquina. Números hexadecimales crudos, sin adornos e inescrutables. Directamente.
Para que una nueva generación de programadores crezca en la ignorancia de este glorioso pasado, me siento obligado a describir, lo mejor que puedo a través del espacio generacional, cómo un programador real escribió el código. Lo llamaré Mel, porque ese era su nombre.
Conocí a Mel cuando fui a trabajar para Royal McBee Computer Corp., una subsidiaria ya desaparecida de la compañía de máquinas de escribir. La empresa fabricó la LGP-30, una computadora pequeña y barata (según los estándares del día) con memoria de tambor, y acababa de comenzar a fabricar la RPC-4000, una batería muy mejorada, más grande, mejor y más rápida. computadora de memoria Los núcleos cuestan demasiado, y no estaban aquí para quedarse, de todos modos. (Es por eso que no ha oído hablar de la compañía o la computadora).
Me contrataron para escribir un compilador de Fortran para esta nueva maravilla y Mel fue mi guía para sus maravillas. Mel no aprobó los compiladores.
"Si un programa no puede reescribir su propio código", preguntó, "¿de qué sirve?"
Mel había escrito, en hexadecimal, el programa informático más popular que poseía la empresa. Funcionó en el LGP-30 y jugó al blackjack con clientes potenciales en programas de computadora. Su efecto fue siempre dramático. El stand de LGP-30 estaba lleno en cada show, y los vendedores de IBM estaban parados hablando entre ellos. Si esto realmente vendía computadoras era una pregunta que nunca discutimos.
El trabajo de Mel fue volver a escribir el programa de blackjack para el RPC-4000. (¿Puerto? ¿Qué significa eso?) La nueva computadora tenía un esquema de direccionamiento uno más uno, en el cual cada instrucción de máquina, además del código de operación y la dirección del operando necesario, tenía una segunda dirección que indicaba dónde, en el tambor giratorio, se encontró la siguiente instrucción. En lenguaje moderno, cada instrucción fue seguida por un IR A! Ponlo en la pipa de Pascal y fume.
A Mel le encantaba el RPC-4000 porque podía optimizar su código: es decir, ubicar las instrucciones en el tambor de modo que, cuando uno terminara su trabajo, el siguiente simplemente llegara al "cabezal de lectura" y estuviera disponible para su ejecución inmediata. Había un programa para hacer ese trabajo, un "ensamblador optimizador", pero Mel se negó a usarlo.
"Nunca sabes dónde va a poner las cosas", explicó, "por lo que tendrías que usar constantes separadas".
Pasó mucho tiempo antes de que entendiera ese comentario. Como Mel conocía el valor numérico de cada código de operación y le asignaba sus propias direcciones de batería, cada instrucción que escribía también podía considerarse una constante numérica. Podía recoger una instrucción anterior de "agregar", por ejemplo, y multiplicar por ella, si tenía el valor numérico correcto. Su código no fue fácil de modificar para otra persona.
Comparé los programas optimizados a mano de Mel con el mismo código que el programa de ensamblaje optimizó, y Mel siempre corría más rápido. Eso fue porque el método de diseño de programa "de arriba hacia abajo" no se había inventado todavía, y Mel no lo habría usado de todos modos. Primero escribió las partes más internas de los bucles de su programa, por lo que obtendría la primera opción de las ubicaciones de direcciones óptimas en el tambor. El ensamblador de optimización no fue lo suficientemente inteligente como para hacerlo de esa manera.
Mel nunca escribió bucles de retardo de tiempo tampoco, incluso cuando el Flexowriter balky requirió un retraso entre los caracteres de salida para funcionar correctamente. Simplemente ubicó las instrucciones en el tambor, por lo que cada sucesivo estaba justo pasado el cabezal de lectura cuando era necesario; el tambor tuvo que ejecutar otra revolución completa para encontrar la siguiente instrucción. Él acuñó un término inolvidable para este procedimiento. Aunque "óptimo" es un término absoluto, como "único", se convirtió en práctica verbal común hacerlo relativo: "no del todo óptimo" o "menos óptimo" o "no muy óptimo". Mel llamó a las ubicaciones máximas de demora el "más pesimista".
Después de que terminó el programa de blackjack y lo hizo funcionar, ("Incluso el inicializador está optimizado", dijo con orgullo) recibió una solicitud de cambio del departamento de ventas. El programa usó un generador de números aleatorios elegante (optimizado) para barajar las "cartas" y repartir desde el "mazo", y algunos de los vendedores sintieron que era demasiado justo, ya que a veces los clientes perdían. Querían que Mel modificara el programa para que, al configurar un interruptor de sentido en la consola, pudieran cambiar las probabilidades y dejar que el cliente ganara.
Mel se resistió. Sintió que esto era claramente deshonesto, lo que era, y que incidía en su integridad personal como programador, lo que hizo, por lo que se negó a hacerlo. El vendedor jefe habló con Mel, al igual que Big Boss y, a instancias del jefe, algunos compañeros programadores. Mel finalmente cedió y escribió el código, pero obtuvo la prueba al revés y, cuando se activó el interruptor de detección de sentido, el programa haría trampa, ganando todo el tiempo. Mel estaba encantado con esto, alegando que su subconsciente era incontrolablemente ético, y se negó rotundamente a solucionarlo.
Después de que Mel abandonó la compañía por $ pa $ ture más ecológico, Big Boss me pidió que mirara el código y ver si podía encontrar la prueba y revertirla. De mala gana, acepté mirar. Seguir el código de Mel fue una verdadera aventura.
A menudo he sentido que la programación es una forma de arte, cuyo valor real solo puede ser apreciado por otro versado en el mismo arte arcano; hay gemas preciosas y golpes brillantes ocultos a la vista humana y la admiración, a veces para siempre, por la naturaleza misma del proceso. Puede aprender mucho sobre un individuo simplemente leyendo su código, incluso en hexadecimal. Mel era, creo, un genio no reconocido.
Quizás mi mayor sorpresa vino cuando encontré un inocente bucle que no tenía ninguna prueba. Sin prueba. Ninguno El sentido común decía que tenía que ser un ciclo cerrado, en el que el programa circulaba, para siempre, sin fin. Sin embargo, el control del programa pasó a través de él y salió del otro lado de manera segura. Me llevó dos semanas resolverlo.
La computadora RPC-4000 tenía una instalación realmente moderna llamada registro de índice. Permitió al programador escribir un bucle de programa que utilizaba una instrucción indexada dentro; cada vez, el número en el registro de índice se agregó a la dirección de esa instrucción, por lo que se referiría al siguiente dato en una serie. Solo tenía que incrementar el índice de registro cada vez que pasaba. Mel nunca lo usó.
En cambio, él extraía las instrucciones en un registro de máquina, agregaba una a su dirección y la almacenaba de nuevo. Él entonces ejecutaría la instrucción modificada directamente desde el registro. El ciclo fue escrito por lo que se tuvo en cuenta este tiempo de ejecución adicional: justo cuando terminaba esta instrucción, la siguiente estaba justo debajo del cabezal de lectura del tambor, listo para funcionar. Pero el ciclo no tenía ninguna prueba.
La clave vital vino cuando noté que el bit de registro de índice, el bit que estaba entre la dirección y el código de operación en la palabra de instrucción, estaba encendido, pero Mel nunca usó el registro de índice, dejándolo cero todo el tiempo. Cuando la luz se encendió casi me cegó.
Había localizado los datos en los que estaba trabajando cerca de la parte superior de la memoria, las ubicaciones más grandes que las instrucciones podían abordar, por lo que, después de manejar el último dato, incrementar la dirección de instrucción lo haría desbordarse. El acarreo agregaría uno al código de operación, cambiándolo al siguiente en el conjunto de instrucciones: una instrucción de salto. Efectivamente, la siguiente instrucción del programa estaba en la ubicación de la dirección cero, y el programa avanzó felizmente en su camino.
No me he mantenido en contacto con Mel, por lo que no sé si alguna vez se rindió a la avalancha de cambios que ha tenido que ver con las técnicas de programación desde aquellos días perdidos. Me gusta pensar que no lo hizo. En cualquier caso, me impresionó tanto que dejé de buscar la prueba ofensiva, diciéndole al Gran Jefe que no pude encontrarla. Él no pareció sorprendido.
Cuando salí de la compañía, el programa de blackjack seguiría haciendo trampa si activaras el interruptor de sentido correcto, y creo que así debería ser. No me sentía cómodo grabando el código de un programador real.
El progreso en la informática vale un sacrificio en gloria o genio aquí y allá.
No escala.
Puedo descifrar una línea de código en mi cabeza, una rutina e incluso un pequeño programa. ¿Pero un programa mediano? Probablemente hay algunos tipos que pueden hacerlo, pero ¿cuántos y cuánto cuestan? ¿Y deberían escribir realmente el próximo programa de nómina? Eso es como derrochar a Mozart en muzak.
Ahora, intenta imaginar un equipo de Mozart. Solo por unos segundos.
Aún así es un instrumento poderoso. Si puedes descifrar una línea completa en tu cabeza, hazlo. Si puedes descubrir una pequeña rutina con todos sus casos divertidos, hazlo.
En la superficie, evita volver al tablero de dibujo porque no pensó en un caso de borde que requiera una interfaz completamente diferente.
El significado más profundo (¿ cabeza falsa ?) Se puede explicar aprendiendo otro idioma humano. Durante mucho tiempo, usted piensa qué palabras representan sus pensamientos y cómo ordenarlas en una oración válida; esa transcripción cuesta muchos ciclos de primer plano.
Un día notarás la sensación liberadora de que solo hablas. Se puede sentir como "pensar en un lenguaje desconocido", o como si "las palabras son naturales". A veces tropezarás, buscando una palabra o modismo particular, pero la mayoría de las veces la traducción se ejecuta en los vastos recursos de la "CPU subconciente" .
El "objetivo principal" es desarrollar un modelo mental de la solución que sea (en su mayoría) independiente del lenguaje de implementación, para separar la solución de un problema de la transcripción del problema. La transcripción es fácil, repetitiva y fácil de entrenar, y las soluciones abstractas se pueden reutilizar.
No tengo idea de cómo se podría enseñar esto, pero "averiguar todo lo posible antes de empezar a escribirlo" suena como una buena práctica de programación para alcanzar ese objetivo.
Creo que la idea es planificar el futuro. Necesita al menos tener algún tipo de esquema de lo que está tratando de hacer y cómo planea llegar allí. Si te sientas al teclado y esperas que "la musa" te lleve a donde tu programa necesita ir, los resultados son bastante desiguales y te llevará mucho más tiempo llegar allí.
Esto es cierto con cualquier tipo de escritura. Muy pocos autores simplemente se sientan en una máquina de escribir sin ideas y comienzan a golpear hasta que se produce una novela de éxito de ventas. Diablos, mi suegro (un profesor de inglés de la escuela secundaria) en realidad escribe esquemas para sus cartas .
El estilo de programación de Mozart es un mito completo (todo el mundo tiene que editar y modificar sus esfuerzos iniciales), y aunque "Mozart" es esencialmente una metáfora en este ejemplo, vale la pena señalar que Mozart fue sustancialmente un mito en sí mismo.
Mozart era un supuesto niño prodigio mágico que compuso su primera sonata a los 4 (en realidad tenía 6 años, y apestaba, nunca lo oirás interpretar en ningún lado). Raramente se menciona, por supuesto, que su padre era considerado el mejor maestro de música de Europa, y que obligó a todos sus hijos a practicar el juego y la composición durante horas todos los días tan pronto como podían recoger un instrumento o un bolígrafo.
El propio Mozart tuvo la precaución de perpetuar la ilusión de que su música salió completamente de su mente al destruir la mayor parte de sus borradores, aunque sobrevivió lo suficiente para demostrar que era un editor como todos los demás. Beethoven fue más honesto sobre el proceso (tal vez porque era sordo y no podía decir si alguien se acercaba sigilosamente a él de todos modos).
Ni siquiera mencionaré la teoría de que Mozart consiguió que sus melodías no escucharan a los pájaros cantores. O el hecho de que creó un sistema que usaba los dados para generar aleatoriamente música (que en realidad es genial, pero también podría explicar qué parte de la música de Mozart parecía provenir de la nada).
La moraleja de la historia es: no creas en la exageración. La programación es trabajo, seguida de más trabajo para corregir los errores que cometió la primera vez, seguido de más trabajo para corregir los errores que cometió la segunda vez, y así sucesivamente hasta que muere.
Edsger Dijkstra analiza sus puntos de vista sobre la programación de Mozart vs Beethoven en este video de YouTube titulado " Disciplina en el pensamiento ".
La gente en este hilo ha discutido bastante sobre cómo las opiniones de Dikstra son poco prácticas. Voy a tratar de defenderlo un poco.
- Dijkstra está en contra de que las compañías esencialmente "prueben" su software en sus clientes. Liberando la versión 1.0 y luego inmediatamente el parche 1.1. Sintió que el programa debería pulirse hasta el punto de que los parches de "revisión" no son éticos.
- No creía que el software debería escribirse de una sola vez o que los cambios nunca tendrían que hacerse. A menudo discute sus ideales de diseño, uno de ellos es la modularidad y la facilidad de cambio. A menudo pensó que los algoritmos individuales deberían escribirse de esta manera, sin embargo, después de haber comprendido completamente el problema. Eso fue parte de su disciplina.
- Después de toda su extensa experiencia con programadores, descubrió que los programadores no son felices a menos que estén empujando los límites de su conocimiento. Dijo que los programadores no querían programar algo completamente y lo entendían al 100% porque no había ningún desafío. Los programadores siempre quisieron estar al borde de su conocimiento. Si bien entendió por qué los programadores son así, afirmó que no era representativo de la programación de tolerancia de bajo error.
Existen algunas industrias o aplicaciones de programación que creo que la "disciplina" de Dijkstra también está justificada. NASA Rovers, dispositivos incorporados en la industria de la salud (es decir, medicamentos de dispensación, etc.), cierto software financiero que transfiere nuestro dinero. Estas áreas no tienen los lujos de un cambio incremental después del lanzamiento y es necesario un "Enfoque de Mozart" más.
Creo que la historia de Mozart confunde lo que se envía con respecto a cómo se desarrolla. Beethoven no realizó pruebas beta de sus sinfonías en público. (Sería interesante ver cuánto cambió alguno de los puntajes después de la primera presentación pública).
Tampoco creo que Dijkstra haya insistido en que todo se haga en tu cabeza. Después de todo, escribió libros sobre programación disciplinada que implicaba trabajarlo en papel, y en la misma medida que quería ver la disciplina de calidad matemática, ¿ha notado cuánto papel y tablero de tiza pueden consumir los matemáticos mientras trabajan en un problema?
Estoy a favor de la respuesta de Simucal , pero creo que la metáfora de Mozart-Beethoven debería descartarse. Ese zapato hace sonar la insistencia de Dijkstra en la disciplina y la comprensión en un rincón donde realmente no pertenece.
Observaciones adicionales:
La popularización televisiva no es tan buena, y confunde algunas cosas sobre la composición musical y lo que está haciendo un compositor y lo que está haciendo un programador. En palabras de Dijkstra, de su Conferencia del Premio Turing de 1972: "No debemos olvidar que no es asunto nuestro hacer programas, sino que nuestra tarea es diseñar clases de cálculos que muestren un comportamiento deseado". Un compositor puede estar fuera para descubrir el comportamiento deseado.
Además, en la noción de Dijkstra de que la versión 1.0 debería ser la versión final, confundimos demasiado fácilmente cómo el comportamiento y la funcionalidad deseada evolucionan con el tiempo. Creo que simplifica demasiado al pensar que todas las versiones futuras se deben a que la primera no fue pensada y realizada de manera rigurosa y confiable.
Incluso sin la urgencia del tiempo de salida al mercado, creo que ahora entendemos mucho mejor que los tipos importantes de software evolucionan junto con la experiencia de los usuarios con este y el propósito utilitario que tienen para él. Los contraejemplos obvios son juegos (también considere cómo se desarrollan las películas teatrales). ¿Crees que Beethoven podría haber escrito la Sinfonía n. ° 9 sin toda su experiencia previa y exploración? ¿Crees que la audiencia podría haberlo escuchado por lo que era? ¿Debería haber esperado hasta tener la Sonata perfecta? Estoy seguro de que Dijkstra no propone esto, pero creo que va demasiado lejos con Mozart-Beethoven para exponer su punto.
Además, considere el software para jugar ajedrez. Las nuevas versiones no se deben a que las anteriores no se reprodujeron correctamente. Se trata de explotar los avances en la heurística del juego de ajedrez y el poder computacional disponible. Para esta y muchas otras situaciones, la idea de que la versión 1.0 sea la versión final está fuera de base. Entiendo que él se está oponiendo legítimamente al lanzamiento de un software poco confiable y tal vez defectuoso con deficiencias que se compensarán en mantenimiento y lanzamientos futuros. Pero el contraargumento de Mozart no se sostiene para mí.
Entonces, ¿continuó Dijkstra conduciendo el primer automóvil que compró, o clones de ese automóvil exactamente? Tal vez haya una obsolescencia planificada, pero mucho tiene que ver con mejoras y confiabilidad que posiblemente no podrían haber estado disponibles o incluso haber sido consideradas en generaciones anteriores de tecnología automotriz.
Soy un gran fanático de Dijkstra, pero creo que la cosa de Mozart-Beethoven es demasiado simplista como inapropiada. Soy un gran fan de Beethoven también.