Archive for 31 agosto 2006

Piso 76cm2 en pleno Chueca

Jueves, 31 \31UTC agosto , 2006

Txus me avisa de este interesante piso de alquiler, creo que habría que ir a echarle un vistazo.

Interfaces gráficas en entornos multihilo

Jueves, 31 \31UTC agosto , 2006

ProyectoRadio está implementado completamente sobre la plataforma .NET 2. No es que me guste más o menos que otras, pero como comenté en mi post sobre C, C# es un lenguaje que me parece muy potente y la plataforma permite desarrollar proyectos bastante complejos de una forma asequible.

La naturaleza del software requiere hacer tareas pesadas o largas. Por ejemplo las simulaciones de coberturas, la importación o la exportación de datos, la carga de mapas, etc son tareas que cuando se ejectuan tienen el control del programa durante un tiempo bastante importante.

La naturaleza de las aplicaciones .NET con interfaz gráfica de usuario Windows.Forms es básicamente la misma que la de la API de Windows nativa, solo que muy organizada y bonita. Las aplicaciones son del tipo “orientadas a eventos”. Esto quiere decir que existe un hilo de ejecución único asociado a la aplicación que está siempre dormido. Cuando la aplicación recibe un evento: Click en un botón o desplazamiento de una barra, el sistema le envía un mensaje que la función principal ejectua (todo esto de forma oculta claro) y llama a la función apropiada para manejar ese click.

Lo que el programador escribe son las funciones asociadas a los eventos. Cada control de usuario puede tener unos cuantos eventos. Por ejemplo un control de tipo Button tiene el evento Click. En C# se pueden asociar funciones a eventos de tal forma que si nosotros queremos gestionar el evento de Click solo hay que asociar una función al evento y cada vez que se pulse el botón se llamara a nuestra función. Bien.

Hasta aquí todo parece fácil. El problema veradero viene cuando asociado a ese handler o función asociada a un evento hay una operación muy lenta o costosa. Ejemplos un poco más arriba. Si no se hace nada y sin más se ejecuta la operación, el hilo de ejecución, que es único está entretenido operando y haciendo cuentas costosas y por tanto no retorna del evento, y por supuesto no puede atender más eventos del sistema, por mucho que estos lleguen. El resultado es bastante conocido, la interfaz de usuario (UI) se queda “como bloqueada” y si movemos la ventana fuera del escritorio y la traemos de nuevo se queda blanca. Normal, no se está gestionando el evento de repintado :).

Esto me ha traído bastantes problemillas. A primera vista la solución parece fácil. Usar un hilo de ejecución paralelo para ejecutar la tarea pesada. La idea es tan sencilla como demoníaca. Esto es fácil en C# y .NET. Hay una clase asociada a un hilo o thread de ejecución. Sin más que instanciar uno de estos objetos, pasarle una función de ejecución y lanzarla ya tenemos un hilo ejecutándose en paralelo al hilo principal. Bueno, pues bien, ahora nuestro hilo principal, después de lanzar el hilo pesado retorna del gestor del evento y la interfaz sigue respondiendo como es debido. Claro.

Ójala fuera todo así de fácil. Si estamos familiarizados con los sistemas paralelos y la programación concurrente rápidamente vamos a ver un problemilla: Hay que garantizar la coherencia de los datos. Esto quiere decir básicamente que todos los datos que necesite el hilo pesado ejecutándose en background no se modifiquen, o lo hagan de forma coherente, por el hilo principal de ejecución. Esto implica que cualquier pulsación de botón, desplazamiento, etc no modifique los datos importantes. Formas de garantizar esto existen, claro. Una de ellas es sin más haciendo una copia de los datos (shadow) y que estos sean los usados por el hilo de background. No creo que sea la ideal. Tenemos otras como usar mecanismos de interlocking. Ejemplos hay variados: Mutexes, CriticalRegions, Semaphores… lo que sea para bloquear al hilo principal de modificar los datos del hilo pesado. Hay que tener de nuevo cuidado de no bloquear la UI en uno de estos mecanismos.

