Archivo

Archive for the ‘programación’ Category

Las cosas que no soporto que diga un programador

febrero 1, 2015 46 comentarios

…y quizás tampoco las soportan los demás programadores.

En mi ordenador funciona

Si el código no funciona en un ordenador con toda las dependencias adecuadas instaladas es un error de tu programa, sin dudas, no hay excusas. Nunca digas esta frase, sólo demuestra que todavía no estás preparado ni para asumir la responsabilidad de tu propio código. Si eres alumno demuestra que no te interesa aprender sólo aprobar con el menor esfuerzo posible… además de tomar como tonto al profesor, como si nunca hubiese oído esta excusa (la oímos decenas de veces cada vez que se presentan prácticas).

El programa peta/se cuelga/no funciona ¿qué es?

Otro error típico, sobre todo de alumnos y jóvenes que preguntan al profesor o a un compañero. Si tú que conoces bien tu código no puedes encontrar el error, ¿cómo pretendes que otro te lo arregle sin conocer el mínimo detalle? Siempre tienes que ir con el código en cuestión, indicando la función o la línea donde falla y en qué condiciones. Si no lo haces así demuestra que todavía eres incapaz de analizar tu propio código. Un buen programador es capaz de analizar y estudiar cualquier código, algunos les puede costar minutos, otros muchas horas, pero es esencial saber hacerlo. Se aprende con mucha práctica, pero hay que comenzar con el código de uno mismo.

Pero si pasa los tests

Desde que se empezó a hablar de test units parece que algunos lo toman con el resultado de los dioses. Pero no, un test sólo verifica los bugs ya detectados o los que se imaginó el que los programó. Seguramente no consideró todos los posibles fallos con las diferentes condiciones que se pueden dar en el código que verifica. Sobre todo si es de un código que todavía no existe y que debe ser programado por otras personas. Por ello no es excusa que pase el test, en todo caso hay que pedir que se mejore el test con el caso descubierto en tu código. Mejor aún si tú mismo lo haces.

Eso no me lo enseñaron

No puedes ser espectador pasivo de tu aprendizaje ni esperar que los demás sean los responsables de enseñarte todo lo que necesitas aprender para cada una de tus tareas como programador. Además es imposible que en unos pocos años de estudio puedas aprender todas las cosas que necesitarás durantes las décadas futuras en tu profesión. Es cierto que muchas cosas que deberían darse no se estudian (y que también critico, a veces chillando por la universidad) pero una respuesta así indica que no asumes responsabilidad de tus conocimientos. Quizás peor, que no te enteraste qué es lo que debes aprender, un psicólogo te explicaría que es “deficiencia meta cognitiva”. En todo caso sólo di “no lo conocía” o “no se me ocurrió, ahora mismo me pongo”.

Pero el código funciona

Esta es una respuesta también muy habitual entre estudiantes y programadores novatos. Es como si un novelista respondiese a la mala crítica con un “pero si al final el mayordomo era el asesino, se entiende”. Se da en dos situaciones diferentes:

  • El código es ilegible: Hay programadores que todavía piensan que los lenguajes de alto nivel se hacen para los ordenadores no para los humanos. Pero no es así, llevamos 70 años diseñando y desarrollando lenguajes de alto nivel principalmente para facilitar el trabajo a las personas, y no sólo al programador original, sobre todo a los demás que tienen que entender o modificar el programa. Una de las condiciones fundamentales de todo programador es que su programa se legible, que sea “fácil y agradable de leer”. Hay novelas que son fáciles de leer, otras que son complejas, hay cortas y otras largas y pesadas, pero todas respetan normas básicas: sintaxis, gramática, oraciones con sustantivo verbo y objeto, limitaciones de adjetivos, puntuación, párrafos, separación entre palabras, líneas, párrafos y bordes de la página. El código fuente de un programa debe ser similar, hay normas generales (por ejemplo espaciado, sangrado, nombres de funciones variables, ficheros, etc.) y otras que son “idiomáticas” de cada lenguaje o de programadores.Lo fundamental es aprender esas normas, respetar tantos las generales como las particulares. Si no lo haces no sólo demuestra la incapacidad como programador, también una falta de respeto a los que tendrán que analizar tu código (sean estos los colegas o los profesores que te tienen que poner una nota).
  • La solución es inadecuada: Muchas veces recurren a soluciones que no sólo no son óptimas, también las peores de su clase. Por ejemplo re-implementar un ordenamiento de burbuja cuando tienen la función qsort(), o una búsqueda secuencial cuando el array está ordenado (los dos últimos son problemas de no recurrir a la menor complejidad de ejecución bien conocidas), o hacer una espera activa cuando tienen primitivas sencillas con bloqueo, etc. En la “ciencias de la computación” se estudian estos temas, algunos de ellos son fundamentales y de conocimiento obligatorio. No sirve que el programa funcione para un caso concreto, debe funcionar para todos los casos previstos y con la eficiencia “formal” bien conocida en el área. Conocer esos temas es parte del proceso de aprendizaje de un programador, si alguien te indica que la solución es errónea quizás pueda estar equivocado, pero nunca la excusa puede ser “pero funciona”.

