Articulos recientes

Código que no se usa, se borra

Every Line Is A Child Of Mine

Comic via Geek and Poke.

Código que no se usa, se borra, para algo quedo en el SCM ya.

Lectura recomendada: Source Control How To.

The fine manual pages

If you want them to RTFM...

Via Amen.

Lo que me recuerda, tengo que documentar en lo que estoy laburando…

Thomas Edison’s fire

Cuando Thomas Edison tenia 67 años un incendio destruyo su fabrica. A la mañana siguiente dijo:

Thomas A. Edison

Hubo valor en este desastre. Todos nuestros errores han sido quemados. Gracias a dios que podemos empezar desde cero.

¿A quien no le gustaría tener esa oportunidad con su código cada tanto? Tomado de Thomas Edison’s fire en The Endeavour.

Como configurar Buildbot

En el post anterior sobre django-yabe escribí sobre que es la Continuos Integration y como, de las distintas herramientas que existen, mi preferida para el caso era Buildbot.

Buildbot esta programado en Python y fue presentado en la PyCon 2003 de Estados Unidos. Desde entonces cada commit que se hace al SVN de Python dispara un proceso que compila el core del lenguaje y corre los tests cases de la stdlib en todos los sistemas operativos soportados. En caso de error notifica a quien halla hecho el commit y aparte lo publica en una pagina web.

Para poder realizar la compilación en varios sistemas operativos Buildbot se separa entre un servicio “Maestro” y muchas instancias “Esclavos”.

La instancia “Maestro” tiene varias responsabilidades:

  • Saber cuando hay que iniciar el proceso de build.
  • Avisarle a los nodos “Esclavos” que hay que realizar el build.
  • Darle a estos las instrucciones de como realizar el build.
  • Notificar del resultado del mismo.

En cambio las instancias “Esclavo” son mucho mas bobas: No llevan configuración sobre como compilar el código ni cuando deben hacerlo: Reciben notificaciones del maestro con esta información.

Este es un gráfico (tomado de la documentación oficial) que ilustra esta arquitectura:

Arquitectura de Buildbot

Instalación

La instalación es muy fácil, hay tres opciones:

Usando setuptools:

easy_install buildbot

Utilizando el package manager de nuestra distribución (Recomendada):

# Gentoo
emerge buildbot
# Debian y Ubuntu
apt-get install buildbot
# Arch
yaourt -S buildbot

Siguiendo la guiá de instalación en la documentación oficial.

En cualquiera de los tres casos es necesario tener instalado Twisted (el framework para aplicaciones de red asincronicas en Python) y Zope-Interface.

Al finalizar la instalación es necesario crear un directorio donde vallamos a crear las instancias maestro y esclavo del Buildbot:

bitfactory ~ # mkdir /var/lib/buildbot

Configuración del Maestro:

En el diagrama que mostraba la arquitectura vimos que el Maestro prácticamente hace todo, de hecho los esclavos no llevan configuración (solamente se les dice a que maestro deben conectarse).

Por esto es que primer configuramos la instancia del maestro: La instalación de buildbot nos dio un nuevo comando “buildbot” con una serie de opciones, la que nos interesa ahora es “create-master”:

bitfactory ~ # buildbot create-master /var/lib/buildbot/django-yabe-master
mkdir /var/lib/buildbot/django-yabe-master
chdir /var/lib/buildbot/django-yabe-master
creating master.cfg.sample
populating public_html/
creating Makefile.sample
buildmaster configured in /var/lib/buildbot/django-yabe-master

Si miramos /var/lib/buildbot/django-yabe-master veríamos algo así:

bitfactory ~ # ls -l /var/lib/buildbot/django-yabe-master
total 20
-rw-r--r-- 1 root root 434 Nov 20 16:21 Makefile.sample
-rw-r--r-- 1 root root 736 Nov 20 16:21 buildbot.tac
-rw------- 1 root root 7471 Nov 20 16:21 master.cfg.sample
drwxr-xr-x 2 root root 4096 Nov 20 16:21 public_html

El archivo Makefile es legacy de cuando Buildbot se iniciaba y paraba utilizando make. El archivo buildbot.tac es utilizado por Twisted para iniciar el servicio (no hace falta que lo editemos), y master.cfg.example es un archivo de configuración de ejemplo, yo no lo voy a utilizar porque es muy completo, y prefiero algo mas minimalista que se ajuste a lo que necesito, pero es bueno como referencia.

