martes, 23 de diciembre de 2014

Bibliotecas externas en versión debug

Siempre pensé que era mejor utilizar versiones "release" de las bibliotecas de terceros en mis proyectos, para todas las compilaciones, aún en mis versiones para debug. Es decir, que si mi programa usa una biblioteca B, al depurarlo me interesa solo depurar mi parte. Agregar la información de depuración de B sería agregar ruido. Hace poco comprobé que esto no siempre es recomendable. Es algo que ahora me parece muy obvio, pero la verdad es que antes no le había dado importancia. Nunca había usado intensivamente una versión debug de una biblioteca externa, y por eso no había notado las muchas ventajas que esto tiene.

domingo, 14 de diciembre de 2014

Por qué la ejecución era tan leeenta en el depurador

Hace unos días comenté que había estado renegando para depurar un proyecto en Windows porque al correrlo en el depurador la ejecución tardaba 17 veces más de lo normal. Encontré en aquel momento un workaround para salir del paso, pero no sabía entonces la causa real del problema. Cerré el post prometiendo escribir si la averiguaba, y ahora vengo a cumplir con eso. Ya encontré la causa, y una solución muy simple que, como siempre, estará incluida en ZinjaI para la próxima versión (muy pronto).

jueves, 11 de diciembre de 2014

Cuando la ejecución en el depurador es mucho más leeenta

Saben que en ZinjaI (y en muchísimos otros IDEs) tenemos dos formas de ejecutar un proyecto: la "normal" y la "debug". La "normal" (Ejecución->Ejecutar o F9) guarda, compila y ejecuta el resultado como si hubiésemos hecho doble click en el exe desde el explorador de archivos. La ejecución "debug" (Depuración->Iniciar o F5), en cambio, ejecuta a través de gdb. Es decir, ejecuta gdb (el verdadero depurador que hay detrás de ZinjaI), y le pide a este que cargue y ejecute el exe. Para tener control sobre esta ejecución, gdb puede hacer internamente cosas raras, normalmente sin que lo notemos. Me dí cuenta hace poco que en Windows alguna de estas cosas raras puede hacer que el programa corra mucho más lento que en la ejecución normal. Y cuando un programa, en su ejecución normal revienta luego de unos pocos minutos de proceso, este "enlentecimiento" se torna un problema grave, porque para intentar depurarlo debemos esperar una eternidad hasta llegar al problema, cada vez que lo probamos. Ahora tengo un mecanismo interesante para resolver el problema de analizar el error con el depurador sin esperar tanto tiempo.

miércoles, 19 de noviembre de 2014

Más novedades en la depuración con ZinjaI

Ya les comentaba en otros posts que venía haciendo cambios importantes en ZinjaI para la próxima versión, y especialmente en lo relacionado a la depuración y el manejo de inspecciones. Y como algunos son cambios muy grandes, esta próxima versión se viene demorando bastante. Pero creo que la espera va a valer la pena, porque así como por un lado estos cambios son grandes y lentos de implementar, por el otro lado los resultados son especialmente útiles. Todo rediseño en las tripas de un software, si se hace después de un tiempo prudencial y de haber aprendido mucho de los errores (u ordenado más precisamente, de haber aprendido de muchos errores), facilita el trabajo futuro, permitiendo pensar en cosas que antes no eran posibles o requerían demasiado trabajo. Y les vengo a mostrar un ejemplo de eso, que parece bastante mágico si se lo mira desde el ángulo adecuado.

viernes, 14 de noviembre de 2014

SFINAE: Magia con templates en C++ (parte 3)

Finalmente llegamos a la última parte. Ya introduje en la parte 1 qué es eso de sfinae, y en la parte 2 cómo usarlo para consultar en tiempo de compilación la existencia de algo. La idea era poder plantear ejercicios de programación autocalificables; es decir, que validen solos si son correctos o no al ejecutarse. Para ello nos falta acomodar un poco el resultado de la parte 2 para que sea más cómodo de usar. Primero vamos a definir una macro para declarar con una linea la clase que hace la prueba de existencia de algo. Luego vamos a definir otra macro para declarar con una linea una función que solo se ejecuta si se pasa una prueba. Con todo eso, podemos plantear un ejercicio como el siguiente:

lunes, 10 de noviembre de 2014