Vaya mierda de código, debería estar programado con ponga_aquí_las_últimas_tecnologías_o_frameworks

Es el típico error que hemos cometido todos. Normalmente se hace sin tener en cuenta las condiciones del momento en que comenzó a desarrollarse, los requerimientos iniciales, la tecnología y recursos disponible, ni la multitud de limitaciones que tienen todos los proyectos. Además, el estado actual de un proyecto es la evolución durante años de programadores, tecnologías y objetivos cambiantes. Cada uno de estos elementos aporta a la deuda tecnológica, tú también generarás la misma deuda, todos los hacemos.

Así que nunca sueltes esta frase ligeramente, sobre todo si vas a una empresa, solo demostrarás que además de ignorante no tienes respeto por el trabajo de tus colegas. Quizás el código realmente sea malo, pero antes de decir una palabra espera un tiempo, aprende de su historia, y si aún así piensas que puede mejorarse propón la solución, o mejor, envía el parche.

Un secreto: cuando los programadores oímos a otro soltar esta frase de un código que ni conoce pensamos “no podía faltar el gilipollas”. No hagas de gilipollas.

Yo hubiese usado ponga_aquí_la_librería_de_moda

Si dices esto es porque alguien te preguntó que te parece lo que implementó. Decirle que hubieses usado otra librería ya no ayuda y quizás estés equivocado o no conoces todos los detalles. Es mejor analizar antes, proponer cambios concretos y reservar esta frase sólo si no hay una solución adecuada (aunque muy raro que no haya soluciones). Nunca nunca nunca sueltes esta frase sólo por ver las primeras líneas de “include” o “package”.

Yo hubiese desarrollado un nivel intermedio de servicios ponga_aquí_el_formato_de_moda

Es el típico ejemplo del programador entusiasmado que tiende a la “sobre ingeniería” y aplicar en un proyecto todas las técnicas y palabros que aprendió o leyó. Pero una una ingeniería se basa en hacer las cosas en su justa simplicidad, agregar servicios y capas intermedias con formatos de intercambio (que requieren conversiones y serializaciones/deserializaciones, antes de ayer era binario, ayer era XML, hoy es JSON, mañana quién sabe) muy pocas veces está justificado y casi nunca elimina complejidad, todo lo contrario. Lo que suelen añadir es complejidad, latencias, consumo, necesidad de recursos y más administración.

Depende del tipo de proyecto sí que es necesario desarrollar una capa de traducción de este tipo, por ejemplo cuando haces el backend/API de servidor para apps móviles. En estos casos la capa es casi un objetivo y requerimiento inicial del desarrollo, no una idea creativa para aumentar la simplicidad de desarrollo y mantenimiento.

Intenta mantener el programa lo suficientemente simple para que se cumplan los plazos y la complejidad esté controlada, si el proyecto crece y necesita agregar capas y servicios se hará en su momento. En todo caso deberías preocuparte más de la estructura de datos: que sean simples y flexibles para expandirlas y usarla de otras maneras. Y si aún así te parece que una capa intermedia con traducción es formatos es necesaria, consúltalo antes con los programadores más expertos. Nunca lo plantees como primera opción, suele generar unos :roll: importantes.

La universidad debería enseñar ponga_aquí_la_última_moda