Así es que creamos un nuevo archivo master.cfg:

bitfactory ~ # vim /var/lib/buildbot/django-yabe-master/master.cfg

(Si no les gusta vim usen su editor de texto preferido para editarlo)

Y empezamos. La primer linea es medio confusa y merece aclaración:

c = BuildmasterConfig = {}

Ahí estamos creando un diccionario de Python accesible a través de dos nombres “BuildmasterConfig” y “c”. Cuando Buildbot lea la configuración va a buscar “BuildmasterConfig”, pero nosotros podemos ahorrar letras guardando los valores que queramos en “c”.

Siguiendo con la configuración:

from buildbot.buildslave import BuildSlave
c["slaves"] = [BuildSlave("Esclavo01", "sarasa")]
c["slavePortnum"] = 4484

Ahí definimos una lista con los esclavos y definimos el puerto donde el maestro va a esperar por conexiones de estos.

Lo que sigue es lograr que Buildbot se entere cuando hay una actualización en el repositorio:

from buildbot.changes.pb import PBChangeSource
c["change_source"] = PBChangeSource()

PBChangeSource utiliza el puerto que se declaro para escuchar respuestas de los esclavos para escuchar por “avisos” de que se cambio el código fuente. Estos avisos se pueden enviar con el comando buildbot sendchange, pero también se pueden configurar hooks en Mercurial o Subversion que avisen al Buildbot de cambios en el repositorio.

Con esa configuración Buildbot ya sabe cuando se cambio el código fuente, ahora tenemos que decirle cuando queremos que lo compile:

from buildbot.scheduler import Scheduler

c["schedulers"] = []
c["schedulers"].append(
Scheduler(
name="EveryCommit",
branch=None,
treeStableTimer=5,
builderNames=["Builder01"]
)
)

Un scheduler define cuando debe hacerse la compilación y quienes deben hacerla. En este caso en particular le estamos diciendo que el Scheduler llamado “EveryCommit” va a ver los cambios que se le hagan al trunk (branch=None), y cuando halla un cambio en el repositorio y no halla habido cambios en los últimos 5 segundos va a hacer que el builder “Builder01” haga un build.

Ya tenemos definidos quienes van a compilar (el esclavo que definimos), y cuando van a hacerlo (cuando le avisemos al maestro), ahora tenemos que definir que es lo que van a hacer.

from buildbot.process import factory
from buildbot.steps.source import Mercurial
from buildbot.steps.shell import ShellCommand

f1 = factory.BuildFactory()
f1.addStep(Mercurial, baseURL="/var/lib/hg/django-yabe/", defaultBranch="", mode="clobber")
f1.addStep(ShellCommand(command=["./manage.py", "test"]))

Ahí definimos un Factory: una serie de instrucciones sobre como compilar el código.

En el caso de un proyecto en Django es muy simple: Se baja el código y corre “./manage.py test”.

Para bajarse el código le decimos que tipo de repositorio es y los parámetros que necesita para hacer el checkout, hay una lista completa con los SCM y sus parámetros en la documentación de buildbot.

Sobre este primer paso hay un parámetro que merece una mención especial: mode=”clobber”

Mode no es un parámetro que utiliza el SCM, si no una instrucción que le damos a Buildbot para que reutilice o no los viejos checkouts. En este caso le estamos diciendo “clobber” que para Buildbot significa “cada ves que recibo la instrucción de hacer un build borro mi directorio de trabajo y hago un checkout limpio”.

El segundo paso se explica solo: Ejecuta el comando “./manage.py” con el parámetro “test”, si lleva mas de un parámetro seguimos agregando elementos a la lista command.

Cada Factory va dentro de un Builder:

b1 = {
"name": "Builder01",
"slavename": "Esclavo01",
"builddir": "django-yabe",
"factory": f1
}

c["builders"] = [b1]

Los Builders asocian Factory con esclavos. Esto es porque el Factory necesario para compilar nuestro código en Windows puede ser distinto que en Linux, pero por ahí hay algunos Builds que se tienen que hacer siempre igual en todas las plataformas. Eh ahí la flexibilidad que nos da la herramienta.

Lo único que nos falta es “como avisar” si algo sale mal:

c["status"] = []

from buildbot.status.html import WebStatus