Además de estos problemas evidentes y muy conocidos, la UI presenta otros problemillas cuando se usa en un entorno multihilo. Solo se puede acceder o modificar los valores de los controles, incluyendo su repintado, desde el hilo donde se crearon. Así, si se llama al constructor de un boton en el hilo principal, que será lo común, cualquier acceso que se haga desde el hilo secundario a este botón: Ver su estado, deshabilitarlo, etc… lanzará una excepción muy bonita y nos obligará a salir de la aplicación con toda probabilidad.

Me imagino que es una forma de proteger la implementación de los controles sin necesidad de complicados mecanismos de interbloqueo pero es una putada. Si te das cuenta que desde el hilo de la tarea pesada es necesario modificar o acceder a la UI, para dar un poquito de feedback o para actualizar una vista, pues cuidadín.

Alternativas a este problema hay muchas, pero principalmente dos: Una alternativa sencilla para problemas sencillos es usar un BackgroundWorker. Este tipo de objeto es una careta a un thread e implementa funciones útiles. Está pensado para el problema que yo planteo así que una vez arrancado el hilo principal retorna y la interfaz sigue funcionando. Cuando desde el hilo pesado hay que dar feedback se llama a una función del objeto BackgroundWorker (GiveFeedback()) y un evento se lanza pero en el hilo de ejecución que creó al BackgroundWorker. Problema resuelto, el feedback se puede dar en el hilo correcto sin más problemas. Lo mismo pasa para cancelar o para terminar el hilo.

El problema a esta primera solución aparece cuando los objetos que se gestionan en el hilo pesado son más complicados y el feedback no es tan sencillo y requiere modificar múltiples vistas. Otro problema es cuando los objetos modificados en el hilo secundario tienen sus propios eventos que pueden ser gestionados por parte de la UI. La solución a este problema puede ser bastante sencilla si se piensa desde un principio.

Allí donde la UI esté asociada a un evento de un objeto y que provoque un cambio o acceso a la UI es necesario comprobar el contexto de la llamada. Todos los controles, bueno realmente todos los objetos heredados de Component implementan una funcionalidad para evitar el problema de los hilos inapropiados. La propiedad InvokeRequired indica si es necesario hacer malabarimos para actualizar la UI. Retorna false en caso de que el hilo es el correcto y true en el caso que el hilo desde el que se llama sea otro diferente a la de creación. De nuevo los controles tienen una función, bueno una pequeña colección de ellas, que permite invocar la ejecución de una función en el hilo correcto. BeginInvoke() e Invoke() son las más importantes. Ambas funciones van a lanzar la ejecución de la función que le indiquemos como parámetro pero en el hilo correcto.

Bufff, esto es todo sobre UI y multithreading que no es poco. La verdad es que puede dar verdaderos dolores de cabeza sin no se diseña desde el principio con cuidado.

Novedades en ProyectoRadio

Martes, 29 \29UTC agosto , 2006

Pues pocas 🙂 Estoy reestructurando el sistema de importacón y exportación para hacerlo, por este orden: Más eficiente, más usable y más flexible. Enseguida nuevos mapas, clutter y asociación de redes y coberturas.

Tengo ganas de escribir un post sobre el poder de reflection para implementar plug-ins y nueva funcionalidad. A ver si mañana desde un teclado de tamaño razonable…

Dormir

Martes, 29 \29UTC agosto , 2006

Curioso, aun estando casi incoscientes disfrutamos tanto como si no lo estuviéramos.

Iratxo, desde mi PDA.

Trac up and running

Martes, 29 \29UTC agosto , 2006

Pues ya llevamos casi una semana con Trac funcionando. La verdad es que hemos tenido un “problemilla”. No hemos conseguido solucionar satisfactoriamente los problemas de la seguridad. Me da la sensación de que su origen viene de su enfoque. Trac está orientado a gestión de proyectos software OpenSource y esto lleva a que se maximice su funcionalidad en ese entorno. Todos pueden aportar y todos pueden corregir y eso a Trac le viene de perlas. En ese entorno estoy seguro de que no hay ningún tipo de problemas.