De este tema ya escribí varias veces, la última en Lo que se aprende, o debería, en la carrera de informática, pero insisto, el tiempo es limitado, no se pueden aprender todas las tecnologías que podrías encontrarte en tu carrera profesional. Antes eran cinco años, ahora cuatro, y ya hay una ley para que sea de tres. Ni en las mejores universidades del mundo podrán enseñarte todo lo que cree importante cada uno de los “actores del mercado”, si fuese tan sencillo las currículas no serían tema de debate y cambios continuos hasta en la ACM.

Por otro lado las “tecnologías de programación” no cambian tan radicalmente, muchas veces se usan ideas que ya se estudiaron y desarrollaron antes. Por ejemplo el tema de concurrencia tan estudiado en sistemas operativos y mainframes hoy vuelve a estar de moda por los procesadores de múltiples núcleos, sí ha avanzado pero los principios son los mismos que hace 40 años. Otro ejemplo, NoSQL, las mismas técnicas de los años 70 pero usadas para tener bases de datos distribuidas mucho más limitadas que las relacionales, ¿hace falta tener una asignatura para saber cómo funcionan los hashes y su almacenamiento en fichero que viste en estructuras de datos o “algoritmia” (signifique lo que signifique)?.

¿Realmente hacen falta asignaturas obligatorias específicas sólo para “desarrollo de apps” cuando hoy lo más raro que te encuentras es que tienes que tener un thread para conectarte a un servidor o mostrar imágenes o listados largos? (ojo, sí que deben ser parte de prácticas o laboratorios, que ya se hacen en la mayoría de universidades).

¿Por qué no usaste el framework X?

Qué pesadilla, no hace falta seguir, ¿no?

Ninguno de los frameworks se ajusta a lo que necesitamos, vamos a desarrollar uno mejor

:roll: :roll: :roll:

Concurrencia: los problemas del hardware moderno y barreras de memoria

enero 25, 2015 25 comentarios

Este artículo incluye un capítulo, La realidad del hardware moderno, del libro que estoy escribiendo: Principios de concurrencia.

Todo el código que desarrollo para los ejemplos están en Github.

Leer más…

Categorías:concurrencia, programación Etiquetas: ,

¿Qué tecnologías utilizarías?

enero 19, 2015 13 comentarios

Hoy un viejo conocido me hizo esta pregunta:

Estuve a punto de contestar pero me di cuenta que soy incapaz, y que tampoco debería. Lo haré al final, como una cuestión muy personal y después de un rant de matizaciones.

Hace cinco años habría respondido sin dudar (de hecho varias veces lo hice) Python con Django. No es que me hayan dejado de gustar pero el mundo cambió bastante. Hay nuevas tecnologías como Javascript sobre node.js (y sus versiones multihilos) y Go por citar un par. Además Django se volvió un framework muy grande que quizás sea un overkill para muchos proyectos.

Pero tampoco es lo más importante, creo que la edad y la experiencia me hace ser mucho más escéptico de los lenguajes metodologías toolkits y frameworks que “solucionan todos los problemas”. Fui testigo de los problemas de cada silver bullet y hype de los últimos años. Luego están los problemas derivados de usar herramientas cada vez más complejas, llegamos a tal punto de complejidad e interdependencia de los diferentes frameworks y toolkits que hacer una actualización de versión de algunos de ellos ya es considerado un gran peligro, por lo que tienen que desarrollarse herramientas para congelar proyectos (por ejemplo los dockers).

Cuando comencé a programar Menéame (ya se cumplirán 10 años) dominaba y estaba actualizado en C, C++, Perl y PHP. A Python lo usé académicamente (hay muchas librerías matemáticas y de grafos) pero no lo controlaba. C y C++ estaban descartados para desarrollo web, Perl también porque ya estaba decayendo mucho y en aquellos años ya se había comenzado a discutir el cambio radical al Perl 6 (un lenguaje diferente y sin comunidad ni herramientas maduras). Comencé a programar en Python, pero no había frameworks, había que hacer casi todo, me pasaba más tiempo leyendo que escribiendo. Creo que a las pocas horas lo dejé, no acabaría nunca y sólo había pensado dedicarle dos semanas (que es lo que me tomó publicar la primera versión) y empecé con PHP (aunque luego hice cosas más complejas en Python para web y me encantó).