SFINAE: Magia con templates en C++ (parte 2)

En la primer parte comenté cómo utilizar algunas reglas particulares de la especialización de funciones genéricas en C++ para permitir o no una determinada especialización de acuerdo a alguna característica de un tipo de dato. La clave estaba en que un argumento de la plantilla intentaba especializar otra plantilla con un entero que surgía de un sizeof. Si en esa otra plantilla fallaba la substitución, no se generaba un error mientras exista alguna otra plantilla en la que no falle. Cualquier cosa que acepte el sizeof nos sirve. Esto permite, por ejemplo, preguntar por la existencia de métodos o atributos, aplicándole el sizeof a un puntero al mismo. Y así, con pequeños podemos "controlar" varias cosas. Veamos cómo con una característica de C++11 lo generalizamos mejor, y con un par de lineas adicionales lo hacemos mucho más fácil de utilizar.

jueves, 6 de noviembre de 2014

SFINAE: Magia con templates en C++ (parte 1)

SFINAE son las iniciales de "Substitution Failire Is Not An Error" (un fallo en una substitución no es un error). Así se llama informalmente a un conjunto de situaciones muy particulares en C++, donde un error que resultaría de intentar especializar un template es ignorado silenciosamente durante la compilación. Si combinamos esto con los mecanismos de sobrecarga y resolución de nombres, podemos lograr cosas muy raras, como preguntar si una clase existe, si tiene cierto método, o si se puede usar de tal forma. Con algunos pocos trucos adicionales podemos tener código que se ejecute solamente si es válido, pero si no lo es (y esto es lo interesante) no genere errores de compilación, sino que utilice un camino alternativo. Llegué a esto tratando de armar ejercicios de programación que se califiquen a sí mismos (para hacer evaluación continua sin perder mucho tiempo de clases), y como el resultado es técnicamente muy interesante, aprovecho la excusa de siempre para documentarlo.

domingo, 28 de septiembre de 2014

Sobre templates y tiempos de compilación

Cualquiera que utilice frecuentemente clases genéricas en C++ sabe que el uso de templates puede aumentar considerablemente los tiempos de compilación de un proyecto, dado que una clase/función templatizada no puede compilarse en un .cpp separado del .cpp que la usa, sino que debe estar completamente definida y declarada en el .h... ¿o no?. Siempre uso como ejemplo extremo la biblioteca CImg, que consta de un archivo .h de alrededor de 2MB de código fuente, 99% genérico, casi todo directa o indirectamente asociado a su clase principal (CImg). Esto hace que compilar un ejemplo muy pequeño tarde unos 25 segundos (en un I7-870), tiempo que aumenta notablemente cuando el ejemplo deja de ser tan pequeño. En este artículo les cuento un truco que voy a incluir en la plantilla del complemento para ZinjaI de CImg, que permite bajar esos 25 segundos a alrededor de 9. Es decir, menos de la mitad. Y esta diferencia será mucho más grande cuando el ejemplo se complique.

viernes, 19 de septiembre de 2014

Mientras tanto, en PSeInt...

Hace ya un buen rato que no vemos versiones nuevas de PSeInt. En buena parte se debe a que por diversos motivos le he dedicado realmente poco tiempo últimamente. Pero no quiere decir que no haya ocurrido nada. Hay algunos cambios ya implementados para la próxima versión oficial, y hay más cambios en camino, algunos muy interesantes. En este post les cuento un poco qué nos depara el futuro a corto y mediano plazo en PSeInt.

domingo, 14 de septiembre de 2014

Excepciones y RAII (control de errores parte 2)

En el post anterior dejé planteado el problema de cómo manejar, a nivel de código, la posibilidad de que una función falle. Es decir, con qué mecanismo poder o no detectar un error, identificarlo de forma más o menos fina, y eventualmente actuar en consecuencia. Todo pensando en cuanto cuesta eso, no en términos de eficiencia, sino de legibilidad del código, de trabajo extra a la hora de programar, y en la usabilidad de estas clases o funciones que podrían fallar. Describí a grandes rasgos, con ejemplos demasiado breves, las primeras opciones que uno podría considerar, y dejé entrever alguna conclusión.

