domingo, 30 de diciembre de 2012

Destripando PSeInt

PSeInt es un programa compuesto por muchos programas. Es decir, consta en realidad de varios ejecutables que se invocan y comunican entre ellos, de forma tal que para el usuario final se ven como partes de un único entorno. En este artículo voy a comentar cuales son esas partes (desde ahora módulos, cada uno un ejecutable), y cómo y cuando se comunican. La idea es que sirva de referencia para el siguiente artículo donde discutiré porqué es así, porqué las cosas están separadas o juntas, porqué se comunican de esa manera, y qué tiene esto de bueno o de malo según mi experiencia y las necesidades particulares de este proyecto. De paso, también sirve de documentación para mí y para los que quieran mirar el código fuente.

Primero voy a hacer una descripción rápida de qué hace cada módulo, y luego cómo se relacionan. En este análisis dejo de lado intencionalmente a psdraw, ya que sus funcionalidades serán absorbidas por psdraw2 (algunas ya lo fueron, y las que no, lo serán en las próximas versiones).  Los módulos que componen entonces al sistema de PSeInt son:

domingo, 16 de diciembre de 2012

Codificar y ejecutar, ¿serie o paralelo?

Se viene algo grande en PSeInt. Por suerte 2012 ha sido un año de muchos muchos avances, y parece que 2013 también va empezar con novedades. Había advertido que no iba a hacer nada nuevo por un buen tiempo, pero me topé con un concepto demasiado bueno como para andar esperando tanto. Navegando sin rumbo llegué a un post de un tal Bret Victor, un tipo que parece tener ideas más que interesantes sobre cómo deberían ser los entornos de programación (entre otras cosas) y cómo la gente debería aprender a programar. Gracias a ese artículo dí con este video. Si miran el video (que dura más de una hora, pero yo solo vi los primeros 20 minutos cuando me decidí a empezar todos estos cambios), van a entender de qué se trata. No estoy 100% de acuerdo en todo lo que propone, pero sí en su gran mayoría, al menos pensando a nivel didáctico que es lo que me ocupa en PSeInt. Y hay momentos de la charla realmente fantásticos, de esos que le abren a uno la cabeza y lo hacen ver las herramientas que tenía desde un punto de vista completamente nuevo.

El tipo plantea un entorno de desarrollo donde los pasos para programar no son primero codificar, luego ejecutar para ver que sale, y repetir; sino que propone codificar y ver qué sale en simultáneo. Es decir, a medida que el programador va codificando el programa, este se va ejecutando, y si a mitad de una ejecución cambia algo del código fuente, la ventana de ejecución refleja inmediatamente esos cambios. El video muestra otras cosas interesantes, pero esa idea tan simple y complicada a la vez fue la que más me impactó. Aquí les presento mi video, de solo 2 minutos, con algunas de estas ideas llevadas a PSeInt:

miércoles, 12 de diciembre de 2012

Trucos para depurar con ZinjaI

Este artículo bien podría llamarse "Tips para convertirse en un ZinjaI Master (parte 5)", pero preferí ponerle un título diferente donde aparezca la palabra "Depuración" ya que trata de este tema en particular, y los tips son algo más específicos. En la pestaña Depuración del cuadro de Preferencias (al cual se accede con el ítem "Preferencias..." del menú "Archivo"), los tres últimos ítems son bastante particulares, pero bien utilizados ayudan mucho.

El primero, "Mejorar inspecciones automáticamente según tipo", hace que cuando ingresemos (durante la depuración) una inspección de algún tipo configurado allí (se configuran con el botón "Opciones" que tiene al lado), ZinjaI la modifique automáticamente. Por ejemplo, cuando trabajamos con la clase std::string, usualmente queremos inspeccionar el contenido de la cadena, y no la estructura de la clase. En gcc, por ejemplo, esta clase tiene el contenido del string en un puntero llamado _M_p que está dentro de un struct miembro llamado _M_dataplus; y la clase tiene además otras cosas que en general no nos interesa ver, como el npos. En resúmen, si el string es s, no interesa evaluar solamente el valor de "s._M_dataplus._M_p" en lugar de "s". Sin esta opción, hay que buscar dentro de la clase el atributo que queremos, lo cual se hace fácilmente con un par de dobles clicks sobre el valor de la inspección y borrando luego las inspecciones que sobren, pero se torna tedioso y repetitivo. Con esta opción, ZinjaI puede hacerlo automáticamente.

lunes, 10 de diciembre de 2012

Tips para convertirse en un ZinjaI Master (parte 4)

En la última (eso creo) entrega de esta serie, voy a hablar un poco de la personalización de ZinjaI. Es decir, de cosas que podemos configurar desde las preferencias o desde las opciones de proyectos, generalmente para mayor comodidad. No voy a cubrir todo lo que se puede configurar en ZinjaI, sino sólo lo que me parece destacable en el contexto de esta serie de posts.

Para empezar, hay una opción en la pestaña "General" del cuadro de Preferencias (al que se accede con el ítem "Preferencias..." del menú "Archivo") que dice "Ocultar paneles automáticamente". Cuando digo paneles me refiero a esas subventanas que aparecen en los bordes de la ventana principal, como el arbol de archivos, los resultados de la compilación, la ayuda rápida, el árbol de símbolos, etc. Por defecto, estos paneles aparecen cuando alguna acción en ZinjaI los necesita (por ejemplo, el de compilación al compilar) y se quedan ahí ocupando buen espacio hasta que los cerremos. Y si el monitor no es tan grande, ese espacio es importante, así que molestan. Algunos desaparecen con la tecla Escape, otros no. Pero si los cerramos, a algunos después hay que ir a buscarlos al menú cuando se necesitan otra vez, o aprender algún otro atajo de teclado (y creo que ya tienen bastante por ahora). Entonces no es tan cómodo.

jueves, 6 de diciembre de 2012

Tips para convertirse en un ZinjaI Master (parte 3)

Después de darles algunos tips para moverse fácilmente por el código, y para realizar algunas operaciones de edición básicas en un periquete, en esta tercera parte voy a comentarles sobre algunas otras funcionalidades afines que han quedado fuera de las dos primeras para no hacerlas tan largas, o porque no son tan triviales.

Por un lado están los autocódigos. Ya hablé de ellos en otro post, así que no voy a volver a explayarme. Si no saben lo que son, escriban "fori(N)" (reemplazando N por lo que quieran) y presionen la tecla Tab justo después de cerrar el paréntesis. Tengo que decir que agregarlos me llevó bastante tiempo porque no me ponía de acuerdo conmigo mismo acerca de cuál sería la forma menos intrusiva de invocarlos (problema cuya solución inspiró NetBeans si mal no recuerdo a través de un comentario de un usuario). Pero una vez implementados, resultaron mucho más útiles de lo que imaginaba, y ahora no vivo sin ellos. Pueden seguir el link que puse antes para ver cuales hay configurados por defecto y cómo definir nuevos con lo que ustedes quieran o necesiten.

lunes, 3 de diciembre de 2012

Tips para convertirse en un ZinjaI Master (parte 2)

Ya les revelé en el post anterior "secretos" varios para deslizarse de un punto a otro de su proyecto con apenas un puñado de teclas. Digo "secretos" entre comillas porque estos atajos no son secretos para nada. Están a la vista en los menúes y la mayoría comentados en la ayuda. Pero por alguna misteriosa razón, el 99% de los usuarios no los ve, entonces, cuando uso algunos de estos atajos en público no falta quien me pregunte cómo hice eso tan rápido. ¿Después de al menos un cuatrimestre de programar con ZinjaI, jamás le pegaron una mirada al menú Editar para ver que había?. Supongo que la respuesta es no, yo tampoco lo haría al principio. Soy de los que empiezan a usar y ya, sin manuales; pero cuando me decido a adoptar finalmente una herramienta para un trabajo prolongado me tomo un ratito para jugar con su interfaz y ver qué cosas pueden ser útiles que no conozca. En fin, en esta segunda entrega, quiero comentar atajos de teclados para pequeñas tareas de edición, bastante triviales, pero que hacemos millones de veces mientras programamos.

viernes, 30 de noviembre de 2012

