15 marzo 2023

¿Qué diablos es programar?

 La Máquina de Turing
Alan Turing era matemático, estudió en el Kings College de Cambrigde y tenía una manera mu rara de pensar, porque mientras otros matemáticos trabajaban con símbolos y álgebra, él imaginaba máquinas. Los problemas matemáticos más intrincados los atacaba diseñando mentalmente máquinas tontas, mecánicas, de funcionamiento muy simple. 

La revolución que causó el pensamiento de Turing en matemáticas fue análoga a la causada por Richard Feynman con sus diagramas en Física, por lo genial, sencillo, claro y potente de su diseño. La Máquina de Turing permitió contestar una de las preguntas más profundas y fundamentales de las matemáticas: el ."Entscheidungsproblem", es decir si las matemáticas son "decidibles" o no. Pero eso mejor dejémoslo para otra oportunidad.  

Recordaba a Turing porque me quedó dando vueltas la pregunta corta y precisa de Karim hace unos días "Bueno ¿y qué mierda es la programación?", es una gran pregunta y le contesté hablando de los algoritmos lenguaje y cosas por el estilo. 

Pero me quedó dando vuelta y me di cuenta que mi respuesta había sido mala y cliché. Para entender realmente lo que es la programación hay que entender primero la Máquina de Turing. A propósito es un lugar común que en matemáticas y ciencias son mucho más valiosas las buenas preguntas que  las buenas respuestas y esta como dije fue muy buena.

Porque casi nadie se lo pregunta en serio, la programación no son simplemente algoritmos, una receta de cocina o las instrucciones de un piloto son algorítmos típicos pero no tienen nada que ver con la programación. 

La Máquina de Turing en cambio permite entender bien que son los computadores, como funcionan, cuales son sus límites y qué es la programación. 

Turing se imaginó su "Máquina Universal" como una caja con un lápiz, un borrador y una cinta que avanza y retrocede, yo creo que una imagen mejor es una libreta, con un mono amaestrado o un mecanismo capaz de entender y obedecer solo cinco instrucciones: (i) pasar a la página siguiente, (ii) volver a la página anterior, (iii) escribir algo en la página, (iv) borrar algo en la página y (v) detenerse.

Esta sencillícima máquina, que no tiene ni una pizca de "inteligencia" es el modelo de todos los computadores que existen y que pueden existir. Permite resolver además asuntos complicadísimos en las matemáticas, inteligencia artificial y distinguir entre lo que es y lo que no es computable. 

Supondremos que la máquina funciona con un lenguaje de solo dos símbolos 1 o 0. O sea las instrucciones serán del tipo "escriba un 1 en la página actual", "escriba un 0 en la página actual (en otras palabras borre lo que haya)", "pase a la siguiente página", "devuélvase a la página anterior" o "termine lo que está haciendo"

Esto de usar solo dos símbolos, ceros y unos, no es necesario para el modelo, pero tiene una conveniencia práctica porque así es como funcionan los computadores digitales, la máquina podría usar tantos símbolos como se nos antoje, pero nos conviene pensar con solo dos. 

Noten que "escribir" es poner una marca en la página y corresponde a un 1 y "borrar" equivale a quitar esa marca y corrsponde a un 0. Al principio todas las páginas están en blanco, o sea con puros ceros.

Los electrónicos ya podemos ver que hay una correspondencia total con los procesadores reales que trabajan solo con unos y ceros que pueden ser escritos o borrados en secuencia, esta secuencia puede ir para atrás o para adelante. 

En nuestra Máquina Universal hemos hablado de "alguien" que desde afuera le da instrucciones a la máquina: ese es el programador, que le entrega cualquiera de las cinco instrucciones a la máquina de manera secuencial, una después de otra.

En principio el programador va dando las instrucciones en tiempo real, pero creo que fue John Von Neumann al que formalizó la idea que el programa podría estar grabado en una especie de memoria, tarjetas perforadas por ejemplo, que se escribían una sola vez y después toda la secuencia podría correrse tantas veces como uno quiera. Esa secuencia de instrucciones es el programa.

Recordemos que nustro computador solo tiene la capacidad de entender 5 instrucciones, nada más y usa un lenguaje de solo dos símbolos: uno y cero.