Como lenguaje PHP es muy malo, tiene montón de inconsistencias y era bastante peor hace diez años que ahora (el soporte de clases era más que rudimentario y lento -no había ni constructores-, no había funciones lambda, anónimas ni clausuras, todavía pasa objetos por referencias pero arrays por copia, etc.), ahora hay muy buenos frameworks (en aquellos años sólo había Smarty), el sistema de caché por defecto (OPCache) es excelente y hay herramientas para verificación y desarrollo de test de unidades. Ha cambiado mucho, pero sigue con sus problemas de que no ha tenido un diseño elegante y coherente desde el principio. No sigo, aquí tenéis un artículo de todos los problemas de PHP como lenguaje.

Lo anterior significó que en ese momento tuvimos que implementar desde cero módulos que hoy los incluye cualquier framework básico: autentificación de usuarios, capa de acceso a la base de datos de bajo nivel, una abstracción mínima de active record (es el patrón que se usaba), sistemas de plantillas eficientes edición de tablas de la base de datos, url router, etc. Pero no ha sido tan malo, de hecho fue una experiencia muy enriquecedora, me forzó a aprender cada una de esas técnicas y al final tiene una gran ventaja: no hay casi dependencias con módulos externos (sólo el mysqli, memcache y GD del propio PHP). Dado que siempre me limité a los “estándares” del lenguaje y que refactorizo continuamente para solucionar mis propias (e inmensas) deudas tecnológicas no tuve problemas en hacer funcionar el código en las últimas versiones disponibles de PHP (hoy la 5.5.9 de la Ubuntu 14.04 LTS).

Es decir, reconozco todas las carencias de PHP y las mías propias, pero no ha sido una mala experiencia. En lo que toca al lenguaje no me limitó nada a la hora de solucionar ningún problema (aunque en la parte de scripts del backend enseguida empecé a usar Perl y desde hace varios años exclusivamente Python).

¿Es válido sacar conclusiones de mi experiencia y aplicarlas a la mayoría de proyectos de desarrollo? Por supuesto que no.

¿Recomendaría PHP? Lo dudo, pero con las herramientas que hay hoy y la evolución de PHP (además de su excelente documentación) es una apuesta segura. Ningún proyecto va a fracasar por culpa de PHP, y hay muchos programadores disponibles.

¿Qué elegiría como cuestión personal? Todavía no, ya lo diré al final ;) pero como norma general diría que un lenguaje y las tecnologías asociadas deben cumplir las siguientes características básicas:

  • Gustos e intereses personales o del grupo: Es lo más importante, si personalmente te apetece hacerlo en un lenguaje en particular y tienes el tiempo para dominarlo, adelante. Si tu grupo de desarrollo tiene mucha experiencia en uno y no tienen motivaciones importantes para cambiar, que sigan con el mismo.
  • Libres: A estas alturas no puedo comprender que un particular o empresa desarrolle sobre herramientas tan básicas como el lenguaje en uno que no sea libre. No tiene sentido, he visto como todas han terminado pagando el error.
  • Disponibilidad de frameworks o toolkits: Ambos son ya herramientas básicas que permiten desarrollar tanto para web como para backend de aplicaciones móviles. Con la madurez y variedad que hay es impensable comenzar desde cero como hice yo. Eso sí, buscaría lo más sencillo y ligero que se adecue al proyecto.
  • Con comunidad: Así estarás seguro que las herramientas que uses evolucionarán, estarán disponibles y mantenidas muchos años y que encontrarás alguien que tuvo antes los mismos problemas y te ayudará con la solución.
  • Lenguajes que ayuden sin burocracia exagerada: No hace falta que añada nada a lo que explica Rob Pike en el siguiente vídeo. Sólo recalcar que un lenguaje que tiene libros con 71 patrones diferentes que debes usar y que además cada conjunto de ellos tiene detractores y teólogos no es un lenguaje divertido. Si además es un lenguaje con el que no puedes desarrollar cómodamente desde cualquier editor de texto sino que requiere de un complejo IDE para hacerlo tampoco es un lenguaje que permita soluciones simples a problemas complejos y menos aún soluciones simples a problemas sencillos.

Me juego

  • Python, Ruby, PHP (y sus respectivos frameworks) son apuestas seguras, maduras y divertidas.
  • Java es lo mismo quitada la diversión y con demasiada burocracia, pero Scala y Clojure le agregan diversión y te quitan de encima tantos teólogos y promotores de ritos y patrones.
  • Javascript (sobre node.js o sus versiones multi hilos) es una apuesta segura y prometedora.
  • Go es muy prometedor, me encanta, la sencillez y potencia de un C del siglo XXI.