Tips para convertirse en un ZinjaI Master (parte 1)

No hay IDE en el mundo con el que pueda desarrollar programas en C++ más rápido que con ZinjaI. Y esto se debe a una razón simple y clara: yo lo hice, ergo, yo conozco todas sus mañas y sus trucos. Y que quede claro otra vez: el hecho de que yo sea mucho mucho más rápido con ZinjaI que con algún otro IDE nada tiene que ver con que ZinjaI sea o no sea superior a ese otro IDE. Entonces, dejando para otro día la discusión de si es el mejor o el peor, y suponiendo que si alguien se toma la molestia de leer esto es porque ya ha decidido darle una oportunidad, voy a tratar de compartir en esta serie de posts muchos de esos trucos y explicar muchas de esas mañas que decía antes, para que el lector usuario de ZinjaI pueda aspirar a ser el programador más rápido del oeste.

Para empezar, es fundamental poder moverse cómodamente por el código. Y en ZinjaI hay muchas formas de ir y venir por el mismo. Están las formas convencionales de todo editor de texto: Ctrl+F para buscar, Ctrl+G para ir a un número de linea en particular, F3 y Shift+F3 para repetir la última búsqueda hacia atrás o hacia adelante, y Ctrl+Alt+F para mover el foco del teclado al cuadro de búsqueda rápida que aparece en la barra herramientas. Pero hay algunos atajos específicos que pueden resultar muy muy útiles.

sábado, 24 de noviembre de 2012

Sobre medios y objetivos

¿Qué guía el desarrollo de un proyecto de software libre? Esta es para mí una pregunta muy interesante, donde hay muchas respuestas válidas. Con ella apunto a analizar cómo se decide hacia dónde debe ir el futuro de un proyecto, cuáles son sus objetivos a corto, mediano y largo plazo, en qué aspectos del proyecto se deben centrar los mayores esfuerzos, o cómo descubrir los puntos fuertes y débiles del mismo, entre otras cosas. En general se distinguen muy fácilmente los casos extremos. Por un lado, proyectos respaldados por grandes organizaciones que toman decisiones en grupo, luego de discusiones (que pueden ser formales y protocolares, o simples encuentros en una sala de chat o mediante envío de mails informales en listas dedicadas). Estos proyectos suelen tener una buena estructura jerárquica, objetivos claros en varios frentes a largo plazo bien documentados, a veces intereses políticos, etc. Por otro lado están los proyectos pequeños, que empiezan una o unas pocas personas, y que básicamente suelen seguir los caprichos de esas pocas personas, o guiarse por sus necesidades e intereses particulares. En el medio de todo esto, está la gran mayoría de los proyectos, y hay tantas y tan diversas variantes que no se me ocurre ni cómo agruparlas.

domingo, 4 de noviembre de 2012

Compilar la versión del repositorio en Windows

En el artículo anterior expliqué los pasos para instalar todo lo necesario y compilar la versión de ZinjaI o PSeInt de los repositorios git en GNU/Linux. En este voy a comentar cómo hacerlo en un sistema Windows. Ya saben que vamos a necesitar el compilador, unas cuantas bibliotecas, git, y algo de paciencia.

Lo primero que vamos a instalar entonces son las herramientas para compilar: compilador y bibliotecas. Se puede intentar instalar todo (MinGW y wxWidgets mínimamente) por separado, pero requiere de muchos pasos. La forma más sencilla es hacer una instalación completa de cualquier versión no tan vieja de ZinjaI, ya que el instalador de ZinjaI incluye casi todo lo necesario. Entonces, vayan al sitio de ZinjaI, a la sección "Descargas", click en "Descargar el instalador para Windows", y luego de esperar unos segundos ejecuten el instalador. En el asistente de instalación de ZinjaI deben tener la precaución de seleccionar todos los componentes en la tercera página (a esto me refería con "completa", "wxWidgets" y "OpenGL" serán necesarios y no están seleccionados por defecto).

jueves, 1 de noviembre de 2012

Compilar la versión del repositorio en GNU/Linux

Para los inquietos e impacientes que quieren probar lo último de lo último, para los curiosos y corajudos que quieren ver y meter mano en los oscuros rincones del código fuente, para los que están en trabados por un bug que necesitan resuelto para ayer, para los que están aburridos, y para cualquiera que quiera colaborar o simplemente meter la nariz tras bambalinas; para todos ellos están los repositorios git. git es el sistema de control de versiones que utilizo en mis proyectos. Estos repositorios contienen el código fuente tal cual está ahora en mi PC, siempre actualizado con los últimos cambios y retoques, mucho antes de que estos aparezcan bonitamente empaquetados en una nueva versión oficial en la sección descargas. Yo lo utilizo como si fuese centralizado (aunque uno de los puntos fuertes de git es su gestión distribuida), y la versión que hay en los servidores de sourceforge es la que considero máster. Cada cambio que hago en mi PC va a parar casi inmediatamente allí.

Pero muchos usuarios no han usado nunca un software de control de versiones, o no están familiarizados con el proceso de compilación mediante makefiles y la configuración del entorno. Por ello, voy a explicar desde cero en un par de posts como preparar todo y compilar ZinjaI o PSeInt (los pasos son los mismos) desde los fuentes de estos repositorios, tanto en GNU/Linux (en este artículo) como en Microsoft Windows (en el próximo). Así, cuando comente en el blog que tengo alguna funcionalidad nueva en desarrollo, ya saben donde tienen que ir a buscarla si no quieren esperar, o si quieren ayudarme a testearla.

viernes, 26 de octubre de 2012

SourceForge, cada día mejor

Desde que comencé a publicar mis proyectos de software libre utilizo SourceForge. Allá por el 2004 cuando decidí "colgar" PSeInt en algún lugar de la web, la gente de la lista de mails de gleducar me sugirió SourceForge, y dado que yo no conocía casi nada al respecto, acepté la sugerencia. Desde entonces y hasta el día de hoy, mis proyectos se han alojado exclusivamente allí, y después de varios años de utilizar sus servicios puedo sacar algunas conclusiones.

Para empezar, tuvo sus puntos flojos en algunas ocasiones. Hace un tiempo solía tener problemas con algunos mirrors que en combinación con ciertos navegadores me dejaban a veces las descargas incompletas. En otros momentos el acceso al sitio era bastante lento. Las interfaces para realizar algunas tareas solían ser tediosas. Pero todo eso fue cambiando, a veces de a poco, a veces de golpe, y mantener mi confianza en este servicio cuando aparecieron alternativas muy prometedoras y populares (como pueden ser google code o github), está pagando con creces.

martes, 23 de octubre de 2012

Parseo y mayusculización en PSeInt

Estoy casi seguro de que esa palabra (mayusculización) no existe, pero viene bien para hablar de algo que pasa en PSeInt cuando le pedimos que haga algo con un algoritmo que no sea simplemente guardarlo. Por ejemplo, si le pedimos que genere el diagrama de flujo, ya sea para verlo o editarlo, todos los identificadores pasan a estar en mayúsculas. Si le pedimos que exporte a código C++ ocurre algo similar, pero en este caso con minúsculas. Si le pedimos que lo ejecute y el intérprete encuentra errores, los identificadores que pone para aclarar entre paréntesis en los mensajes de error están siempre en mayúsculas. Y así ocurre con algunas otras situaciones menos frecuentes.

La justificación es bastante simple: para simplificar el "parseo" del pseucódigo, todo se pasa a mayúsculas. "To parse" significa analizar, o procesar, y el "parser" es una parte fundamental de cualquier intérprete/compilador. Sin embargo, es muy frecuente no dejarle al parser toodo el trabajo, sino hacer antes un preprocesamiento del código para simplificar algunas tareas posteriores (que no son difíciles en realidad, solo tediosas o poco eficientes de otra forma). En muchos casos, parte de este preproceso está en el parser mismo, ya que lo realiza internamente.

viernes, 12 de octubre de 2012

La estrella del show