c["status"].append(WebStatus(http_port=8101))

Listo, con eso le dijimos que levante un webserver en el puerto 8101 donde va a estar la información sobre los distintos builds.

Finalmente necesitamos algo de información sobre el proyecto:

c["projectName"] = "Django-yabe"
c["projectURL"] = "http://bitbucket.org/cuerty/django-yabe/"
c["buildbotURL"] = "http://cuerty.com:8101/"

Con todo esto tenemos configurado el buildmaster. Con el siguiente comando levantamos el mismo para probarlo:

bitfactory ~ # buildbot start /var/lib/buildbot/django-yabe-master/
/usr/lib64/python2.6/site-packages/twisted/internet/_sslverify.py:4: DeprecationWarning: the md5 module is deprecated; use hashlib instead
import itertools, md5
Following twistd.log until startup finished..
/usr/lib64/python2.6/site-packages/buildbot/scripts/logwatcher.py:48: PotentialZombieWarning: spawnProcess called, but the SIGCHLD handler is not installed. This probably means you have not yet called reactor.run, or called reactor.run(installSignalHandler=0). You will probably never see this process finish, and it may become a zombie process.
env=os.environ,
/usr/lib64/python2.6/site-packages/twisted/persisted/sob.py:12: DeprecationWarning: the md5 module is deprecated; use hashlib instead
import os, md5, sys
/usr/lib64/python2.6/site-packages/twisted/python/filepath.py:12: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
import sha
/usr/lib64/python2.6/site-packages/twisted/mail/smtp.py:32: DeprecationWarning: the MimeWriter module is deprecated; use the email package instead
import MimeWriter, tempfile, rfc822
2009-11-20 17:16:58-0800 [-] Log opened.
2009-11-20 17:16:58-0800 [-] twistd 8.1.0 (/usr/bin/python2.6 2.6.2) starting up
2009-11-20 17:16:58-0800 [-] reactor class:
2009-11-20 17:16:58-0800 [-] Creating BuildMaster -- buildbot.version: 0.7.11p3
2009-11-20 17:16:58-0800 [-] loading configuration from /var/lib/buildbot/django-yabe-master/master.cfg
2009-11-20 17:16:58-0800 [-] adding new builder Builder01 for category None
2009-11-20 17:16:58-0800 [-] trying to load status pickle from /var/lib/buildbot/django-yabe-master/django-yabe/builder
2009-11-20 17:16:58-0800 [-] no saved status pickle, creating a new one
2009-11-20 17:16:58-0800 [-] added builder Builder01 in category None
2009-11-20 17:16:58-0800 [-] adding IStatusReceiver
2009-11-20 17:16:58-0800 [-] twisted.web.server.Site starting on 8101
2009-11-20 17:16:58-0800 [-] Starting factory
2009-11-20 17:16:58-0800 [-] WebStatus using (/var/lib/buildbot/django-yabe-master/public_html)
2009-11-20 17:16:58-0800 [-] adding 1 new schedulers, removed 0
2009-11-20 17:16:58-0800 [-] notifying downstream schedulers of changes
2009-11-20 17:16:58-0800 [-] adding 1 new changesources, removing 0
2009-11-20 17:16:58-0800 [-] twisted.spread.pb.PBServerFactory starting on 4484
2009-11-20 17:16:58-0800 [-] Starting factory
2009-11-20 17:16:58-0800 [-] BuildMaster listening on port tcp:4484
2009-11-20 17:16:58-0800 [-] configuration update started
2009-11-20 17:16:58-0800 [-] configuration update complete
The buildmaster appears to have (re)started correctly.

¡Errores! No hay que preocuparnos. La mayoría de lo que vemos es porque parte del código de Twisted imprime DeprecationWarning dado que no se actualizo para Python 2.6. Si vamos a http://127.0.0.1:8101 (o la dirección de donde este el buildbot) vemos una pagina que dice “Welcome to the Buildbot!” y nos da distintas opciones, una es el waterfall es quizá la mas interesante, donde vamos a poder ver si falla algo, o si todo esta perfecto.

Esto fue la configuración del maestro, ahora hagamos un esclavo que se conecte a este.

Configuración del Esclavo:

bitfactory ~ # buildbot create-slave /var/lib/buildbot/django-yabe-slave 127.0.0.1:4484 Esclavo01 sarasa
mkdir /var/lib/buildbot/django-yabe-slave
chdir /var/lib/buildbot/django-yabe-slave
creating Makefile.sample
mkdir /var/lib/buildbot/django-yabe-slave/info
Creating info/admin, you need to edit it appropriately
Creating info/host, you need to edit it appropriately
Please edit the files in /var/lib/buildbot/django-yabe-slave/info appropriately.
buildslave configured in /var/lib/buildbot/django-yabe-slave

Listo, tenemos el esclavo configurado. Los parámetros que le pasamos son para que sepa donde conectarse:

  • 127.0.0.1 es la IP del Buildmaster
  • 4484 es el puerto que configuramos en el Buildmaster para escuchar conexiones de los esclavos.
  • El usuario (Esclavo01) y password (sarasa) son los parámetros que le dimos al BuildSlave en el master.cfg.

Ahora puedo arrancar el buildslave:

bitfactory ~ # buildbot start /var/lib/buildbot/django-yabe-slave
/usr/lib64/python2.6/site-packages/twisted/internet/_sslverify.py:4: DeprecationWarning: the md5 module is deprecated; use hashlib instead
import itertools, md5
Following twistd.log until startup finished..
/usr/lib64/python2.6/site-packages/buildbot/scripts/logwatcher.py:48: PotentialZombieWarning: spawnProcess called, but the SIGCHLD handler is not installed. This probably means you have not yet called reactor.run, or called reactor.run(installSignalHandler=0). You will probably never see this process finish, and it may become a zombie process.
env=os.environ,
ERR: 'tail: cannot open `twistd.log' for reading: No such file or directory
'
/usr/lib64/python2.6/site-packages/twisted/persisted/sob.py:12: DeprecationWarning: the md5 module is deprecated; use hashlib instead
import os, md5, sys
/usr/lib64/python2.6/site-packages/twisted/python/filepath.py:12: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
import sha

The buildmaster took more than 10 seconds to start, so we were unable to
confirm that it started correctly. Please 'tail twistd.log' and look for a
line that says 'configuration update complete' to verify correct startup.

¡Mas errores! En principio son parecidos a los anteriores, pero al final no dice que “inicio el servicio”, si no que no sabe si inicio, y que deberíamos hacer un tail del log para ver si arranco bien, así que hacemos eso:

bitfactory ~ # tail /var/lib/buildbot/django-yabe-slave/twistd.log
2009-11-20 17:40:38-0800 [-] Log opened.
2009-11-20 17:40:38-0800 [-] twistd 8.1.0 (/usr/bin/python2.6 2.6.2) starting up
2009-11-20 17:40:38-0800 [-] reactor class:
2009-11-20 17:40:38-0800 [-] Starting factory
2009-11-20 17:40:38-0800 [Broker,client] message from master: attached
2009-11-20 17:40:38-0800 [Broker,client] SlaveBuilder.remote_print(Builder01): message from master: attached
2009-11-20 17:40:38-0800 [Broker,client] sending application-level keepalives every 600 seconds

Lo que nos importa aca es el mensaje “message from master: attached”, eso quiere decir que funciono. Si volvemos a ver el waterfall del buildmaster vamos a ver que el buildslave se conecto:

connect
Esclavo01

¡Excelente! Tenemos un buildbot configurado, ¿Ahora que? Lo integramos con Mercurial.

Configurando Mercurial

Yo tengo en /var/lib/hg/django-yabe un clone del repositorio del proyecto, voy a configurar para que cualquier commit a ese repositorio dispare un build en el buildbot.

bitfactory ~ # cd /var/lib/hg/django-yabe
bitfactory django-yabe # vim .hg/hgrc

(Devuelta, no usen vim si no quieren, elijan la herramienta que prefieran)

Agrego las siguientes lineas:

[hooks]
changegroup.buildbot = python:buildbot.changes.hgbuildbot.hook

[hgbuildbot]
master = 127.0.0.1:4484

Las primeras dos un hook que se activa ante un push o un commit a este repositorio. Las ultimas dos son la configuración para ese hook, ahí tenemos configurada la IP y el puerto del buildmaster.

Con eso basta para hacer que Mercurial se comunique con el buildbot.

El clone del repositorio que tengo en /var/lib/hg/django-yabe esta ahí para que lo acceda remotamente (utilizando el servidor web), solamente para simular una prueba voy a hacer un clone local del repositorio y probarlo:

bitfactory ~ # hg clone /var/lib/hg/django-yabe django_yabe

Pongo mi proyecto dentro del directorio django_yabe y “programo” hasta que “./manage.py test” corra sin problemas:

bitfactory django_yabe # ./manage.py test
Creating test database...

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK
Destroying test database...

Entonces agrego los archivos al repositorio:

bitfactory django_yabe # hg add __init__.py manage.py settings.py urls.py

Commiteo a mi repositorio local:

bitfactory django_yabe # hg commit

Y finalmente hago un push al repositorio en /var/lib/hg/django-yabe:

bitfactory django_yabe # hg push
pushing to /var/lib/hg/django-yabe
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 4 changes to 4 files
/usr/lib64/python2.6/site-packages/twisted/spread/pb.py:64: DeprecationWarning: the md5 module is deprecated; use hashlib instead
import md5
rev fe9688cab329fb43eb6169a541c663dac8c134b5 sent
change sent successfully

Las lineas interesantes son las siguientes:

rev fe9688cab329fb43eb6169a541c663dac8c134b5 sent
change sent successfully

Eso quiere decir que Mercurial le aviso al buildbot sobre el cambio, si voy a ver el Waterfall de nuevo:

django-yabe
last build build
successful

Se puede editar el css del buildmaster para hacer un poco mas amigable la vista a través del Waterfall, el mismo esta en /var/lib/buildbot/django-yabe-master/public_html/buildbot.css (En mi caso, reemplacen el path en el suyo).

Eso es todo, ya hay un build por cada push que hagamos al repositorio de Mercurial. Despues un detalle extra que se puede agregar al master.cfg es que aparte de notificar en el waterfall nos envie un reporte de los builds que fallan por email:

c["status"].append(
MailNotifier(
fromaddr="buildbot@cuerty.com",
extraRecipients=[“cuerty@gmail.com”],
sendToInterestedUsers=False,
mode="failing"
)
)

mode=”failing” significa que solamente me envie un email cuando el build falla.

Esto fue todo por ahora, espero que en lo próximo que empiece a trabajar ya sea el código del blog.

Quotes del dia

Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.

Martin Golding

Programming is like sex: one mistake and you’re providing support for a lifetime.

Michael Sinz

The trouble with programmers is that you can never tell what a programmer is doing until it’s too late.

Seymour Cray

Good code is its own best documentation.

Steve McConnell

Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other, with no structural integrity, but just done by brute force and thousands of slaves.

Alan Kay

Sacadas de WTF Code, una linda distracción mas para suscribirme por RSS.

Buildbot: ¿Que?

Este es el segundo post sobre django-yabe, mi propio blog engine.

Primero un poco de background, a principio de año lei el libro “The productive programmer”.

The Productive Programmer

La verdad no es un gran libro, me deje llevar por un par de reviews y el glosario parecía interesante, pero resulto ser una colección de anécdotas (algunas muy buenas) y alguna que otra analogía que me ayudaron a entender mejor algunos conceptos, pero el resumen del libro se puede hacer en una palabra: automatizar.

Automatizar es genial: cualquier trabajo repetitivo es propenso a errores cuando lo realiza una persona, en cambio cuando lo hace una computadora no. Una computadora no se “olvida de un parámetro” o “se saltea un paso”, la computadora hace lo que le digamos y listo (Si sabemos decírselo es otro tema). Y dentro de la creación de software existen muchas tareas que se pueden hacer de forma automática, una de ellas es la integración continua (del ingles Continuous Integration):

Integración continua es una practica del desarrollo de software donde los miembros de un equipo integran su trabajo frecuentemente, normalmente cada persona integra su trabajo al menos una ve por día – dando múltiples integraciones por día. Cada una de estas integraciones es verificada por una construcción automática del software (incluyendo los tests) para detectar errores de integración tan rápido como sea posible. Muchos equipos encontraron que este acercamiento llevo a reducir significativamente los problemas de integración y permitió al equipo a desarrollar software de una forma mas rápida.

Martin Fowler, Continuous Integration

El primer paso para la integración continua se logra teniendo el código fuente de la aplicación en algún sistema de control de versiones (SCM por sus siglas en ingles). Particularmente a mi me gusta Mercurial por ser distribuido y simple, pero existen otras opciones como GIT y Subversion. El segundo paso es tener una construcción automática (automated build).