Los que aprendimos a programar -por ejemplo- controladores en lenguaje de máquina, vemos que esos aparatos son exactamente máquinas de Turing: su entrada y salida está en código binario, el programa se escribe en una memoria que almacena la secuencia de instrucciones y el controlador tiene "registros" que son espacios de memoria interna que equivalen a la hoja de la libreta. Estos registros pueden ser escritos, borrados, se puede ir hacia atrás o hacia adelante en la secuencia, una máquina de Turing hecha y derecha.

¿Pero cómo entonces los computadores que no tienen nada de inteligencia y lo que pueden hacer es tan limitado puede hacer cosas tan sofisticadas como Youtube, Whatsapp, Blogger, hacer complicados cálculos matemáticos, analizar textos, jugar ajedrez contra humanos y todo lo demás?

Bueno, de lo que yo conozco, todas estas capacidades existen gracias a un concepto de capas o niveles de abstracción. Por ejemplo una primera capa consiste en que con ceros y unos, que son las "letras" del lenguaje o "bits" se pueden formar "palabras" o "bytes" de 8, 16, 32 o 64 bits.

Con dos bits solo se pueden representar los primeros 4 números: 00, 01, 10 y 11, que corresponden a 1,2,3,4 si no me equivoco. 

Pero si usamos palabras de 8 bits podemos usar 256 números, si usamos palabras de 16 bits podemos manejar hasta 65.536 números, si usamos palabras de 32 bits podemos disponer de 4.294.967.296 números y si usamos palabras de 64 bits -que es lo que usan los computadores actuales ¡podemos representar la friolera de 18.446.744.073.709.551.616 números!

Hemos hablado hasta ahora solo de números pero sabemos que los computadores trabajan con palabras ¿cómo se hace? Es muy sencillo, a cada letra y símbolo se hace corresponder un número, eso se llama "Código Ascii" y cuando a un computador le advertimos que lo que estamos mandando es un caracter Ascii, si recibe el número 65 (1000001 en binario) eso se interpreta como el caracter A y así para cada letra y símbolo.

Claro que esa conversión existe en una capa de abstracción mucho más arriba. El secreto que hace tan poderosos a los computadores es que se diseñan en capas. En su nivel más bajo está  la máquina de Turing. En un siguiente nivel está "el bus" o canal, que comunica a las distintas partes del computador y usa palabras de 32 o 64 bytes. Encima de eso están las memorias, que son controladas por otras máquinas de Turing y así, capa tras capa, una sobre otra.

Nosotros sabemos que existen esas capas, pero las que están más abajo no las tocamos prácticamente nunca, sabemos que existen, alguna vez se hicieron, funcionan y ya está. En cuanto al computador como maquina existen solamente siete capas estandarizadas en el Modelo OSI, que van de lo más primitivo (nivel de máquina) a lo más abstracto (nivel de aplicaciones).

Pero los programas -instrucciones almacenadas- también se van acumulando por capas. La máquina de Turing que tiene el computador solo entiende unos y ceros, es binaria, entonces la primera capa que tienen todos los procesadores se llama "lenguaje de máquina", encima de este viene el "set de instrucciones" que se escribe usando ciertos nemotécticos que permiten instruir a la máquina de Turing mover, borrar, reemplazar, etc. El set de instrucciones de los 8086/8088 se puede ver aquí. Es claro que son instrucciones para la máquina de Turing.

Los programas de más bajo nivel se escriben usando los nemotécnicos del set de instrucciones del procesador. Teóricamente se podría programar con unos y ceros pero es para volverse loco, los electrónicos que estudiamos con el SDK-80 tenemos pésimos recuerdos de esa tarea inútil y tediosa.

Desde allí se van acumulando capas de lenguajes cada vez más simplificados, por ejemplo el Assembler, lenguajes intermedios de los compiladores y los lenguajes de alto nivel como C++, Python, Visual Basic, Java Script, Ruby on Rails o tantos otros.

En ese alto nivel, o sea la capa más sencilla es donde entra el 99% de los programadores, que diseñan y codifican las aplicaciones como Twitter, Facebook y todo lo demás. Los programadores en los niveles más bajos son poquísimos en comparación porque se necesitan muchos menos.

Podríamos hacer la comparación del programador de aplicaciones como el mecánico y el programador de bajo nivel como el ingeniero que diseña y construye autos: se necesitan muchísimos más mecánicos que diseñadores y constructores.