En este mini-show que componen mis proyectos personales, unos posts en un blog que pareciera tener alguna fijación con los insectos, y otros delirios afines, donde ustedes, lectores y usuarios, son los preciados espectadores que busco cautivar, PSeInt se roba todos los flashes. Mientras que a mis últimos 7 posts les llevó unos 10 días llegar a la (para nada envidiable) cantidad de 50 visitas a cada uno, la nueva versión de PSeInt tuvo más 200 descargas en sus primeras 10 horas de vida y eso que esas 10 horas fueron entre las 10 de la noche y las 8 de la mañana, lo que implica que la mayoría de los usuarios estaba cenando, durmiendo, mirando tele, o haciendo cualquier otra cosa, pero no creo que trabajando o estudiando tanto (aunque pensandolo bien yo suelo hacer mis tareas de mantenimiento, lo que incluye actualizaciones, durante la noche). Para el final de su primer día, había llegado a nada menos que 900 descargas.

lunes, 1 de octubre de 2012

Nuevo miniproyecto: wxTimeLineEditor

Hace un tiempo agregué en la página de PSeInt, en la parte de documentación, una "linea de tiempo" que resume los hitos más importantes para ese proyecto. Me pareció útil para ver rápidamente cómo evolucionó el proyecto en estos casi 9 años, porque creo que la historia de PSeInt tiene varios matices interesantes, dado que nació con pocas expectativas, y tiempo después el hecho publicarlo como software libre me generó unas cuantas gratas sorpresas, y con él fui aprendiendo muchas cosas. En fin, la linea de tiempo no era realmente un gráfico de una linea de tiempo, sino una simple tabla de fechas y acontecimientos porque en aquel momento no encontré un software que me permita generar el gráfico como yo quería. Lo que buscaba era algo sencillo, offline, y que permita exportar la imagen. Probé unos cuantos, algunos muy malos, otros innecesariamente complicados, otros solo para Windows, y algunos muy buenos pero que no se ajustaban a lo que yo quería, o que me daban errores varios al utilizarlos. Finalmente decidí programar algo yo, ya que tomando la experiencia que ya conté del graficador de diagramas de flujo, iba a ser trabajo de una tarde/noche o a lo sumo un fin de semana, al menos para las muy pocas funcionalidades que realmente necesitaba, "los extras vendrán después" pensé. A la noche tenía mi preciado grafiquito. Así es el poder que da aprender a programar, si no encuentro lo que quiero, tengo siempre la alternativa de hacerlo (o intentar, tampoco hago magia :). En fin, la noticia es que ahora registré el proyecto en SourceForge y si les sirve para algo ya pueden empezar a descargarlo.

viernes, 28 de septiembre de 2012

Compilación y bibliotecas (parte 5): crear bibliotecas con ZinjaI

En los cuatro posts anteriores de esta serie Compilación y Bibliotecas hablé un poco en general del proceso de compilación y el uso de bibliotecas externas, para explicar finalmente en el cuarto cómo utilizar un biblioteca X en un proyecto de ZinjaI. En la última entrega de la serie, vamos a ver un caso mucho menos frecuente, pero igualmente interesante: vamos a ver cómo crear nuestras propias bibliotecas con ZinjaI.

Desde hace ya unas cuantas versiones, ZinjaI presenta en el cuadro de diálogo de Opciones de Compilación y Ejecución de Proyecto, una pestaña titulada "Biblioteca". Esta pestaña sirve para crear una biblioteca a partir de una parte del proyecto. Sabemos ya que una biblioteca por sí misma no se puede ejecutar, sino que requiere de un programa cliente. Cuando uno desarrolla una biblioteca va desarrollando al mismo tiempo uno o más programas clientes para probar su funcionamiento.  Entonces, la idea es que en el proyecto de ZinjaI tendremos un conjunto de archivos que conforman los fuentes de una o más bibliotecas, y otro conjunto de archivos que conforman el programa cliente. En la pestaña "Biblioteca" es donde decimos qué bibliotecas generar y con qué archivos. También se puede indicar allí mediante un checkbox que el proyecto solo generará una biblioteca, y no habrá programa cliente si así se quisiera, pero creo que no es lo normal durante el desarrollo, aunque puede ser útil en los perfiles para release.

miércoles, 26 de septiembre de 2012

Compilación y bibliotecas (parte 4): utilizar bibliotecas desde ZinjaI

En este post voy a tratar de ser bien práctico y dar instrucciones precisas de qué hacer para utilizar bibliotecas no estándar en ZinjaI. Lo primero que hay que saber es qué se necesita para utilizar una biblioteca. Repasando los posts anteriores se llega a la conclusión de que se necesitan dos cosas, los archivos de cabecera (.h o .hpp), y los binarios (.dll, .lib, .so, o .a). Los primeros son necesarios para compilar las partes del programa cliente que hacen uso de la biblioteca. Estos fuentes deberán incluirlos (con "#include") para que el compilador no se queje de que no conoce las clases o funciones de la biblioteca al querer utilizarlas. Los segundos son necesarios para enlazar el ejecutable final, ya que los primeros solo decían qué hace la biblioteca, pero no cómo. En algunos casos particulares puede que esté todo en los .h y no haya binarios. Esto suele ocurrir cuando hay templates involucrados (como la biblioteca CImg por ejemplo), o cuando por decisión de diseño porque la biblioteca no es tan compleja, el que la desarrolló lo hizo así para facilitar su utilización (por ejemplo, la biblioteca EasyBMP), pero son excepciones (y aún así requieren binarios del sistema, bibliotecas de Windows por ejemplo), normalmente se requieren las dos cosas (como con GLUT, wxWidgets, SFML, QT, etc, etc, etc).

sábado, 22 de septiembre de 2012

Compilación y bibliotecas (parte 3): ese oscuro y mágico proceso

Centrándonos ahora en el proceso de compilación de un programa C++, hay que aclarar que es un proceso de varias etapas, y que no se realiza por un solo programa, sino por un conjunto. El compilador es en realidad un grupo de programas. En el proceso de convertir el código C++ en código objeto hay que preprocesar los fuentes, analizar la sintaxis y traducir a lenguaje ensamblador, convertir el código ensamblador en código de máquina dentro de un archivo llamado "objeto", aplicando optimizaciones, agregando información para el depurador, etc, y finalmente juntar todos los archivos objetos y, si las piezas encajan, empaquetar todo en un archivo ejecutable final. La parte del preproceso en C/C++ es la que analiza las lineas que empiezan con # (como los #define, #ifdefs, #includes) y otras tareas similares (quitar comentarios y expandir macros por ejemplo). Luego viene la etapa más importante, que sería la verdadera compilación, que es donde se traduce el código fuente a código de máquina. Pero en un proyecto real, el código fuente no es un sólo gran archivo, sino que está distribuido en muchas partes, y se debe traducir cada uno de ellas. Luego, juntando todas esas traducciones, se confecciona el ejecutable. Este último paso se conoce como enlazado. En general, a fines prácticos, al programador sólo le interesa diferenciar entre la etapa de compilación (incluyendo aquí en un solo bloque preproceso, compilación y ensamblado), y la etapa de enlazado.

miércoles, 19 de septiembre de 2012

Compilación y bibliotecas (parte 2): Intérpretes vs Compiladores

A la hora de ejecutar un programa escrito con algún lenguaje de programación hay, en principio, dos grandes opciones: interpretar y compilar. Digo en principio, porque se podría discutir un buen rato sobre dónde ubicar lenguajes administrados, máquinas virtuales por ejemplo, o intérpretes que utilizan algún formato intermedio que no es ni fuente ni objeto, pero simplificando en los dos casos de libro más claros, tenemos intérpretes y compiladores. Un compilador es un programa que "traduce" el código fuente de un lenguaje de alto nivel a código de máquina listo para ser ejecutado. Un intérprete, en cambio, es otro programa que interpreta las instrucciones del código de alto nivel e intenta ejecutarlas él mismo. La diferencia en principio no parece clara, pero pongamos una metáfora. Si quiero escuchar una canción, digamos "Over the rainbow", la hoja con la partitura y la letra serían el código fuente. Un compilador sería un músico que toma la partitura, y graba la canción por ejemplo en un cd de audio que voy a poder escuchar en mi auto cuando quiera aunque el músico se haya retirado, vendido su guitarra y quemado la partitura. Un intérprete en cambio sería un músico que toca la canción en vivo para mi, leyendo de la partitura cada vez que quiero escucharla, y que tengo que llevar sentado con su guitarra en el asiento del acompañante todo el tiempo. Parece poco cómodo, pero tiene sus ventajas. Digamos que quiero probar cómo quedaría si agrego algunos arreglos, o si cambio la letra por otra nueva que se me ocurrió, o si afino la guitarra un semitono más arriba. En el primer caso, tendría que llamar al músico "compilador" para volver a grabar un nuevo cd, mientras que en el segundo tendría que hacer lo mismo de siempre, pedirle al músico "intérprete" que interprete una vez más la partitura, que esta vez estará modificada.