¿Que es un “automated build”? Del mismo texto de Fowler:

Hacer que el código fuente se convierta en un sistema funcionando puede ser un proceso complicado que involucre compilar, mover archivos, cargar esquemas en las bases de datos y mas. Pero, como la mayoría de las tareas en el desarrollo de software, puede ser automatizada y, como consecuencia de esto, debe ser automatizada. Pedirle a personas que escriban comandos o hagan clicks en ventanas de dialogo es una perdida de tiempo y un campo fértil para errores.

Así que entendemos a un automated build como tomar el código fuente y llevarlo a un sistema andando, en el que corremos las pruebas de forma automática. ¡Eso es perfectamente scripteable! Puede hacerse un hook para el SCM que elijamos que cuando recibe un commit se encargue de correr un script que compile el código (en este caso en particular estoy usando Python para el proyecto, así que no se compila, ¡pero puede correr los tests!), es tan fácil que me sorprende que nadie lo halla hecho ya… Hudson, CruiceControl o Bitten (de los creadores de Trac) son algunos de los que ya lo hicieron, y hay muchos mas en la pagina de Wikipedia al respecto. De hecho ayer anunciaron en Mozilla que van a empezar a utilizar Hudson para el desarrollo de la pagina de Addons de Firefox y Thunderbird.

Mi gusto particular en herramientas de CI es BuildBot. La primer razón por la que me gusta es porque esta hecho en Python, y se puede extender y configurar utilizando este lenguaje. Eso es una ventaja grande porque en el espíritu de ser DRY puedo hacer que configuraciones como “a quienes avisarles por email cuando falla un build” puedo, en lugar de escribirlas en la configuración, hacer que las lea dinamicamente de la base de datos de Redmine o Trac para el proyecto en cuestión. La segunda es que es muy completo, tiene distintas formas de notificarte, trabaja con muchos SCM (Subversion, Mercurial, GIT, ¡hasta CVS!) y tiene una documentación que es muy buena como referencia, aunque lamentablemente es pésima como introducción.

Así que el plan para el próximo post es configurar que cuando subo código al repositorio de Mercurial para django-yabe, BuildBot haga un build (Django tiene un framework de unittesting muy completo) y me avise por email si fallo.

Quote

Good programs do not contain spelling errors or have grammatical mistakes. I think this is probably a result of fractal attention to detail; in great programs things are correct at all levels, down to the periods at the ends of sentences in comments.

Dad hacker en  30 years of C

Me viene justo porque estoy leyendo  The Elements of Style.

YABE (Yet another blog engine) #1

Este es mi primer post sobre django-yabe, un proyecto que acabo de empezar.

¿Que es yabe? Yet Another Blog Engine. Es simplemente otro blog programado en Django.

Sinceramente no creo que haga falta otro blog engine, el problema es que es divertido programar uno, aparte de fácil, y que me  sirve como escusa para practicar algunas cosas en las que estoy medio oxidado, o que directamente no se (CSS y Javascript).

Los objetivos del proyecto son:

  • Que soporte la API de Blogger o Metaweblog (Para poder actualizarlo usando BloGTK).
  • Que soporte unicode “de punta a punta”.
  • Tener los posts y los comentarios en markdown.
  • Mantener las URLs de mis posts actuales después de migrar.

Pero si hiciera solamente eso seria aburrido:

  • El código va a estar disponible en bitbucket, así que voy a utilizar mercurial para el versionado.
  • Voy a aplicar TDD a todo lo que se pueda.
  • Desde un principio voy a tener un buildbot (y mostrar como lo configuro).
  • El código va a ser adaptativo y modular.

Si bien se que estoy reinventando la rueda, el ecosistema de Django es muy completo. Espero poder reutilizar muchas de las apps que ya existen, así como el mismo admin de Django.

La próxima entrega es sobre la configuración del repositorio y el buildbot.

PyCon Argentina 2009

Copiado textualmente de ¡Vamos todos a PyCon Argentina! (del blog de Facundo Batista)

Está abierta la inscripción para participar de PyCon Argentina 2009, la primera conferencia en castellano sobre el lenguaje de programación Python, a realizarse los días 4 y 5 de septiembre en la sede de la Universidad de Belgrano, Zabala 1837, en la Ciudad de Buenos Aires.