Podríamos resumir con algo como lo que sigue. Pareciera que las excepciones son lo ideal para cosas que podría ser aceptable que fallen, aunque no sería esperable ni tan frecuente. Por ejemplo, que me quede sin memoria, que se caiga abruptamente una comunicación, etc. Mientras que dejamos los asserts (o _revienta) para cosas que definitivamente no deberían ocurrir, a menos que el programa contenga un error. Ahora vamos a analizar algunos detalles más finos e interesantes sobre el manejo de excepciones.

sábado, 6 de septiembre de 2014

Control de errores con C++

Hoy vengo a divagar sobre un aspecto en el diseño de interfaces para clases y/o funciones que siempre me genera dudas: ¿qué pasa cuando algo sale mal durante la ejecución? Muchas cosas pueden fallar, en diferentes niveles, algunos aceptables y otros no. ¿Cuándo retornar un código de error? ¿Cuándo simplemente retornar true/false? ¿Cómo manejar esto a nivel de código? ¿Cuándo usar excepciones? ¿Cuándo assert? ¿Cuando ignorarlo? Tengo que confesar con vergüenza que durante mucho tiempo vi a las excepciones como algo a evitar, una funcionalidad innecesaria de segunda clase (como un garbage collector :). Evité por años usarlas, y por ello no se ven hoy en día en mis códigos. Pero me voy dando cuenta de que estoy equivocado. No son la solución a todos los problemas, pero tienen lo suyo, y hacen cosas que otros mecanismo no. La idea es entonces analizar cada mecanismo de control de errores para tratar de entender dónde conviene usar cada uno.

lunes, 1 de septiembre de 2014

Entendiendo la tabla de inspecciones (parte 2)

Siguiendo con esta serie de artículos sobre cómo hace ZinjaI para mostrar las inspecciones durante la depuración, ahora voy contar un poco más qué pasa por debajo, en gdb, el verdadero depurador. Si alguien alguna vez usó directamente gdb sabrá que su interfaz es básicamente una linea de comandos, donde uno ingresa por ejemplo "break hola.cpp:12" para agregar un punto de interrupción, o "print x" para ver qué hay en la variable "x". Sin embargo, cuando uno programa un front-end para gdb (una interfaz, como ZinjaI), puede utilizar un conjunto diferente de comandos que otorgan una salida más uniforme y predecible para que analizarla automáticamente sea más simple y eficiente. Esta interfaz alternativa (también tipo linea de comandos) se conoce como MI (creo que por machine-interface).

lunes, 18 de agosto de 2014

Preguntas frecuentes: "Error al crear proceso"

Ya les comenté en el post anterior que hay algunos errores que se les manifiestan a muchos usuarios de ZinjaI, y que entonces iba a comentarlos aquí, con sus causas y pseudo-soluciones para facilitar un poco las cosas. Decidí empezar por dos problemas particulares (de los cuales creo que ZinjaI no tiene culpa alguna), porque son de los que más me han consultado a mi correo personal. El que presento hoy tiene que ver con esos infames comerecursos que son los antivirus, y se manifiesta de esta forma: cada vez que desde ZinjaI se quiere compilar y ejecutar un programa, la compilación finaliza con éxito (suponiendo que el código era correcto), pero en la ventana de ejecución sale algo como "Error al crear proceso: C:\booga\dooga\algun_programa.exe".

jueves, 14 de agosto de 2014

Preguntas frecuentes: "No hay disco en la unidad"

El título de este post muestra parte de un mensaje de error que aparece frecuentemente en PCs con Windows tras actualizar ZinjaI a su última versión. ZinjaI está lleno errores, algunos que conozco, seguramente cientos que todavía no noté, pero este en particular, y otro que comentaré en el próximo post, no son errores propios. Son "problemas" de Windows (o sus drivers) uno, y del antivirus que lo acompaña el otro. Me cansé de responder consultas a mi correo personal por estos problemas una y otra vez, así que lo publico acá para que cualquiera lo encuentre fácil, y para redireccionar a los próximos que pregunten.

jueves, 31 de julio de 2014

Entendiendo la tabla de inspecciones (parte 1)