lunes, 17 de septiembre de 2012

Compilación y bibliotecas (parte 1): ¿por qué?

Aprender a programar es difícil. Involucra muchas cosas. Por un lado están la lógica, el nivel de abstracción, los conceptos, los paradigmas; todas esas cosas inherentes a la programación en sí, e independientes del lenguaje. Por otro lado está el mismísimo lenguaje, esa oscura maraña de reglas, en un inglés abreviado y poco amigable para el estudiante, donde tratamos de aplicar todo lo primero para poder ver sus frutos. Mediante mis proyectos PSeInt y ZinjaI intento contribuir a simplificar el aprendizaje en ambos frentes. Siempre digo que aprender las dos cosas al mismo tiempo es demasiado difícil. Para poder separar e ir por partes es que nace el pseudocódigo. El pseudocódigo sería una herramienta didáctica para aprender y practicar lo conceptual sin lidiar con el lenguaje. Allí es donde espero que PSeInt dé una mano, permitiendo hacer alguna práctica más real y entretenida de esa primera parte. Una vez dado ese primer paso, se pasa a estudiar un lenguaje real, y allí es donde (si el lenguaje resulta ser C++) ZinjaI intenta contribuir. Pero el problema acá es que deliberadamente oculté un tercer componente muy muy importante en esto de aprender a programar, que es el compilador. Un lenguaje sin un compilador no es más que ideas en el aire, intangibles y poco prácticas. Es el compilador (o intérprete) el que lo trae a la vida, el que hace el nexo entre ese lenguaje y el conjunto hardware+sistema operativo que representa el mundo real para el programa.

viernes, 7 de septiembre de 2012

Próximamente: SubProcesos en PSeInt!

La posibilidad de crear funciones/subprocesos/subrutinas/como-quieran-llamarlos en PSeInt es por lejos la funcionalidad por la que más veces me han preguntado los usuarios. Desde hace años que joden con eso. Y desde hace años que les digo lo mismo: por razones históricas el código base del intérprete está tan mal diseñado que me es imposible agregarlas en ese estado. Pero con el paso del tiempo, muchos cambios internos fueron sucediéndose. Por ejemplo, la clase que administra la memoria virtual del intérprete es completamente nueva, culpa de esto los tipos de datos se gestionan de forma muy diferente a cómo se lo hacía en las primeras versiones, y gracias a esto la evaluación de expresiones a mejorado muchísimo y se ha vuelto también más flexible. Después de muchos intentos, esas partes quedaron listas para un futuro mejor. Seguro que tienen sus errores, pero comparativamente ha sido un gran paso. Por contraparte, el código que analiza la estructura de las instrucciones y que en verdad parsea la sintaxis más allá de las expresiones sigue siendo bastante horrible en su diseño. De a poco voy puliendo la implementación, pero el diseño no ha cambiado sustancialmente. No me gusta el enfoque actual, pero no estoy seguro de que el enfoque teóricamente correcto para un intérprete sea el mejor en este caso. No obstante, repensando el tema de los subprocesos por enésima vez llegué a la conclusión de que la no tan pequeña evolución de la que hablaba ya era sufiente como para intentar implementarlos sin morir en el intento. Puse manos a la obra, y algo salió. En este post quiero presentar con bombos y platillos la tan pedida y flamante funcionalidad, y explicar algunas cuestiones de diseño desde el punto de vista del lenguaje y la interfaz, ya no desde la implementación del intérprete. Hay muchos puntos grises que aún no me terminan de convencer y que posiblemente cambien en el futuro, así que hay que tomar todo como está, en estado experimental, sin terminar, sujeto a cambios, pero igual ya hay disponible en el repositorio git un intérprete capaz de aceptar la definición de funciones/subprocesos por parte del usuario.

lunes, 27 de agosto de 2012

¿Hacia dónde debe ir el pseudolenguaje de PSeInt?

Escribo este post para abrir formalmente un debate con la comunidad de usuarios de PSeInt. Quiero pedir sus opiniones y hacer que sean partícipes del futuro de PSeInt, y entonces comienzo escribiendo esto para dejar claro mi punto de vista y mis objetivos como principal y único desarrollador de este proyecto. La motivación del debate reside en la necesidad de ampliar (o no) el pseudolenguaje que utilizo. Varios usuarios, en la mayoría docentes, me han pedido extender el pseudolenguaje para poder hacer tal o cual cosa. Por ejemplo: definir funciones/subprocesos, manejar cadenas, escribir y leer archivos, controlar mejor la salida por consola (ubicación, colores, etc). Por otro lado, algunos usuarios alumnos escriben preguntando ¿cómo hago tal cosa? que actualmente no se puede hacer, e indirectamente también están aportando una nueva idea. Entonces, tengo que decidir si el lenguaje va a crecer o no para permitir estas cosas, cuales debo permitir y cuales no, y sobre todo, de qué manera se integran. Para tomar esta decisión de la mejor forma y dejar contenta a la mayor cantidad de personas posibles es que quiero iniciar antes un debate. En primer lugar voy a describir mi visión del pseudocódigo, y debo advertir que será innegociable. A continuación, presentaré algunas de las posibles mejoras, mencionando los pros y contras que veo en ellas, como se relacionan con mi visión innegociable, y tratando de dejar abierto el camino para la futura discusión.

miércoles, 8 de agosto de 2012

El runner, la terminal y las señales

Hace muy poquito escribí acerca del uso de la función signal de C para interceptar un segmentation fault. En estos días estuve tratando de utilizarla para otras cosas y eso me llevó a notar algunos problemas en el runner de ZinjaI. El runner es un pequeño ejecutable que utiliza ZinjaI para ejecutar indirectamente los programas y proyectos que compila, a modo de wrapper. Desde el punto de vista del usuario el runner es casi invisible, pero básicamente se encarga de cambiar el directorio de trabajo, informar cómo terminó la ejecución (con qué código de salida), y esperar una tecla si es necesario para que no se cierre la terminal.

Cuando uno ejecuta directamente (no mediante ZinjaI) un programa de consola en Windows, este se ejecuta en una de esas ventanas negras y se cierra inmediatamente cuando termina. En GNU/Linux es peor aún, ya que si estamos en el entorno gráfico ni siquiera se toma la molestia de abrir una ventana. En GNU/Linux, ZinjaI llama a una terminal gráfica para que la cosa se vea, y le pide al runner que, entre otras cosas, espere una tecla después de que termine el programa, para que el usuario pueda ver qué resultado arrojó. Básicamente ZinjaI pide a una terminal gráfica (xterm o konsole por ejemplo) que ejecute el runner, y éste hace un fork (se "divide" en dos procesos idénticos, se llama padre al original e hijo al nuevo), ejecutando al programa que realmente queríamos ver en el nuevo proceso hijo. El proceso original espera a que termine el hijo, y analiza su código y estado de salida, que puede ser el valor de retorno del proceso (usualmente el return 0 del final), o el número de la señal que lo obligó a detenerse de forma anormal. Hasta aquí todo más o menos normal. Eso es lo que hace el runner en las versiones de ZinjaI estables. Pero jugando con las señales me surgió un nuevo problema: cuando mando una señal desde el teclado en la terminal, ambos procesos la reciben.

viernes, 3 de agosto de 2012

Numeración de Versiones

Cómo numerar las versiones de un programa no es un detalle menor. El número de versión comparativamente dice mucho. El cambio ayuda a despertar interés, influye sobre el deseo de actualizar del usuario, da idea de la edad del proyecto, etc. Es importante que el usuario pueda determinar exactamente qué versión tiene, sobre todo para cuando reporta un error o pide algún cambio. Y si el número le indica algo fácilmente mejor.