Existe una gran mitología en torno a los "hackers" y a los "genios de la computación" que trabajan codificando en Google, presentándolos como tipos superdotados o a lo menos muy inteligentes. 

Es todo lo contrario, la programación -en todos sus niveles- es sumamente sencilla, inclusive los que se dedican a hackear sistemas por Internet no tienen nada de brillante ni inventan nada, simplemente invierte mucho tiempo y paciencia para encontrar brechas de seguridad, cosa que no es nada de otro mundo.

Uno de mis cursos en Udemy se llama "Cualquiera puede programar" y es cierto,  se puede aprender cualquier lenguaje de programación desde cero en un mes, con eso basta y sobra, especialmente cuando se conoce un lenguaje, aprender otros es sumamente fácil y muchos programadores se quedan con un solo lenguaje de puro flojos, como fue mi caso.

Resumiendo porque el asunto se me alargó demasiado, programar es escribir listas de instrucciones para la Máquina de Turing que tienen todos los computadores, pero no se escriben en lenguaje de máquina ni en el set de instrucciones, ni en Assembler (a menos que se esté programando un controlador o algo así).

Las instrucciones se escriben en el 99% de los casos en lenguajes de alto nivel, es decir que son interpretados -tal como si hablamos en español a un intérprete y este le explica lo que dijimos a un chino en su idioma, es exactamente lo mismo, pero el intérprete no es un humano sino otro programa, llamado compilador o intérprete según sea el caso.

Creo que en un futuro cercano los programadores de aplicaciones se quedarán cesantes, es un trabajo mecánico que solo requiere ser meticuloso y enfocado, no se necesita ser inteligente ni siquiera tener grandes conocimientos de nada. De hecho una de las aplicaciones más prácticas de la "inteligencia artificial" es la creación automática de código a partir de unas especificaciones de lo que queremos obtener.

Bueno, eso es la programación en esencia. Podríamos darnos muchas más vueltas en los detalles pero ya me he extendido demasiado y creo que eso es lo principal.