Nosotros aplicamos Trac a una estructura empresarial. No es que no se pueda, pero el hecho de no tener una gestión de control de acceso a las páginas, tickets o demás de forma independiente hace que no se pueda tener un Trac unificado si se quiere tener usuarios con acceso a diferentes contenidos o informaciones. Además requiere que para que un usuario tenga permisos de acceso en condiciones (escribir y leer) este sea de confianza en la organización. Pero bueno, yo creo que cuando mejor se funciona es cuando las relaciones son de confianza.

Por lo demás, sigo pensando que me encanta. Estamos portando toda nuestra documentación, antes dispersa entre carpetas y branches de CVS y otros sitios siniestros. Me encanta el concepto de marcar las entradas con tags, de organizar la información de la forma que quieras, o incluso la de no organizarla. Poder buscar entre todo el conocimiento de la empresa o los tickets asociados a los milestones.

De momento Trac está resultando muy positivo. El mejor indicador de esto es que hace que esté más tranquilo con respecto al estado de las cosas.

Algo para apuntar

Lunes, 28 \28UTC agosto , 2006

Sigo siendo un auténtico novato para esto de los blogs personales, pero aun así ya me ha dado tiempo a darme cuenta de uno de los problemas a los que te debes enfrentar si le coges el gustillo: Las ideas.

No es que esté falto de ideas, si lo estuviera estas alturas, mejor lo dejaba y punto. No. Al contrario, ahora me pasa una cosa rara: según va pasando el día y van ocurriendo cosas o pienso sobre algún tema me salta una bombillita que dice – deberías escribir algo sobre esto por la noche -. Esto es nuevo y creo que es bueno. Realmente creo que por este motivo todos deberíamos tener un blog; y es que tenerlo y querer manternelo ayuda a reflexionar y pensar sobre lo que pasa un poquito más allá. Al menos tan allá como para decidir si merece la pena escribir algo sobre ello.

Pero claro, asociado a este nuevo fenómeno mental desconocido para mí antes, viene uno de mis grandes problemas: La memoria de pez de la que hago gala. El resultado es que por la noche me pongo y digo – um… yo tenía por lo menos… 3 o 4 ideas que me parecían interesantes – Pero claro, las tenía, porque ya no las tengo. Así que, nota mental, llevar o tener a mano siempre algo para apuntar.

Espero que no se me olvide cogerlo mañana.

Arroz con Pollo

Lunes, 28 \28UTC agosto , 2006

Desde siempre recuerdo este plato como uno de mis favoritos. La verdad es que no es nada del otro mundo y mucha gente lo confundiría con una paella, pero no, no es una paella ni muchísimo menos.

La receta original del arroz con pollo que hacía mi madre nunca la he sabido realmente. Más o menos ahora me la podría imaginar e intentarla pero hace ya un tiempo que decidí hacer la mía propia. El resultado en sabor es casi casi el mismo que el que recuerdo y me gusta hacerlo porque tiene mucho éxito con la gente que lo prueba. La principal diferencia entre mi receta y la original es que la mía no necesita olla a presión. Así puedo dejar el punto de caldo a mi gusto.

Los ingredientes necesarios son pocos y sencillos:

  • Arroz normal, SOS me gusta especialmente. 1 vaso y medio para 3 personas.
  • Media cebolla.
  • 2 dientes de ajo.
  • Media pechuga de pollo grande.
  • Sal, ajo y perejil.
  • Caldo de pollo concentrado.
  • Vino blanco.
  • Agua, 3 medidas por cada una de arroz.
  • Quizá limón o zumo de limón.
  • Aceite de oliva virgen, el mejor que se tenga a mano.