La tabla de inspecciones de ZinjaI es esa grilla que aparece abajo a la izquierda al iniciar una depuración, donde podemos escribir nombres de variables y otras expresiones C++ para ver cuánto valen en cada pausa de la ejecución. Hay algunos detalles de interfaz conviene conocer como usuario de ZinjaI, y hay otros sobre la implementación interna de la misma y su comunicación con gdb que se podrían ignorar tranquilamente, pero igual resultan interesantes. Y es que desde hace un buen tiempo venía pensando en reescribir en ZinjaI todo el código relacionado a esta tabla y al manejo de inspecciones en general. Ahora que la reescritura ha avanzado bastante y las cosas se van definiendo, aprovecho para contarles de qué se trata y documentar un poco algunos trucos que se usan por debajo.

martes, 24 de junio de 2014

Sobre señales y volcado de datos

Creo que para la mayoría de los programadores, la depuración es la etapa que más tiempo consume en un desarrollo. A mi me gusta modificar un poco la regla del noventa-noventa para decir que el segundo 90% corresponde a la depuración. Depurar implica probar un programa para detectar errores, identificar sus causas, plantear posibles soluciones, y aplicar el mismo proceso recursivamente sobre estas soluciones, hasta que la recursión se corte porque ya [creemos que] no hay errores.

La parte de identificar la causa puede ser muy tediosa cuando llegar al punto en que se produce o manifiesta el error lleva bastante tiempo de ejecución. Porque el procesamiento previo es costoso, porque hay que cargar muchos datos, porque depende de acciones manuales del usuario, porque no sabemos bien cuándo va a manifestarse, por lo que sea. Y a veces hay que repetirlo y repetirlo para ir acotando el problema, porque cuando vemos el error, nos damos cuenta de que nos falta información, de que tenemos que modificar un poco el código para que genere y/o muestre más resultados intermedios y volver a probar. Hoy les comento un truco que, utilizando señales, permite generar en cualquier momento, desde cualquier punto de la ejecución, un volcado de datos ad-hoc y arbitrario hacia un archivo, para analizar el estado del programa.

martes, 17 de junio de 2014

Corrigiendo un ejecutable sin reiniciar la depuración

En este post les vengo a mostrar una funcionalidad nueva en ZinjaI, que verán en la próxima versión (a publicarse dentro de pocos días), y que bien presentada parece mágica, aunque está  lejos de serlo. Con el ejemplo adecuado, puedo hacer que se parezca al maravilloso Edit & Continue de Visual Studio (la funcionalidad que realmente me maravilla y envidio de ese IDE que tan poco conozco). Consiste en la posibilidad de modificar el ejecutable mientras se está ejecutando, durante una pausa en una depuración, alterando el código fuente, recompilando, y continuando luego de la pausa desde el mismo punto con el binario nuevo como si nada. Estoy a años luz de ofrecer algo como eso de verdad, pero puedo hacer algunos trucos simples para emularlo en casos muy muy particulares. Vean el video y luego sigan leyendo.

miércoles, 14 de mayo de 2014

Cómo [no] ayudar al compilador

Siempre les digo a mis alumnos: "el compilador es más vivo que todos nosotros juntos", y la experiencia me ha demostrado que es una buena máxima para respetar a la hora de programar. Me refiero a esos momentos donde programamos algo de cierto modo que no es precisamente el más prolijo ni el más simple, pero imaginamos que hacerlo como dicen los libros sería agregar algún tipo de sobrecarga evitable. Y esto se debe a que imaginamos mal o desconocemos qué va a hacer con eso el compilador.