¿Qué elegiría hoy para un proyecto desde cero? Go. Aunque no sé qué framework usaría, hay mucho debate.

Categorías:personal, programación Etiquetas: , , , , , ,

Las elecciones de Podemos, voto electrónico, y AgoraVoting (y 2)

noviembre 4, 2014 16 comentarios

Hace unos días escribí un apunte sobre las tan comentadas elecciones electrónicas de Podemos. Comencé el artículo con una descripción de los requisitos que tiene que tener un sistema de votación (de papeleta y electrónico) y el procedimiento que se seguía en las votaciones tradicionales para asegurar que se cumplan esos requisitos (voto secreto y anónimo, no adulteración, impedir agregar votos, auditoría…).

En ese apunte me limité a comentar el problema del censo de Podemos, y cómo sólo eso hacía que se incumpliesen varios de los requisitos mencionados anteriormente. Aquí introduzco un leve paréntesis para dejar claras algunas cosas (lo pongo “entrecomillado” para que te lo puedas saltar).

Leer más…

Ciencias de la computación e ingeniería, y [algunas de] sus diferencias

octubre 7, 2014 17 comentarios

Hay un tema que se estudia en todas las carreras de informática, el de “sincronización, concurrencia y exclusión mutua entre procesos”. Surgió en la década de 1950 cuando empezaron a desarrollarse los primeros sistemas con multiprogramación. Aunque surgió como problemática de sistemas operativos se ha convertido en un tema de general y fundamental en informática. Todas las carreras de informática incluyen su estudio tanto en las asignaturas de sistemas operativos como en otras específicas de programación concurrente.

El tema de concurrencia (y su hermano más complejo “programación distribuida”) es un típico tema de “ciencias de la computación”, donde se estudian los algoritmos y se prueban formalmente que funcionan: se demuestra que aseguran exclusión mutua, que no produce inanición (starvation), ni interbloqueos (deadlocks). No es simple enseñar estos temas y sus soluciones obligan a pensar de otro manera, un programa ya no es una serie secuencial de instrucciones, sino que se mete por medio una intercalación “no controlada” y no determinística de otras instrucciones de procesos independientes.

El tema de exclusión mutua es un tema relativamente sencillo de demostrar, por ejemplo este código que suma una variable desde cero hasta 99.999.999 (cien millones menos uno), pero no lo hace de una forma tradicional, sino que son dos hilos (threads) los que la incrementan individualmente. Podéis compilarlo y probarlo (no olvidéis de compilarlo con la opción -pthread), veréis que produce unos errores enormes. El problema es que dos procesos diferentes acceden al mismo recurso compartido (la variable count) y se “pierden” operaciones debido a las interrupciones e intercalaciones.

Este caso es muy estudiado y todas las asignaturas comienzan con algo similar, es la exclusión mutua entre [solo] dos procesos. Así se estudian los “cuatro intentos” para solucionarlo, luego el algoritmo de Dekker y finalmente el de Peterson (aquí los tenéis a todos).

Así se puede demostrar formalmente que funciona correctamente, que asegura exclusión mutua y tal y cual. Pero si lo implementas (aquí lo tenéis listo para compilar y ejecutar con el ejemplo anterior) y lo pruebas en cualquier ordenador moderno verás que… falla como escopeta de feria.

¿Qué pasó? ¿Falla la teoría? ¿Fallan las demostraciones? ¿Los teóricos de las ciencias de la computación no sirven para nada?

Actualización: la respuesta.

Ninguna de ellas, este es un típico ejemplo donde la teoría se distanció de la “realidad”, o mejor dicho, donde la evolución tecnológica de los microprocesadores modernos hace que las técnicas de concurrencia que dábamos por buenas (y que lo son formalmente y con todos los modelos de computación y/o de lenguajes “tradicionales”) ya no funcionen. Es la diferencia entre hacer “sólo ciencia” y la “ingeniería” (es decir, resolver problemas que te impone la realidad, no tan perfecta como la teoría).

Tampoco es para los ingenieros se feliciten y miren por encima del hombro a los teóricos, porque la mayoría de “ingenieros” tampoco saben explicar o resolver este problema, muchas veces ni siquiera son capaces de identificarlo (no, si estás leyendo este blog no eres de la “media”, eres bastante friki y al menos lo habrás oído, o sabrás buscar rápidamente en la Wikipedia o Stackoverflow ;) ).