Primero hay quienes numeran sus versiones de la forma tradicional, con la 1.0, 1.1, 2.0, etc. Dentro de este esquema, hay muchas formas de utilizarlo. En general, un número de versión alto sugiere un programa maduro, mientras que un número bajo puede sugerir un producto incompleto. Pero conozco proyectos excelentes, que llevan años en desarrollo, llenos de funcionalidades, y que no han llegado todavía ni a la versión 1, como por ejemplo Inkscape, que va por la versión 0.48, y sin embargo todavía no encontré algo que no pueda hacer, y eso que yo solía ser un usuario más o menos avanzado de Corel Draw, allá por las versiones 3, 5 y 7. En el caso de Inkscape, el motivo creo que es simplemente una planificación demasiado ambiciosa; van a usar el 1.0 cuando tengan todo lo que soñaron en esa herramienta y algunas cosas más que se les ocurrieron después también. En otra línea se encuentran proyectos como Firefox, cuyo número de versión avanza de forma ridícula, y en poco más de un año pasamos de la 4 a la 14. El cambio parece haber sido impulsado por las odiosas comparaciones con la competencia. Si Internet Explorer iba a por el 9, Chrome por el 6, Opera alrededor del 11, Mozilla con el 3 parecía poco. Por una cuestión de puro marketing diría, decidieron acelerar la numeración. Algo similar o peor pasó con mi tan preciada distribución de GNU/Linux favorita, Slackware. Slackware quedó atrasada en números respecto a otras distros, y la solución fué más directa: no cambiaron su sistema de numeración ni mucho menos, simplemente dieron un salto en el tiempo y se comieron unos cuanto números pasando directamente desde la 4 a la 7 y luego siguieron como si nada. Jamás hubo una versión 5 o 6.

lunes, 30 de julio de 2012

Espejitos de Colores

Vengo a develar el oscuro misterio que envuelve a mi computadora cuando se conecta a un proyector para dar clases. Los más supersticiosos dicen que el código se escribe solo, los escépticos quieren saber por qué. Yo no entiendo nada...

Uno, como desarrollador de un proyecto de software que a su vez consume (que uso para mis otros desarrollos o para mis clases), tiene una posición de privilegio. Porque si uno programa para otro, tiene que hacer ingeniería de software de la que no me gusta hacer. Hay que averiguar que necesita el usuario (averiguar no es preguntarle, normalmente el usuario no sabe ni qué quiere ni qué se puede hacer), hay que entender su posición, imaginar el detalle de los casos de uso, identificar los problemas, proponer las mejoras, etc. Estando a la vez en la posición del desarrollador y del usuario, no hay tanto que adivinar. Generalmente creo que sé que me gustaría ver en mis programas, y sé qué puedo implementar y que no (aunque también suelen sorprenderme gratamente sugerencias de otros usuarios o características de otros entornos que no se me habían ocurrido).

lunes, 23 de julio de 2012

Cómo prepararse para enfrentar un segfault (parte 2)

En la primer parte comenté cómo hacer para que un programa simule un punto de interrupción si encuentra una condición inesperada. Buscando algo más en google, encontré algunas otras macros interesantes, diseñadas para generar errores en tiempo de compilación y ya no de ejecución. Si bien esto no cuadra con el título (más abajo hay otros ejemplos que sí), igual vale la pena comentarlo para completar el tema de los asserts y la macro _revienta que empezé en la primer parte. Se basan en errores como declarar arreglos con tamaños negativos, o tratar de utilizar especializaciones de una plantilla que no existen. La idea de la primer versión es (simplificado y con llaves extra para evitar un problema cuando hay mensajes repetidos):
    #define _compile_assert(x,mensaje) { char _compile_assert##mensaje [x?1:-1]; }
    ....
       _compile_assert(sizeof(T1)
            <sizeof(T2),EL_TAMANIO_DE_T1_DEBE_SER_MENOR_QUE_EL_DE_T2);
que va a generar un error del tipo"error: size of array '_compile_assert_EL_TAMANIO_DE_T1_DEBE_SER_MENOR_QUE_EL_DE_T2' is negative", pero que también va a generar un warning del tipo "unused variable '_compile_assert_EL_TAMANIO_DE_T1_DEBE_SER_MENOR_QUE_EL_DE_T2'" si estos warnings están habilitados. La ventaja de este enfoque es que permite insertar en el mensaje de error algún texto propio para agregar más información. El segundo enfoque no, pero aún así me parece más elegante:

jueves, 19 de julio de 2012

Cómo prepararse para enfrentar un segfault (parte 1)

Segfault (segmentation fault, violación de segmento) es un intento por parte de un proceso de hacer algo "ilegal" como por ejemplo desreferenciar un puntero a NULL, escribir en un arreglo en posiciones fuera de los límites válidos, etc. Usualmente el sistema operativo envía una señal al proceso y hace que el programa se cierre. Si lo habíamos invocado desde una consola vemos el discreto mensaje "Segmentation fault". En Windows veríamos esa molesta ventana de la que lo único que recuerdo es que tiene un botón que dice "No enviar" (otrora una escalofriante pantalla azul). Cuando un programa tiene que lidiar con estructuras de datos complejas, o que hacer operaciones complejas en estructuras no necesariamente tan complejas, suelen aparecer estos problemas, y muy frecuentemente están asociados al manejo de memoria dinámica, punteros, o índices en arreglos. Por ejemplo, a mi me pasa mucho cuando hago operaciones sobre mallas en mi trabajo (donde hay muchas referencias cruzadas que mantener), o muchas veces cuando cambio algo en el parser de ZinjaI (ya que la forma en que almacena su información es bastante rebuscada). En general estos errores son difíciles de depurar, ya que a menos que se hayan tomado los recaudos necesarios, el problema puede saltar en un punto de la ejecución alejado de una u otra forma del punto en donde realmente se metió la pata. La idea de estos post es comentar mi experiencia intentado cazar estos errores y tirar algunos tips muy útiles que aprendí en el camino.

martes, 19 de junio de 2012

Autitos, píxeles, y cucarachas

"The Big Bang Theory" es una gran serie, llena de diálogos picantes e ingeniosos, pero hay uno en particular que me gustó mucho. Entra Leonard en el departamento y ve a Sheldon con su laptop muy enfrascado en algo. Sheldon lo mira y dice:
- Encontré un emulador en linea que me permite jugar los clásicos juegos de texto de los 80s.
A lo que Leonard responde algo como:
- Eso está muy bueno.
Y Sheldon remata con:
- Oh, sí. Esto corre en la placa gráfica más poderosa del mundo: la imaginación.

(...dejo un blanco para que reflexiones...)

Esta frase va más allá del chiste y es para muchos toda una declaración de principios y un grito de añoranza a los viejos buenos tiempos, donde la computación estaba más verde, donde mucho quedaba por descubrir, donde los grandes saltos en la entonces insipiente industria de los videojuegos aún no se habían dado. No es que ya no queden cosas por descubrir ni brincos que pegar, pero las escalas son otras, y para un niño/adolescente, los 80s eran una oda a la imaginación. Está claro que yo no hice mis primeros pasos en la informática en los primero años de la misma, sino más bien en los 90s (muuucho más tarde). Pero las circunstancias (especialmente no disponer de una conexión a Internet ni nada parecido por ejemplo), hicieron que se sintiera así, y estoy muy agradecido por eso (aunque siempre dije que me hubiese gustado mucho nacer diez años antes).

jueves, 14 de junio de 2012

Programación Extrema