Por dar un ejemplo simple, he usado mil veces macros de preprocesador (#define func(x) bla...bla) en lugar de funciones para evitar la sobrecarga que significa invocar a una función. Está claro que a nivel ensamblador la llamada a una función, por simple que sea ésta, implica varias instrucciones adicionales (preparar el stack, crear variables locales, pasar los argumentos, recibir el resultado, etc). Pero debería estar igual de claro que considerar eso al codificar es un gran gran error. Es un problema que un buen compilador sabrá resolver mucho mejor que nosotros. En este post quiero dejar algunos tips sobre cosas como estas no hay que hacer y otras  cosas sí, si queremos que lo que hacemos de verdad le sirva al compilador para generar un mejor ejecutable.

lunes, 5 de mayo de 2014

Interesante problema de Estructuras de Datos

En varios casos en ZinjaI tengo datos que necesito utilizar en dos contextos diferentes, requiriendo en uno el conjunto completo, y en otro solo una parte. Tomemos por ejemplo la lista de breakpoints de un proyecto. Mientras se edita un archivo fuente, la mayoría de las operaciones con breakpoints (agregar, quitar, definir propiedades, etc) se hará sobre los de ese fuente. Además, al guardar esta información en el proyecto, los breakpoints de un fuente se guardan asociados al mismo. Sin embargo, una lista de breakpoints por fuente no siempre es lo mejor porque muchas operaciones en el depurador (a nivel gdb) se harán sobre la lista completa. Por ejemplo, al inicializar la depuración, se deben setear todos los breakpoints en gdb antes de ejecutar, sin importar de dónde provengan. La misma idea aplica a varias otras cosas, como por ejemplo los archivos del proyecto (que están agrupados por categorías) o próximamente las inspecciones (que están asociadas a distintas ventanas/paneles de la interfaz).

Entonces, hace poco me armé un par de clases para representar dos contenedores que operen sobre los mismos elementos. Es decir, habrá un contenedor para el conjunto global, y otro para los subconjuntos parciales. A nivel algoritmos y estructuras de datos creo que es un ejercicio interesante, y por eso vengo a (documentarlo) comentarlo  en este post.

lunes, 14 de abril de 2014

Aplicaciones visuales con ZinjaI

Después de algunos años ya de utilizar ZinjaI en combinación con wxFormBuilder, creo que la integración de ambas herramientas ha quedado bastante aceitada. Para quien no lo conozca, wxFormBuilder es una programa que permite "dibujar" interfaces (digamos ventanas para nuestros programas) de forma visual (como si fuera Visual Basic, o  Borland Builder), y luego generar automáticamente el código fuente C++ (o Python) que produce esas interfaces para usarlas en nuestros proyectos. Por un lado nos automatiza un poco una tarea a veces tediosa y repetitiva, y por otro nos ahorra escribir mucho código y consecuentemente también investigar la forma de utilizar la biblioteca de componentes gráficos.

Desde un proyecto de ZinjaI, podemos aprovechar esto, y ZinjaI está particularmente preparado para simplificar mucho la interacción entre ambas partes, y estas características de ZinjaI han mejorado bastante en las últimas versiones. Por eso en este post voy a resumir qué se puede hacer, en líneas generales cómo funciona a nivel del código (y aquí va otro uso interesante del polimorfismo) y los pasos básicos para empezar a aprovecharlo. Espero con esto mostrar lo simple y rápido que es hacer GUIs con esta combinación de herramientas.

lunes, 7 de abril de 2014

Un "feature" para ZinjaI por cortesía del servidor X

En el mundo GNU/Linux hay desde hace un buen tiempo un revuelo importante de noticias relacionadas a los servidores gráficos. El famoso servidor X que utilizamos actualmente (Xorg) está viejo, muy viejo, tiene cerca de 30 años. Todo parecía indicar que el relativamente reciente Wayland iba a ser el gran reemplazo hasta que Cannonical quiso hacer la suya y metió al más reciente Mir en la discusión. Sea cual sea el reemplazo (personalmente espero que triunfe Wayland, y creo que así será), el X tenía algunas características muy útiles que los nuevos no tendrán. Y está bien que no las tengan, porque no siguen la misma filosofía, porque están diseñados en el 2000 y no en los 80. Pero hay una muy discutida que voy a extrañar, porque la uso para programar con ZinjaI. Es la posibilidad de ejecutar un programa en una PC y verlo en el servidor gráfico de otra, el infame X remoto. Les cuento hoy de qué se trata y cómo me resulta útil, antes de que migremos a Wayland y tengamos que buscar otra opción.

viernes, 28 de marzo de 2014

Sobre el futuro a mediano plazo de ZinjaI

El fin de semana pasado publiqué una versión nueva de ZinjaI con muchas mejoras, aunque la mayoría no son fácilmente visibles. Hay pequeños detalles por aquí y por allá en la interfaz, hay mejoras en casos particulares para el autocompletado, hay algún que otro cambio en la configuración de proyecto para simplificar algunos nuevos complementos, etc. Aunque también hay cosas que se ven, como la nueva ventana de ayuda sobre C++ que permite explorar offline el contenido ofrecido por cppreference (con licencia CC, instalable como complemento); o el nuevo cuadro de configuración para la integración de proyectos con wxFormBuilder (de lo que hablaré en breve en otro post). Pero el tópico de hoy apunta a comentar qué grandes cambios (visibles o no) estoy pensando a futuro. Algunos para la próxima versión, otros tal vez tarden un poco más en llegar.

jueves, 13 de marzo de 2014

El autocompletado y yo (capítulo 2)

Ya comenté hace mucho cómo funcionaba el sistema de autocompletado en ZinjaI, y cuales eran sus limitaciones. Básicamente, por un lado tengo a cbrowser, una herramienta que analiza los fuentes y me dice qué cosas se definen. Su parseo es mucho más rápido que el de un compilador, ya que no usa toda la información disponible, pero aún así no es tan rápido como para aplicar en tiempo real. Por eso solo se aplica cada vez que se guarda un archivo fuente, completando con su información el árbol de símbolos. Luego, como el autocompletado es necesario mientras estamos editando un fuente, tiene que haber otro mecanismo en tiempo real para compensar la falta de actualización de esa información. Y además, mientras lo editamos, el código no es válido, está a mitad escribir, y en ese caso el análisis de cbrowser tampoco funcionaría. Entonces tengo un mecanismo alternativo que analiza un fuente abierto, mirando solo ese fuente (y solo cerca de donde estemos editando), y aplicando una heurística propia y poco fiable, pero muy rápida y tolerante a errores de sintaxis. Esencialmente se encarga de dos cosas: tratar de averiguar de qué tipo es una variable mirando si hay algo que pueda ser su definición (sino se buscará en el árbol de símbolos), y averiguar qué representa hasta el momento una expresión a mitad escribir.

Hace un tiempo que me decidí a reescribir este último mecanismo. Lo quise reescribir porque estaba fragmentado en diferentes lugares de ZinjaI y entonces había algunas funcionalidades repetidas, y otras difíciles de reutilizar. Mi idea era mejorar el diseño para agregar algunas mejoras muy útiles, y de paso tratar de que todo se analice con el mismo código para simplificar el mantenimiento y acotar los problemas. En este artículo entonces voy a describir los problemas a los que me enfrento al hacer esto, y qué hay de nuevo para la próxima versión de ZinjaI.

lunes, 10 de marzo de 2014

El programador es un pequeño Dios

Empieza una vez más el cursado en "mi" Universidad, y como docente de una de las comisiones de teoría de la materia "Fundamentos de Programación"  tengo la enorme responsabilidad de presentarles la programación por primera vez a muchos jóvenes ingresantes. Es una oportunidad única para que empiecen motivados y con el pie derecho, para que lo vean como algo atrapante y divertido, y no como una materia más. Y es en este contexto, donde cada año al preparar esos primeros 15 minutos de la primer clase, divago sobre la naturaleza de la programación, como lo voy a hacer en este post. Pero antes de seguir leyendo, estén advertidos de que será una ensalada de cosas muy subjetivas relacionadas de formas cuestionables.

Miles de artículos se han escrito debatiendo acerca de la naturaleza de la programación, ¿arte o ciencia? Si me preguntan a mi, es ambas cosas, pero primero digo arte, porque lo de ciencia lo doy por obvio, mientras que lo de arte es lo más discutido. De todas, formas, no es esta pregunta el eje de este post, sino que pretendo volcar en algunas lineas una visión general y motivadora de la parte que más disfruto de esta maravillosa actividad, la visión que me gustaría transmitir a mis alumnos y compañeros para alentarlos a disfrutar de los desafíos como yo lo hice cuando estaba aprendiendo, y como lo sigo haciendo en la mayoría de los casos.

viernes, 28 de febrero de 2014

Excusas para no documentar un código

En un proyecto de software tenemos dos tipos básicos de documentación. Por un lado está la documentación para el usuario final, para que aprenda a utilizarlo, como los manuales de ayuda o las referencias, mientras que por otro lado está la documentación sobre el desarrollo del mismo, como los diagramas de clases, casos de uso, o los comentarios en el código por ejemplo. Quiero hablar particularmente de los últimos, de los comentarios en el código (lo que se conoce como documentación interna) porque es algo que creo que a la mayoría no nos simpatiza mucho tener que hacer, pero que tampoco podemos delegar. El manual de usuario, por ejemplo, sí lo podría hacer por otra persona que no sea la que codificó el programa. Pero la documentación interna en general es responsabilidad directa del programador.

Como ya dije, es algo que consume tiempo y ganas, y por eso solemos inventar mil excusas para no hacerlo (o si es un proyecto individual, directamente no lo hacemos, sin tener que rendirle excusas a nadie). Pero a la larga, las consecuencias de una mala documentación terminan costando todavía más tiempo y paciencia (mucho más) de lo que habría costado hacerlo bien en su momento. Yo lo aprendí por las malas, mis códigos viejos son claras evidencias de ello, y por eso ahora vengo a refutar las excusas más comunes que nos ponemos para saltearnos ese trabajo.

jueves, 13 de febrero de 2014

Polimorfismo en psexport

Psexport es uno de los módulos de PSeInt, el que se encarga de traducir un algoritmo en pseudocódigo a lenguajes de programación reales como C, C++, Java, PHP, etc. En realidad hace la mitad del trabajo. Traducir implica primero entender qué es lo que está escrito en un lenguaje, para luego ver cómo escribirlo en el otro. La primer parte la hace el mismísimo intérprete, generando un archivo intermedio "premasticado" para que psexport lea más fácilmente y dedique sus mayores esfuerzos a ver cómo sería mejor escribirlo en ese otro lenguaje. Inicialemente, ese otro lenguaje era solo C++, pero recientemente se añadieron unos cuantos más. La orientación a objetos y particularmente el polimorfismo hicieron que pueda programar todas esas nuevas traducciones con muy poco esfuerzo. Así que en este post les voy a mostrar un ejemplo del tan valioso y no siempre bien ponderado polimorfismo.

viernes, 7 de febrero de 2014

Polimorfismo en C++

El uso del polimorfismo en C++ es uno de los temas que más complicaciones les trae a los estudiantes cuando están haciendo sus primeras armas en C++ y Programación Orientada a Objetos. Aclaro que estoy hablando de clases abstractas y métodos virtuales, porque algunos materiales cuentan la sobrecarga como un tipo de polimorfismo. Tal vez se deba a que para utilizarlo hay que tener claras las ideas de la POO y el diseño de clases por un lado (algo muy difícil si se tiene poca experiencia), y por otro lado los conceptos del manejo de memoria en C++, ya que involucra punteros y conversiones implícitas de tipo. Es decir, ni el diseño ni la sintaxis son triviales. Entonces es lógico que les resulte complejo. El problema es que culpa de esto, le esquivan todo lo posible, y terminan no utilizándolo.

Se puede hacer todo tipo de cosas en C++ sin utilizar polimorfismo, es posible evitarlo, o emularlo. Pero en muchísimos casos, hacerlo de esa manera implica más código, clases más complejas, implementaciones más rebuscadas, más dependencias entre objetos, o el uso de otros trucos tanto o más complicados que el mismo polimorfismo que estaban tratando de evitar. Voy a comentar en este artículo rápidamente de qué se trata, cuales son los mecanismos del compilador que hay por detrás, y qué usos le podemos dar, para que sirva de introducción a otros artículos donde comentaré casos particulares y de interés en PSeInt y en ZinjaI.

viernes, 31 de enero de 2014

Sobre la evolución de C++

Aproveché una parte de las vacaciones para tratar de ponerme al día con el "nuevo" estándar de C++: C++11. Digo "nuevo" porque aunque el estándar (el documento que describe el lenguaje) tiene ya 3 años, recién el año pasado los principales desarrolladores de compiladores publicaron versiones con soporte suficientemente estable y completo para las nuevas características y bibliotecas (gcc 4.8, clang 3.3, visual studio 2013, etc). No vengo a explicar las nuevas características, sino que les voy a contar a modo de recomendación de dónde me informé, y que otras cosas muy interesantes me encontré en el camino; para al final tratar de pensar cómo y cuando nos va a afectar esto.

El que me conozca o siga el blog sabe que el 90% (o más) de lo que programo, lo hago con C++. Se convirtió en mi lenguaje favorito por cuestiones más bien pragmáticas, y por oposición a alternativas (discutiblemente) más simples, modernas, o prolijas, pero en general menos eficientes. Estos motivos no hicieron más que afirmarse y crecer durante estas semanas, gracias a algunas lecturas adicionales que encontré en el camino.