Si no tienes idea de qué está pasando, ya lo explicaré en un comentario (si nadie lo hace antes), pero mientras tanto puedes ir probando este otro código que sí funciona y sólo difiere en una línea con el anterior.

Sólo quería recordar que aún en ciencias tan “formales” como la informática la teoría no siempre funciona en la práctica, que el tema de concurrencia tiene sus complejidades no siempre a la vista, que un buen ingeniero debe saber reconocer esos problemas y poder solucionarlo, y que esto exige que conozcamos bastante de detalles del hardware y microprocesadores actuales.

No es nada simple, lleva su tiempo, y tendemos a pensar que lo sabemos todo. O que la “ingeniería informática” consiste en saber liderar sprints de Scrums con postits de colores fosforitos.

PS: Por estas cosas, entre muchas, la informática es apasionante.

La compleja coreografía porque presionaste la letra A

abril 29, 2014 19 comentarios

Tu teclado detectó que presionaste la letra A, sus chips lo codifican en un scancode, este código es convertido en un señales eléctricas que se transmitirán por el cable USB al controlador que está conectado a la placa del ordenador. Este controlador detecta las señales eléctricas, las reconstruye en números binarios que almacena en un área de memoria del dispositivo, a continuación genera una solicitud de interrupción (IRQ) que será transmitida al microprocesador.

Esta interrupción está codificada y se recibe en el procesador en unas pins especiales para ellas, cuando llega la generada por la tecla que presionaste el procesador decide a qué core o procesador enviar esa petición (enrutamiento de interrupciones). Éste interrumpe lo que estaba ejecutando en ese momento,  analiza el IRQ, accede a una tabla de interrupciones (que fue rellenada cuando el sistema operativo se inició) donde le indica la dirección de la rutina del kernel que debe ejecutar. Cambia los registros necesarios, posiblemente invalida (flush) las cache y TLB del proceso anterior, cambia el nivel de ejecución del procesador a uno de con más privilegios y pasa a ejecutar la dirección indicada en la tabla de interrupciones.

La rutina del núcleo del sistema operativo analiza los registros y llama al gestor del controlador USB, que puede acceder a la memoria del dispositivo vía instrucciones de E/S del procesaor para que copie los datos a la memoria RAM. También llamará al gestor específico de teclado por USB (lo más probable es que sea el usbhdi) que convierte el scancode original en un código de caracteres vía una tabla de conversión (o mapa del teclado).

Una vez realizada las operaciones de transferencia de datos desde el dispositivo, se llaman a las rutinas de E/S de caracteres del núcleo. Éstas analizan qué proceso es el que debe recibir esa entrada de teclado, si usas un GNU/Linux con interfaz gráfica el proceso es el servidor X (X.org), copian los datos al área de memoria de dicho proceso, lo desbloquean y llaman al scheduler para que decida qué proceso debe ejecutar a continuación.

Al desbloquearse el proceso, éste pasa de la lista de procesos bloqueado a la lista de procesos listos para ejecutar. Allí el servidor X competirá por el procesador con otros procesos, eventualmente será seleccionado por el scheduler, este procederá a preparar al procesador (o núcleo) para que lo ejecute (cambio de contexto o context switch), invalidará las caches del proceso anterior, preparará las tablas de páginas básicas, cambia el privilegio del procesador al de uno de proceso normal y finalmente transfiere el control al proceso X.

Éste continúa su ejecución desde la llamada epoll o select que hizo para recibir E/S, analiza los datos que le dejó el sistema operativo y decide que es un letra picada en el teclado (el editor de texto, o la terminal, o el navegador web….), analiza cuál era el proceso interactivo que tiene la ventana activa en ese momento, codifica el evento en el protocolo X11, y se lo envía a dicho proceso vía memoria compartido o socket UNIX.

Al enviar el mensaje a otro proceso, se llama otra vez a una rutina del sistema operativo en un proceso similar al IRQ inicial, pero esta vez iniciado por una instrucción especial (interrupción por software) que hace que el procesador la trate de forma similar, selecciona un procesador para que la trate, analiza el código de interrupción y los registros que dejó el programa, cambia a modo privilegiado y llama a la rutina del kernel que tratará esta interrupción (posiblemente las de UNIX socket).