¿Sabían que el XP de "Windows XP" deriva de una metodología de desarrollo conocida como eXtreme Programming? Cuando lo escuché por primera vez me lo imaginé de una forma bastante graciosa, más al comenzar a leer sobre el tema, dado que esto de las metodologías ágiles, si bien tiene su costado serio y muy útil, también da pie para encuadrar como metodología cosas ridículas, o a veces simples cuestiones de sentido común, que no ameritan la denominación de una metodología si no es más que para parecer elegante hablando con ilegítima propiedad. En fin, no vengo a cuestionar ni a defender las metodologías ágiles, ni la programación extrema, ya dije que hay muy buenas y muy malos, y yo no soy particularmente especialista en esto, más allá de mi experiencia de programar durante años sin metodología para descubrir después que lo que hacía podía encuadrarse en alguna de estas, probablemente de las malas. Sólo traigo el título a colación porque planeo malinterpretar uno sus postulados fundamentales, que según wikipedia es:
"Programación en parejas: se recomienda que las tareas de desarrollo se lleven a cabo por dos personas en un mismo puesto. Se supone que la mayor calidad del código escrito de esta manera -el código es revisado y discutido mientras se escribe- es más importante que la posible pérdida de productividad inmediata."
Es obvio que apunta a dos programadores discutiendo los algoritmos e implementaciones, pero vamos a hacer el ejercicio de omitir la palabra "persona" de la definición. ¿Que tal un programador y un robot?... Si el robot va revisando lo que escribe el programador, haciendo pequeños cambios, marcando errores, sugiriendo algunas mejoras, o hasta escribiendo algo de código, ¿no cuenta como programación en pareja? Si esto contara, la cantidad de gente que aplica este postulado ascendería notablemente.

jueves, 7 de junio de 2012

Sobre Dibujos y Bibliotecas

El fin de semana pasado me puse a escribir un graficador de de diagramas de Gantt. Mi hermano está trabajando en el modelado de problemas de de planificación y me había comentado que necesitaba algo para visualizar mejor los resultados que le daba el solver. En principio dibujar un diagrama de Gantt no debería requerir de mucha magia, son solo rectangulitos de colores agrupados con algún criterio por fila. Pero otra vez se me apareció la misma pregunta que me hago cada vez que tengo que hacer un programa de esta naturaleza. Por un programa de esta naturaleza entiéndase un programa con gráficos armados a pata (donde dibujo lineas, rectángulos, puntos uno por uno), lo cual implica una API gráfica con funciones de un nivel relativamente bajo, pero donde hay cosas que configurar, que ingresar, que elegir, y entonces donde también quiero tener alguna que otra facilidad de más alto nivel, como la posibilidad de hacer menúes, botones, y demás controles y cuadros de diálogo estándar.

El problema de como dibujar lo enfrenté muchas veces desde que entré en la universidad y lo solucioné de formas muy diferentes. La primera vez necesitaba ver una simulación de una colonia de hormigas para un contest, donde el objetivo era "programar" una hormiga, pero los organizadores no nos facilitaban el simulador. Como la cosa era contra-reloj, no tenía tiempo de aprender algo nuevo, así que fui por el viejo y querido QBasic y sus comandos de dibujo en los modos gráficos de una ventana de DOS. Muy poco elegante, pero sirvió para salir del paso. La segunda vez tenía que simular la planificación de tareas de un sistema operativo para un práctico de la materia Sistemas Operativos, y para verlo usé OpenGL, sin saber mucho y copiando pedazos de código que encontré en Internet. Antes de la tercera vez pasé por la materia Captura y Procesamiento de Imágenes, donde nos enseñaron a utilizar la biblioteca CImg.

jueves, 31 de mayo de 2012

¿Quien es quien? Hoy: MotoGT

Para terminar con las presentaciones formales, voy a contarles sobre el tercer y último proyecto: MotoGT. En resumidas cuentas, es un juego de carreras de motos 2D de vista superior. Los gráficos son bastante feos ya que no soy un gran dibujante ni diseñador, y la mecánica del juego es por ahora muy básica ya que escribí todo el "engine" (va entre comillas porque no puedo llamarle engine a eso) de cero y sin muchas ambiciones. La verdad es que empezó como una, digamos, prueba de concepto, y después me entusiasme y terminé publicándolo.

Lo primero que hay que saber es que me encanta ese tipo de juego. Como referencia obligada, puedo recordar horas y horas de un verdadero grande del género como fue Death Rally (el original, que pueden bajar legalmente para Windows desde aqui, y que en GNU/Linux corre perfectamente con wine). Lo que mejor lograba este juego según mi criterio era un balance perfecto en la dificultad y el sistema de premios (mejores autos, más armas, la posibilidad de competir en carreras más difíciles, trampas, sabotajes, premios inesperados, un adversario final, etc). Con gráficos impecables para la época, una combinación excelente de carrera y combate, y un sinfín de agregados y personajes, hacían que uno no se cansara de ver y hacer siempre lo mismo como puede ocurrir fácilmente en un juego aparentemente tan simple. Desde chico intenté programar juegos de carrera de vista superior (además porque es relativamente fácil para empezar). Por otra parte, hay otra historia más personal sobre una deuda pendiente que será develada en otro post, y que me lleva a tener un especial cariño con estos juegos y a querer experimentar en el género.

viernes, 25 de mayo de 2012

Toolchains alternativos en ZinjaI

Wikipedia en inglés empieza la definición de toolchain con algo que traducido sería más o menos "el conjunto de herramientas de programación que se utilizan para crear un producto...". Esta definición involucra compilador, editor, depurador, etc. Pero en la práctica he visto usar este término para referirse mayormente al conjunto de herramientas que verdaderamente producen el ejecutable; es decir el compilador en sentido general, que incluye preprocesador, compilador, ensamblador, enlazador, y cualquier otra cosa que pueda ser necesaria para pasar del fuente al ejecutable. Mi compilador amigo es el archiconocido gcc en GNU/Linux (y su port para Windows de 32 bits, mingw32), pero existen muchos otros. Entre las alternativas puedo mencionar al compilador de intel (que nunca probé, pero que tiene muy buena fama en el ambiente científico porque logra ejecutables más rápidos en ciertas configuraciones y un set interesante de herramientas auxiliares), o al flamante conjunto LLVM+Clang. LLVM es un conjunto de herramientas que forman parte de un toolchain propio modular y flexible. Clang es el módulo que le falta para completar un conjunto enteramente basado en llvm que compile de principio a fin código C++. Su creciente popularidad y su rápida evolución, junto con otras ventajas que forman parte de su concepto me hacen pensar en integrarlo en ZinjaI. Y ya que voy a estar en el baile, pretendo hacer esta integración de una forma más o menos genérica para que al final ZinjaI permita configurar fácilmente toolchains alternativos, o incluso diferentes formas de construir un proyecto independientemente del toolchain.

lunes, 21 de mayo de 2012

Emparchar vs Reescribir: ¿qué hacer con un diseño limitado?

Rara vez, al comenzar un proyecto personal, el diseñador/programador sabe exactamente a donde va a llegar. Puede tener una idea bastante aproximada de hacia donde quiere ir, y hasta de qué podría llegar a cambiar, pero inevitablemente algo va a pasar que lo va a obligar a plantearse la posibilidad de rediseñar medio programa. Solo un experto iluminado con gran experiencia puede proponer desde el comienzo el diseño adecuado en un proyecto más o menos complejo. En general, el programa muta, el programador madura, y las cosas cambian. La mayoría de los mortales, empezamos con un diseño que por alguna razón en algún momento pareció correcto (o tal vez no pareció del todo correcto, pero si pareció ser la mejor de las posibles opciones), y luego vemos como el proyecto, si sobrevive al embate inicial, va cambiando lenta O dolorosamente: lentamente cuando las cosas se hacen bien, dolorosamente cuando se hacen rápido.

Es decir, a la hora de implementar algo no previsto en el diseño inicial de un sistema, podemos tomarnos todo el tiempo necesario replantear el diseño inicial para hacerlo más flexible, recodificar lo que sea necesario recodificar para cumplir con el nuevo diseño, actualizar la documentación, etc. y luego agregar pacíficamente la nueva funcionalidad; o bien podemos empezar a parchear el código poco flexible que escribimos en un primer momento para tener rápidamente al menos un prototipo andando. Por lo general, cuando el cambio no es tan grande, voy por la segunda alternativa, hasta que llega un día en que mi código es 90% parches y 10% del pobre diseño original, y se hace imposible seguir añadiendo cosas (o al menos hacerlo sin romper lo que ya estaba andando).

martes, 15 de mayo de 2012

Las mil y una distribuciones