Hacerlo cuesta nada y queda muy rico:

  • En una cazuela baja y ancha se calienta el aceite a fuego suave y se añaden los ajos en láminas y la cebolla en juliana.
  • Se tapa y se deja pochar todo a fuego muy muy suabe. Cuando la cebolla se pone blanca o casi blanca se da por terminado este paso. La cebolla se puede retirar si a alguien no le gusta. A Silvia no le va nada así que siempre la quito. Hay que aprovechar al máximo el juguito que tiene la cebolla que se retira, recomiendo aplastar un poco con una espumadera.
  • Se sube el fuego y se añade la pechuga trozeada y aliñada con sal, ajo y perejil. Se remueve y cuando todos los trozos ya están blanquitos por fuera se añade vino. Cantidad… la que se quiera. Es el secreto del plato realmente.
  • Se deja que el vino evapore el alcohol y se añade el arroz, el agua y caldo y se mantiene a fuego fuerte hasta que comienza a hervir en abundancia. Se puede echar un poquito de sal.
  • Se baja el fuego y se tiene cociendo hasta que se consuma el agua al gusto. Yo recomiendo sacar del fuego cuando aún haya bastante agua y el arroz aún esté un poco duro.
  • Se tapa con un trapo limpio y se deja reposar unos minutejos para que termine de cocer pero no se pase.
  • Se sirve en platos y se come a gustito. Si a uno le gusta pues se le puede añadir el limón. A mí, según los días, me apetece.

La verdad es que es un plato muy sencillo y rápido y es difícil que quede mal, salvo que quede duro o se pase el arroz.

Ala todos a cocinar!

Hablar sobre uno mismo

Domingo, 27 \27UTC agosto , 2006

Hoy he dedicado parte de esta tarde a hablar sobre mi mismo. Bueno, no realmente si no de proyectoradio. He aquí la entrada: ProyectoRadio. Está escrita como una página fija del blog, así que siempre estará ahí como referencia cada vez que, como es habitual, hable de mi proyecto favorito :).

Thinking in C

Domingo, 27 \27UTC agosto , 2006

Creo que si los ordenadores pensasen lo harían en C.

Hace no mucho leí un post en algún blog super Web2.0 que decía algo así como: “Compiled languages are dead”

Gran reflexión. Supongo que viniendo de gente para los que su mundo es la Web2.0 es razonable. Os contaré lo que pienso que para eso es mi blog. Yo trabajo principalmente en dos entornos y con dos lenguajes de programación.

Por un lado trabajo en C. Trabajo diseñando e implementando una pila de protocolos WiMAX. Una pasada, se lo recomiendo a cualquiera que se atreva a decir que le gusta el soft. En este trabajo aprendes lo crítico que puede ser poner una sentencia if que casi siempre va o no va a ser cierta. Trabajando en C con código crítico te das cuenta de que detrás de cada línea hay un microprocesador ejecutando lo que escribes. Te das cuenta el problema de reservar memoria cuando no debes, o la importancia del número de parámetros y variables locales de una función. Todo cuenta.
Por otra parte trabajo en C# en proyectoradio diseñando una aplicación de usuario. C# tiene un montón de virtudes y es, probablemente, uno de mis lenguajes de programación favoritos. Tiene abstracciones muy útiles como las propiedades de los objetos, la gestión de memoria automática, las referencias seguras y los delegates. C# ayuda a crear aplicaciones grandes y potentes de forma bastante sencilla. Pero tiene un problema: hace que te olvides fácilmente que debajo de tu aplicación hay unos recursos limitados y una máquina ejecutando código. Lo digo por experiencia.

Supongo que tengo la visión de los dos lados. He escrito mucho C y mucho C#. Trabajar con C ayuda muchísimo a escribir código C# mucho más eficiente y rápido, lo digo de verdad. La gestión de memoria en C ayuda a que en C# no te dejes referencias sin anular. La gestión de la pila, la memoria, las llamadas, los paths de ejecución… todo es muy útil.

Trabajar con C# también ayuda a trabajar en C mejor. Los patrones de diseño orientados a las interfaces, las funciones polimórficas o virtuales… todo es totalmente aplicable a C si se sabe como. Nosotros trabajamos en C orientando el diseño totalmente a objetos. Solo requiere escribir un poquito más de código a la hora de crear las estructuras de datos, pero los paths de ejecución son tan buenos, o mejores, que los tradicionales de C. Un día escribiré un post con algunas de mis técnicas favoritas.