Esta rutina mira en las tablas de sockets cuál es el proceso receptor (el editor, terminal, navegador…), copia los datos necesarios, desbloquea al proceso moviéndolo a la cola de listo para ejecutar y llama al scheduler.

Eventualmente el proceso que debe recibir esa letra A es seleccionado por el scheduler, pasa a ejecución, continúa su ejecución desde el select o epoll, analiza la entrada, decide que hay que mostrarlo en pantalla, codifica la información necesaria (caracter, tipo de letra, posición, color, etc.) y la envía nuevamente -mediante un mensaje en protocolo X11- al servidor X.

Se repite de nuevo el proceso, interrupción de software, llamada a una rutina del núcleo y desbloqueo del servidor X que eventualmente es ejecutado.

Éste analiza el mensaje, detecta que tiene que dibujar una letra en la pantalla y llama a sus rutinas de dibujo de fuentes TrueType. Estas rutinas recuperan la información de la fuente necesaria (consisten de puntos en 2D), aplican los fórmulas necesarias que definen cómo debe dibujarse en la pantalla y llaman a las rutinas de DRI del kernel que lo harán, vía ayuda del gestor de la placa gráfica, en un complicado procedimiento de sincronización entre el servidor X, el gestor de la placa y la propia placa gráfica (que es otro ordenador muy potente y complejo, con su propio “sistema operativo”).

La letra A es dibujada así en la memoria del back buffer de la tarjeta, también se dibujan las otras ventanas con complicadas combinaciones y copias (compositing) para intentar minimizar todo lo que hay que re-dibujar. Cuando el back buffer está completo, se notifica a la placa gráfica que lo intercambie con el front buffer (lo que se visualiza por la pantalla), ésta espera que llegue el momento justo de sincronización con el monitor (para que no parpadee con mezcla de imágenes de ambos buffers) y finalmente hace el cambio y puedes ver lo que esperabas:

La letra A

Esta maravillosa coreografía de sincronización y paso de información ocurre cada vez que presionas una tecla, o mueves el ratón un pixel, o se empieza a bajar una imagen de la web. Y no sólo en tu PC o Mac, ocurre lo mismo en tu teléfono móvil, tu router WiFi, tu lector de libros, o tu smartwatch.

Todo esto que acabo de explicar ya funcionaba prácticamente igual desde finales de los años 70. Explico estas interacciones y algoritmos en mis clases de sistema operativo desde hace más de 20 años, pero nunca deja de maravillarme al nivel de complejidad y sofisticación al que hemos llegado en pocas décadas de informática.

 

 

 

Una técnica útil para el programador solitario (o sea, yo)

abril 24, 2014 13 comentarios

No sé si os pasa a todos, yo creo que sí, pero tenía serios problemas de organización y productividad en el desarrollo de Menéame. Quizás sea un caso especial, es un sistema complejo:

  • software relativamente grande y soy básicamente el único programador responsable de todos los módulos,
  • diversidad de lenguajes, PHP para la web, Python para scripts y programas “off line”, Perl por herencia de hace años,
  • base de datos grande e imposible de hacer alteraciones de las tablas por el tamaño de las mismas (ya veremos con el MySQL 5.6),
  • mucha manipulación de datos en la base de datos,
  • interacciones complejas de usuarios,
  • muchos controles de entradas y acciones de usuarios “externos”,
  • los usuarios piden muchas modificaciones, correcciones y detectan bugs que ni se te pasaron por la cabeza que podían ocurrir,
  • cada vez que se implementa una nueva característica (cada vez más complejas), aparecen nuevos bugs y sobre todo, los usuarios demandan muchas modificaciones y ań nuevas características complementarias.

Con todo esto, a veces me ocurría que me bloqueaba porque no sabía por dónde comenzar, o que pasos seguir, o cuál era el trabajo pendiente, cuáles son importantes, cuáles son urgentes, y cuáles secundarios que pueden esperar hasta tener ese momento de inspiración. Soy bastante desorganizado, y odio profundamente usar programas (los tipos “gestión de tickets”) para esto. Ya demasiado tengo con ventanas de editores, consolas de administración y páginas de manuales para encima tener que estar buscando una ventana perdida para ir leyendo y apuntando lo que estoy haciendo.

Leer más…

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 552 seguidores