Sabido es que hay cientos de distribuciones de GNU/Linux dando vueltas, y que de cada una conviven varias versiones al mismo tiempo. Es decir, unos usuarios tienen Fedora, otros Ubuntu, otros Arch, algunos Mint, unos pocos Slackware, aquel usa Gentoo, un amigo OpenSuse, etc, etc, etc. Y además, supongamos que solo existiera Ubuntu, alguno usará la de 32 bits, otro la de 64, alguno seguirá con la 10.04 porque es LTS, otro tendrá la 12.04 porque le gusta tener siempre lo último, el más pacífico tal vez corra la 11.10 porque aún no aplicó las actualizaciones, y hasta uno por alla con un hardware viejo y raro se quedó en la 9.10 porque es la única que le reconoce todo y le anda rápido con su poca memoria.

Tanta variedad trae problemas (y ventajas, pero vengo a plantear algunos problemas). Para empezar, los programas de terceros de los que dependen ZinjaI o PSeInt varían enormemente. Por ejemplo, si quiero correr algo en una terminal gráfica, ¿uso xterm? o ¿konsole? o ¿gnome-terminal? ¿o qué?. Supongamos que uso konsole, los argumentos que recibía en kde3 eran unos, pero en kde4 son otros, y hasta varían entre versiones de kde4. O supongamos que uso gnome-terminal. Hasta cierta versión de gnome uno lanzaba un proceso en esta terminal y esperaba a que termine, pero a partir de no se cuando empezó a lanzar el proceso algo así como en segundo plano, entonces el comando que hace la llamada finaliza enseguida, aunque el proceso que quería ver tal vez ni siquiera alcanzó a comenzar. Otros casos podrían ser instalar íconos y asociar tipos de archivos con los muchos exploradores de archivos (soluciones como xdg empiezan a parecer estándar pero aún no están en todos lados), o lanzar un comando como administrador (gksudo es lo más común, pero tampoco está en todos lados).

jueves, 5 de abril de 2012

El autocompletado y yo (capítulo 1)

Si hay algo que hace cosas raras en ZinjaI es el autocompletado. A veces funciona, a veces no, a veces se confunde, y otras inventa. Un buen programador sabrá notar sus defectos. Por eso voy a intentar, con una serie de artículos, justificar algunos con sus virtudes, contarles porqué tomé estas decisiones a la hora de diseñarlo, y de paso explicar en lineas generales cómo funciona, qué hace bien, qué hace mal, qué no hace, y qué planes tengo para mejorarlo.

La culpa de todo la tienen Basic y Borland C++ Builder. Como ya comenté antes en algún que otro post, aprendí a programar con Basic y jugué con eso por muchos años. Y allí no había autocompletado alguno (a menos que llamemos a los atajos de teclado que escribían palabras clave autocompletado, pero no es lo mismo). De hecho en los primeros Basics que usé no había siquiera un "editor" (entre comillas porque es discutible), hasta que descubrí QBasic y QuickBasic. Es por esto que en mis comienzos no estaba acostumbrado al autocompletado, y entonces no tenía mucho con que comparar cuando usaba uno como para opinar sobre sus virtudes y defectos. Pero en Builder, que es lo que usábamos en la facultad cuando aprendí C++, había algo que cualquiera podía notar aún sin saber nada del asunto: era desesperantemente lento. Las PCs de los laboratorios de la universidad no eran aviones ni mucho menos, pero tampoco estaban tan mal para ese momento. Y aún así, cuando uno ponía un punto después de un objeto, o la flecha después de un puntero (cosa que ocurre cada 3 segundos mientras se programa en C++), podía irse a tomar un café y volver al rato a ver si había terminado de cargar el menú de autocompletado. Y esto me sacaba de quicio, claro está. Así que cuando empecé a pensar en el autocompletado de ZinjaI, solo impuse una condición: tenía que ser rápido.

miércoles, 28 de marzo de 2012

¿Quien es quien? Hoy: ZinjaI

Siguiendo con las presentaciones, toca hablar de ZinjaI (aclaración: la ultima letra es una i, pero en mayúsculas, no una L como parece con muchas fuentes, y lo pronuncio zinyai, por su significado: "ZinjaI is not just another IDE"). ZinjaI es actualmente un IDE (entorno de desarrollo integrado) para programar en C/C++, que debería ser útil tanto para principiantes como para programadores avanzados. Pero originalmente, no iba a ser así.

Todo empezó por un programa de becas que tienen en mi facultad para que alumnos de grado se inicien en investigación. El alumno se presenta con un director y un plan de trabajo para dedicarle algunas horas a la semana durante año y medio a algun proyecto de investigación o relacionado. A cambio recibe, entre otras cosas, una formación básica, una primer experiencia, y un punto más en su CV.  En un momento de mi carrera, el docente titular de las primeras materias de programación, aprovechando lo que ya tenía encaminado con las primeras versiones de PSeInt me ofreció aplicar para una de estas becas, para formalizar ese desarrollo y continuarlo.

Como la parte más importante (el intérprete en sí) de PSeInt ya estaba desarrollada, me puse a pensar qué otra herramienta nueva podría ser de utilidad en el aula. Dado que en nuestra carrera, luego de pseudocódigo pasamos a utilizar C++, lo lógico era pensar en una herramienta para empezar a trabajar con C++. 

lunes, 19 de marzo de 2012

Juguemos al diagrama de flujo

El diagrama de flujo es una alternativa directa al pseudocódigo. Siempre digo a mis alumnos que se puede pasar del pseudocódigo al diagrama y al revés mecánicamente, todas las veces que se quiera, y sin perder nada en el intento. Esto es bastante cierto, la información importante para el intérprete no varía. Es decir, no se pierde ninguna instrucción ni ningún argumento en el pasaje. A algunos estudiantes les resulta más fácil empezar planteando sus algoritmos en un diagrama antes que en un código. Cuando el algoritmo involucra estructuras de control (condicionales y/o bucles), el diagrama de flujo permite visualizar mejor las posibles lineas de ejecución que un código escrito secuencialmente.

Actualmente PSeInt permite ir del pseudocódigo al diagrama, pero no al revés, no permite editar el diagrama. Además de que los diagramas que muestra no son de los más lindos, y el visor no es de los más rápidos, siempre me pareció un punto bajo, un hueco donde se podía aportar mucho. Pues bien, en la próxima versión incluiré nuevo y fantabuloso visor/editor de diagramas de flujo, parecido al que se muestra en el video:

lunes, 12 de marzo de 2012

Su consulta no nos molesta

Antes de que lean esta entrada tengo que hacer una aclaración: en un proyecto de software libre, los usuarios son uno de los recursos más valiosos, no solo lo digo yo, lo deja muy claro Eric Raymond en "La Catedral y el Bazar" (no dejen de leer ese ensayo). En particular, en mis proyectos, donde no hay un gran equipo trabajando en el testing, el diseño, la documentación, etc. como sí puede suceder en una gran empresa, o en una fundación con más recursos, el feedback de los usuarios es vital, y por eso hay que cuidarlos, y no atacarlos como voy a hacer a continuación.

Creo que el problema se debe en gran medida a que el usuario medio, por decirlo de alguna manera, está acostumbrado a utilizar software privativo (pensando en enlatados de uso diario, no en desarrollos a medida para una empresa), y esto le ha generado muy malos hábitos, al menos desde la perspectiva de un desarrollador de software libre. Más allá de mis alegatos a favor del software libre, no soy un extremista, y sé que hay software privativo de muy buena calidad, que hay empresas serias y desarrolladores muy capaces en ellas; pero la forma en que se trabaja de un lado y del otro es muy diferente, y los usuarios, en consecuencia, también lo son.

miércoles, 7 de marzo de 2012

Sobre tipos de variables y bolas de cristal