Pero al final, muy abajo, tan cerca del micro que casi lo puedes tocar… está C. Vale, de acuerdo, está el código máquina, pero C es tan parecido al ensamblador… es un ensamblador universal a todos los microprocesadores y puedes estar tan cerca de la máquina como quieras. Por eso creo que si los ordenadores pensasen lo harían en C. Jamás creo que los lenguajes compilados puedan desaparecer, al menos mientras los ordenadores sean tal y como los conocemos o parecidos. Siempre habrá que escribir un intérprete, siempre habrá que escribir software para manejar dispositivos, sistemas de archivos, gestión de memoria… Si queremos que la potencia de nuestros ordenadores no creza de forma absurda, si queremos aprovechar todo lo que son capaces de darnos hay que pensar que detrás de cada línea de phyton o de php hay miles de instrucciones ejecutándose. ¿Todavía nos preguntamos porqué para servir unos tristes 200Kbytes de html haya que tener unos monstruos de servidores? Sin lenguajes compilados no podrían existir routers ADSL/WiFi/Ethernet por 100€. Si los lenguajes javeros no existieran los juegos de móviles serían muchísimo mejores.

En cierta forma, este post es un alegato en favor de aprender informática de verdad. Donde el diseño estructural es tan importante como la codificación de una función. Donde la elección del lenguaje no venga impuesta por la última moda. Es un alegato para que en las escuelas de ingenieros se siga enseñando C como la mejor herramienta para aprender sobre ordenadores, sistemas operativos y sistemas de información. Aprender Java luego es mucho más fácil. C no está reñido con los objetos, simplemente da toda la libertad del mundo para hacer lo que necesites. Kernighan & Ritchie escribieron un libro que todos los escritores de código deberían haberse leído. Aún hay tiempo.

Construyendo software

Domingo, 27 \27UTC agosto , 2006

Al final cada uno acaba siendo lo que menos se esperaba ser. Yo no me esperaba trabajar haciendo software y resulta que es básicamente lo que hago. Diseñar y escribir software es una de las mejores formas de crear que conozco. Creo que a cualquiera que le gustase hacer cosas con sus manos (quizá bricolaje) o que le gustase escribir o pintar, debería gustarle hacer software.

Y si eres ingeniero también. A mí me pasa. A veces pienso, por ejemplo, en un arquitecto. Un arquitecto sigue el mismo proceso de diseño que un ingeniero de software:

  • Analiza los requerimientos de su cliente.
  • Analiza las necesidades de la obra, su integración en el medio, en la ciudad, en el urbanismo.
  • Propone unos bocetos iniciales, unas ideas de lo que puede ser el edificio final.
  • Hace un diseño general del edificio.
  • Se dibujan los planos de detalle de la obra y puede, si el ayuntamiento lo permite, empezar a construirse.

Todo esto es igual pero justo ahí empiezan los problemas. Un ingeniero de software puede coger su diseño y empezar directamente a implementarlo, a generar el software que ha diseñado. El arquitecto, además de esperar visados de sus proyectos, necesita que comiencen las obras, se construyan y se terminen y en general lleva mucho tiempo. Supongo que ser arquitecto puede ser un poco más frustrante si no consigues ver tus obras construidas hasta muchos años después de haberlas creado, o incluso nunca. Ahora bien, no sé qué se debe sentir al ver un edificio que has firmado tú.
Profesionalmente me dedico a hacer software por lo menos el 70% del tiempo. Y me gusta porque después de discutir y pensar sobre lo que queremos que haga nuestro código, podemos escribirlo y probarlo. Me gusta también porque experimentar es fácil y, está demostrado, experimentando es como más y mejor se aprende. Los niños son expertos en esto. Me gusta llevar el lenguaje de programación que uso al límite en algunos casos y antes de liarla me gusta probarlo, y lo hago.