En esta primera edición contaremos con la participación de Jacob Kaplan-Moss (creador de Django) y Collin Winter (core developer de Python) como invitados especiales del evento, y con más de 30 charlas sobre Python y temas relacionados, desde tutoriales para principiantes hasta charlas de nivel avanzado. Miren el cronograma de charlas, ¡está buenísimo!

La entrada es libre y gratuita. Para evitar contratiempos, confirmar su asistencia y recibir credencial y demás materiales de la conferencia, se recomienda realizar inscripción previa en el sitio web.

Va a estar genial.

Yo voy a ir, hay varias charlas que me interesan, seguramente me vean en la audiencia de:

  • Python como lenguaje de hacking.
  • Extendiendo PostgreSQL con Python.
  • Hacking Django, mismo framework, distintos paradigmas.
  • Escribi menos codigo, pensa como un (buen) matematico.
  • Twisted para seres humanos.

Y los plenarios de Jacob Kaplan-Moss y Collin Winter.

RE: Writing good code requires you to perform experiments

Acabo de leer el articulo Writing good code requires you to perform experiments. El titulo me llamo bastante la atencion, siempre “experimento” con pequeños snippets de código cuando estoy programando, de hecho tengo un shortcut (”Control Mod1 P :ExecCommand aterm -tint green -e python” en el .fluxbox/keys) para iniciar una terminal de Python ni bien tengo una pequeña duda o quiero “experimentar”. Pero para mi asombro, detrás de un titulo prometedor encontré un par de malos consejos.

Primero los dos puntos que rescato del articulo como ciertos (al menos en mi experiencia):

Es poco probable, casi imposible, que un poco de código recién escrito funcione como esperamos: Esto es especialmente cierto con los ejemplos que da de consultas a la base de datos y expresiones regulares. Siempre una tarea, por mas insignificante o banal que parezca puede contener errores.

Probar una funcionalidad o un poco de código dentro de una aplicación es ineficiente: Existen tiempos muertos entre que arranca el programa y el flujo del mismo llega hasta donde esta nuestro nuevo segmento de código. Hay que agregar que esta tarea es iterativa: tenemos que repetir el proceso hasta tener el resultado que queremos (o todos los resultados que queramos si son varias opciones). Y a esto tenemos que sumarle el tiempo de compilación (Si el lenguaje que utilizamos lo requiere).

Habiendo leído esto mi conclusión es ese código debe estar en un test case del proyecto. Pero esta es la respuesta del autor a esta idea:

Some of you may now be thinking that the obvious solution is to write a proper unit test and run that unit test after every modification, until the code passes the test. I agree that goes a long way, but usually the test is part of a larger number of classes and running all those tests takes times, especially if it bootstraps an entire Spring-Hibernate application or something of the like.

Y ahí mi horror, respondo por partes:

but usually the test is part of a larger number of classes

Una funcionalidad básica de la mayoría de las librerías para correr test cases es elegir correr un solo test de la test suite. Para mi eso es muy importante justamente por este caso que esta nombrando, y siempre me fijo (cuando elijo una librería al menos) que cuenta con esta funcionalidad, se me vienen a la mente la librería de unittest de Python y CppUnit.

especially if it bootstraps an entire Spring-Hibernate application or something of the like

Voy a evitar el chiste fácil de decir que mi segundo horror es que usan Java y referirme a lo que importa: ¿Por que debería hacer falta iniciar toda una aplicación para probar un pequeño pedazo de esta? Eso me suena a mucho coupling:

Si tenes un código lo suficientemente no trivial como para que lo hallas tenido que probar antes, merece al menos su propia función con su propio test case. Es una simple premisa de manejar la complejidad del código que estas desarrollando. Un nombre de la función va a describir mejor lo que pretendes hacer que tener que parsear con la mente la expresión regular que estas escribiendo. Y si tiene su propia función: ¿Para que vas a levantar todo el programa para probar solamente esa función? El test case debería limitarse a probar esa, y solamente esa, función, a lo sumo mockear (del ingles mock, “imitar”) sus dependencias.

En conclusión: Experimentar es bueno, sirve para sacarse dudas de como funciona una librería, que hace con cada parámetro, etc. Pero una ves que empezamos a escribir un código que es probable que llegue a producción, tiene que ser probado por su correspondiente test case y ser versionado en el SCM que utilicemos.