13 comentarios:

  1. ahora me queda claro, gracias Tomas, un abrazo

    ResponderBorrar
  2. Jajaja.... grande Tomas!! ... la materia completa de un semestre en cualquier universidad o instituto explicada en un post sencillo y de fácil entendimiento. Un cra...
    Jorge

    ResponderBorrar
    Respuestas
    1. Hola Jorge, a mi me pasaba cada semestre que tenía que hacer clases de computación empresarial, sistemas y cosas por el estilo en la universidad, ¡me ponía a pensar que enseñar y a lo más me daba tema para dos semanas!
      Entonces tenía que estirar el chicle y poner rellenos, no quedaba otra jaja

      Borrar
  3. Me hiciste retroceder hasta 1995, cuando comencé a estudiar para técnico en programación de aplicaciones computacionales. Comencé con Pascal, que era super sencillo de aprender, para despues pasarme a COBOL y después a C++. como justo me pilló la crisis asiática y darme cuenta que lo que aprendí ya estaba obsoleto, me decanté por Visual Basic y SQL para terminar aprendiendo HTML5 y algo de Python, pero por razones de tiempo, dedicación e interes no seguí.

    Sobre lo de los algoritmos, llegué a la conclusion de que vivimos un tremendo algoritmo llamado vida, con muchas subrutinas, como la que estoy haciendo en estos momentos.

    ResponderBorrar
    Respuestas
    1. Claro José, todos los lenguajes son prácticamente los mismo en el fondo pero hay dos "formas" de escribirlos, una derivada del Pascal, con corchetes y una topología más horizontal (C, C++, los Java, etc) y los de la familia del Fortran, que son listas más o menos verticales (Basic, VBA, Python, etc.), es más que nada una diferencia estética pero deja mucha inercia, es notable que hayas pasado del Pascal al Visual Basic sin problema)
      Yo creo que es malo aprender un lenguaje en una universidad o instituto, eso perjudica bastante porque la manera formal de enseñar a programar es pésima, hacen una especie de "problemas de ingenio" que no sirven para nada y se pierde tiempo que se podría aprovechar aprendiendo la artesanía de la codificación.
      Esto último solo se puede aprender programando, primero copias código ya hecho y tratas de entenderlo, después lo empiezas a modificar, lo compartes con otros que están en lo mismo y allí adquieres todos los trucos y las malas prácticas que necesitar para codificar con rapidez.
      Después si tiene que trabajar como parte de un equipo tienes que acostumbrarte de nuevo a las normas y a las buenas prácticas, pero en ese orden, primero debes tener la habilidad para codificar rápido y fluido, después aprendes a hacerlo correctamente.
      El gran error cuando contratan a programadores es darles una especie de problemas de ingenio, que son muy populares y decirle al candidato que lo "resuelva". Eso no sirve para nada porque en el mundo real del trabajo lo que menos se necesita son tipos ocurrentes, un programador debe ser meticuloso y enfocado, mientras más bruto, mejor.
      Las universidades e institutos han hecho un mal enorme con la enseñanza de la programación, son verdaderas fábricas de inútiles

      Borrar
  4. "En cuanto al computador como maquina existen solamente siete capas estandarizadas en el Modelo OSI, que van de lo más primitivo (nivel de máquina) a lo más abstracto (nivel de aplicaciones)".

    Creo que de ahí viene eso de la "capa 8" (supuestas fallas que finalmente son culpa del mal uso y/o ignorancia del usuario)...

    Saludos,
    El triministro.

    ResponderBorrar
    Respuestas
    1. Claro, ese es un chiste de computines desde los ochentas!! Las capas son
      1 Física
      2 Enlace de datos
      3 Red
      4 Transporte
      5 Sesión
      6 Presentación
      7 Aplicación
      8 EL HUEVÓN
      ¡Ese es el modelo OSI+ de 8 capas

      Y antes que un purista me corrija lo haré yo mismo, el modelo OSI es para comunicación de datos no para computadores, pero sirve muy bien para ilustrar las capas en la computación, que es todo un temazo

      El alemán ese cuyo apellido no recuerdo en estos momentos, me juega malas pasadas a veces jaja

      Borrar
  5. A propósito, yo aprendí a programar como a los 9 años, en BASIC, con un computador Sinclair ZX Spectrum de 48 KB, y después en un Atari 800 XL. Era un lenguaje sumamente estructurado, en el que cada línea de código se numeraba y se la podía invocar desde otra mediante sentencias "goto" y "gosub". Además, en ese tiempo no había compatibilidad, por lo que programar con un mismo lenguaje era diferente si se cambiaba de computador, así que un código de BASIC hecho para Atari no servía en un Commodore ni en un Spectrum.

    Después, en la universidad, aprendí el infernal lenguaje Scheme (un "hijo" de LISP), algo de Pascal, C y C++. Éste último es el que más me gustó. Debo decir que al principio me costó un poco pasar de la estructura de código basado en líneas, del BASIC, al tipo "texto escrito", basado más en rutinas, de los otros. Una pequeña muestra de cómo nos afectan las fijaciones que progresivamente vamos adquiriendo.

    Tuve también algunos acercamientos a Visual Basic y a VBA, que ingenuamente creí que se parecerían al BASIC que yo conocía. Nada más lejos de la realidad!

    Ciertamente, como todo niño de la época, en algún momento me enseñaron lenguaje LOGO, el de la tortuguita, que se suponía que era para "acercar a los niños a la programación", pero nunca lo vi así: para mí era un juego para hacer dibujos, lo que -una vez más- muestra cómo se fracasa cuando los adultos hacen cosas "para que los niños aprendan". Para eso hay que tener mentalidad de niño, la que definitivamente se pierde cuando se deja de serlo, y de nada sirve haberla tenido alguna vez...

    Saludos,
    El triministro.

    ResponderBorrar
    Respuestas
    1. Los niños aprenden mucho mejor a programar que los que aprenden de adultos y no tiene nada que ver que sean "nativos digitales", más inteligentes o cualquiera de esas tonteras que se mencionan, simplemente tienen más tiempo, ponen más dedicación y aprenden a programar igual que a hablar: imitando y haciendo variaciones.

      Borrar
  6. Se te cayó el carnet, el ASCII ya prácticamente no existe :-)

    ResponderBorrar
    Respuestas
    1. baia baia, en mis tiempos hijitos el ASCII era el rey.
      Ahora me voy a buscar unos pregramas que tengo en un stack de tarjetas por ahi, solo espero que no se la hayan comido los ratones

      Borrar

"Send me a postcard, drop me a line
Stating point of view
Indicate precisely what you mean to say
Yours sincerely, wasting away
Give me your answer, fill in a form
Mine for evermore
Will you still need me, will you still feed me
When I'm sixty-four"