En PSeInt siempre tuve un dilema interesante, y aún hoy no tengo certezas sobre cual es la mejor solución. El problema es cómo determinar el tipo de una variable. En este lenguaje, no es necesario declarar las variables y decir de que tipo son, pero sin embargo cada variable tiene un tipo asociado. Es decir, hay variables para guardar texto, otras para números, y otras para valores de verdad. El usuario casi nunca dice explícitamente de qué tipo son las variables que usa en su algoritmo (en realidad a veces sí, se puede configurar, pero en la mayoría de los perfiles no). Entonces, el interprete debe "adivinarlo", y para ello debe analizar qué se hace con estas variables, o qué datos se guardan. O sea, en realidad debe tratar de deducirlo. Pero no siempre se puede, y el problema es ¿qué hacer cuando no?.

Por ejemplo, tomando el siguiente fragmento de pseudocódigo:
    Leer A
    Escribir "Usted ingreso: ",A
La variable A podría ser de cualquier tipo, según qué ingrese el usuario. Si analizamos qué ingresa el usuario para determinar el tipo, en cualquier caso el algoritmo funciona. Pero este otro fragmento:
    Leer Clave
    Si Clave="123" entonces ...
funcionaría mal, ya que al leer 123 el interprete deduciría que es numérica, pero al querer comparar con la cadena de texto "123" generaría un error.

domingo, 4 de marzo de 2012

¿Quién es quién? Hoy: PSeInt

Antes de poder escribir sobre tópicos o problemas específicos de alguno de mis tres proyectos, por prolijidad debería escribir artículos presentándolos. Debería contar para qué sirven, como nacieron, en qué estado están, hacia a donde van, qué tienen de interesante, etc. Por eso, este artículo inaugura una trilogía de posts llamada ¿quién es quién? donde trataré de hacer las debidas presentaciones. Según el orden cronológico, de los tres proyectos que se considerarán centrales por ahora en este blog (no quiere decir que no haya tenido otros más chicos dando vueltas, o que no aparezca uno nuevo en el futuro), el primero en cobrar vida fue PSeInt; y su historia comienza así:

Tuve la suerte de aprender a programar (o algo similar, porque era un cavernícola, pero me las rebuscaba) mucho antes de entrar en la universidad. Aprendí de muy chico con Logo y Basic, y seguí con este último y sus derivados durante largos años, tal vez más de lo aconsejable. Probé desde el primer Basic para DOS hasta los modernosos Visual Basics de la época, pasando por apbasic, zbasic, qbasic, quickbasic, etc. Aunque podría resumirlo en Quick Basic y Visual Basic, los demás son solo leves variaciones. Programar siempre fue un hobbie, casi un arte, como tocar la guitarra, o escribir cuentos, algo divertido, así que hice mucha mucha práctica. El punto es que llegué a la universidad sin saber lo que era una clase o un puntero, pero con un dominio casi absoluto sobre los ifs anidados, los fors, los whiles, y las expresiones matemáticas que uno usa habitualmente al programar.

domingo, 26 de febrero de 2012

Actualizaciones automáticas, instalación de complementos, y Windows haciendo cosas raras

En el sitio de ZinjaI agregé hace un tiempo una sección de complementos y versiones de prueba entre las descargas. Lo que uno encuentra allí son ejecutables de versiones no estables (¿alguna lo es realmente?... no, pero estos no están ni testeados a veces) y archivos para facilitar el trabajo con bibliotecas (templates de proyectos, archivos para el autocompletado, binarios, documentación, etc.). Estos archivos se presentan como comprimidos (zip o tgz) y la "instalación" consiste en que el usuario lo descargue y lo descomprima encima de la instalación original de ZinjaI.

Por el momento sólo hay un complemento (para trabajar con la biblioteca SFML) y encima no muy actualizado, pero me gustaría mejorar esa situación actualizándolo y agregando algunos otros. Dándole vueltas al asunto empecé a analizar la idea de incorporar una opción de menú para instalar los complementos directamente desde ZinjaI. Es decir, que ZinjaI los descomprima donde el sabe de modo que no haya forma de equivocarse, y podría ser que en el futuro, además de descomprimir, también ejecute algunas acciones como alterar configuraciones para colocar botones accesos a las referencias en la barra de herramientas.

De la instalación de complementos desde el mismo programa surgen dos tópicos interesantes para comentar: 1) ¿que tal si hago que ZinjaI acceda al sitio y descargue él los complementos para que el proceso sea todavía más fácil y rápido?, y 2) algunas cuestiones de implementación relacionadas a los privilegios y permisos de usuario que requiere esta instalación.

miércoles, 15 de febrero de 2012

Como abandonar los frames de html en 3 simples pasos

En estos días tuve que hacer pequeñas modificaciones en los sitios web de ZinjaI y PSeInt, y esto me llevó a recordar lo poco recomendable que era utilizar frames html para armarlas. Tengo que aclarar que no se casi nada sobre lenguajes de programación y marcado para web. Es decir, entiendo como funcionan, pero no estoy realmente familiarizado con ninguno de ellos. Simplemente aprendí lo escensial de html y javascript durante un curso en mi carrera de grado y completé esta formación con un curso de php muy muy básico que tomé por separado (no tengo ni idea de la sintaxis para hacer una clase en php por ejemplo). Con este poco conocimiento y google a mano me las rebusco para armar los sitios webs de mis proyectos, ya que son sitios bastante simples, razón por la cual tampoco me tomé el tiempo de profundizar mucho sobre estos temas. Y entonces, como era de esperar, la implementación es horrible.

Basicamente me gustan los diseños claros: una pequeña cabecera que no moleste, un menú bien a mano, y el contenido al centro ocupando la mayor parte de la ventana. Una forma muy fácil de implementar esta organización en html es usando frames. Los frames básicamente particionan el espacio en varias sub-areas y dentro de cada una se carga una página web individualmente. Entonces, cuando empecé hace años a armar el sitio del pseint, dividí la ventana en tres: cabecera, menú y contenido, escribí un html para cada una y listo. Lo bueno de los frames es que cada área puede ser independiente y cargar una página completa hasta de otro sitio si se quiere. Además, al acceder a un enlace en el contenido por ejemplo se actualiza esa área, manteniendo el menú y la cabecera intactos.

lunes, 13 de febrero de 2012

Bienvenido Al Mundo Del Mañana

Probando, probando... Sí, ssssí, hola... hola... 1,2,3, probando. Bien, parece que está encendido...

Tengo el agrado de dirigirme a ustedes con el vital objetivo de informarles de que va este nuevo blog. Para empezar hay que saber que tengo, hasta ahora, tres proyectos de sofware que empecé hace tiempo y mantengo en mis ratos libres: PSeInt, ZinjaI y MotoGT. El primero es una herramienta para aprender a programar, el segundo un IDE para programar en C++, y el tercero un juego de carreras.

Resulta que estos programas no son perfectos en muchísimos aspectos, no se ajustan a lo que algunos usuarios esperan o imaginan en otros, o simplemente tienen cosas medio raras que, para bien o para mal, llaman la atención del programador más avesado. Entonces, suelo recibir preguntas cuyas respuestas no son cortas o directas, sino que tienen historia, que hay que considerar casos, hay que analizar alternativas, o simplemente hay que aceptar errores y limitaciones. Pues bien, este será el lugar donde trate esos temas, explayandome lo necesario y sin estructura alguna.

Por ejemplo: mil veces me han pedido que agregue la posibilidad de definir funciones en PSeInt; o me han preguntado por qué el autocompletado de ZinjaI actúa extraño; etc. Publicaré mis respuestas esperando que se entienda lo que me llevó a hacer las cosas de ese modo, y tal vez alguien se enriquezca de mi experiencia para no cometer en sus proyectos los mismos errores, aprenda de mis pocos aciertos, o simplemente sacie su infinita curiosidad. Además, va a ser un buen lugar para publicar las cosas que pasan actualmente en mi cabeza y las discusiones que tengo conmigo mismo o con otros usuarios en relación a nuevas funcionalidades que planeo implementar y que presentan algún desafío interesante.

Leerán artículos de todo tipo, desde aquellos que simplemente expliquen cuestiones funcionales sin entrar en detalles, hasta otros que discutan cuestiones de implementación, con contenido algo más técnico. Algunos estarán muy relacionados con lo que hacen mis programas, otros tocarán temas más generales, como la programación multiplataforma, el desarrollo de software libre, etc. En lo personal, me servirá para documentar muchas decisiones, pero espero que a alguien más le resulte útil o al menos interesante.