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.
viernes, 28 de septiembre de 2012
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é?
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.
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.
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).
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:
#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.
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).
- 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.
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.
Suscribirse a:
Entradas (Atom)