Hace algún tiempo salió el tema sobre lo políticamente incorrecto que era aprender a costa del cliente para el que se trabaja. Es decir, que mientras te pagan por hacer una aplicación web, uno aprenda a usar struts.

Solía estar de acuerdo con esto...

School Bus Top

Pero ya no. O no sin matices, al menos...

Cuando alguien nos contrata (y, por si alguien llega despistado, hablamos de informáticos, mejor si tienen formación específica) no lo hace porque seamos robots intercambiables, capaces de trabajar sin pensar.

Nosotros aprendemos cada día. Si tras un mes trabajando no has aprendido nada, intenta aprender a automatizar tu trabajo... si es así de simple, no es necesario un humano para hacerlo. Y quizá hasta puedas vender el resultado.

¿Suena a utopía? Bueno, hay muchas cosa a nuestro alrededor creadas para eliminar la repetición de tareas tediosas... maven, hudson, capistrano, filtros antispam, 1password, los pagos por domiciliación bancaria, Ctrl-C / Ctrl-V, la imprenta... seguro que puedes ver alguno más.

Los trabajos que realmente importan, los trabajos por los que debemos ser contratados son aquellos que nos permiten aprender durante el trabajo. No tiene porque ser algo revolucionario...

El matiz (que habelos, hailos) es que el aprendizaje revolucionario no podemos conseguirlo sólo durante el trabajo con el cliente. Si no sabes django, primero juega un poco con él en casa y luego lánzate a algún proyecto. Una cosa es aprender y otra sacrificar un proyecto (y puede que tu futuro profesional).

Otro matiz importante... es que hablo desde la perspectiva de un autónomo y trato directamente con mi cliente... Si estás dentro de una empresa puede que tengas oportunidad de elegir o, más probablemente, que sea otro el que decide en qué empleas tu tiempo.

Finalmente... ¿porqué no aprender solo en casa? ¿o en coding dojos y code retreats como los que organiza agilismo.es? Así no pondremos en riesgo el proyecto...

Pues, en mi opinión, por múltiples motivos. Además de que podríamos ser reemplazados por autómatas, se me ocurren estos dos:

1. Seguro que dedicas más tiempo a trabajar (y aprender) durante la jornada laboral. No mucha gente se pasará otras 8 horas aprendiendo sin cobrar.

2. Los problemas de juguete no sirven para aprender de verdad. Son una buena iniciación y quizá una buena forma de pulir detalles. Pero sólo se aprende de verdad cuando estás bajo presión, cuando hay que reducir el alcance para llegar a la fecha, cuando unos cientos de usuarios hunden tu servidor... ahí es dónde un puede lucirse... y dónde demuestra si lo que cobra lo vale o no.

P.D: a mis clientes... espero que yo sí valga lo que cobro :-)

Fan del Plan Bolonia

Hace unos días que participo en una conversación en el grupo de ingenieros e ingenieros técnicos en informática de linked in.

La conversación empezó preguntándose si la titulación garantiza la calidad del trabajador (ambigüo, si...). El tema derivó en ideas locas (porque ninguno vamos a mover un dedo por ellas... eso cuesta mucho trabajo) para mejorar el sistema educativo/universitario.

En un punto, se escapó de mis dedos esto, mientras defendía la necesidad de especializar la formación de forma agresiva...

En cuanto a especialidades... algunas salen muy claras: hardware vs software. No es lo mismo el diseño de microprocesadores o robots que hacer aplicaciones web.

Otras más discutibles (quizá): Ingeniero de testing? Administrador de sistemas? Programador (que parece que es el único ingeniero informático del que nos acordamos)?
¿Una especialidad en gestión y metodologías? ¿Soft skills para elicitación de requisitos y negociación con clientes?

No es que haya que ser un hacha programando... es que hay que salir sabiendo hacer algo (y preparado para recuperarse de muchos golpes en el ego al encontrar gente mejor). Aunque estés preparado para mucho más.

No tienen porque ser titulaciones separadas. Pero habría que permitir a quien le interese trazar ese camino. Y el sistema actual solo hace un amago en esa línea con las asignaturas opcionales... no hay un recorrido real.

La respuesta desde dentro de la Universidad de La Rioja fue:

Abel, acabas de definir la filosofía del denostado Plan Bolonia.

(No tengo claro si eso es positivo o no :-) ).

Apenas tengo mucha información sobre el Plan Bolonia. En su momento leí algo, pero me pareció que todo el mundo discutía sobre planes/atribuciones/exclusividad/colegios... nunca leí mucho sobre cambios al sistema educativo, excepto que ciertas carreras estarán reguladas (y gente quejándose de que la Ingeniería Informática no lo estuviese y pidiendo atribuciones/exclusividad).

Pero divago...

¿Es vedad que el Plan Bolonia se parece a mi sueño humedo para el sistema educativo? Aunque sea sólo sobre el papel, que ya sabemos cómo se hacen las cosas luego...

JUnit y la mayoría de los frameworks de testing suelen ser bastante buenos generando mensajes explicativos cuando falla un assert. Esto me ha creado la mala costumbre de no proporcionar mis propios mensajes de error.

Love message

El problema aparece con los métodos del tipo assertNull / assertNotNull / assertTrue / asserFalse, dónde lo único que se ve en el mensaje de error es la (muy fea) traza:

java.lang.AssertionError: 
	at org.junit.Assert.fail(Assert.java:74)
	at org.junit.Assert.assertTrue(Assert.java:37)
	at org.junit.Assert.assertNotNull(Assert.java:356)
	at org.junit.Assert.assertNotNull(Assert.java:365)
	at un.paquete.UnaClaseTest.testLoQueSea(UnaClaseTest.java:232)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:616)
	at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
	...
	... blah blah blah

Dentro del IDE tiene un pase, porque estamos a un click del problema. Lo feo es cuando esto pasa en integración continua y necesitamos abrir el código simplemente para saber cuál es el problema y poder decidir lo importante que es resolverlo.

Así que... chicos y chicas, assertNotNull("El karma no debe ser nulo", user.getKarma())

Hasta aquí mi consejo de hoy.

Hoy he llegado a la segunda charla de Sir Ken Robinson en TED gracias a un post de mi ex-colega y jefe Justo Hidalgo (también es muy buena la primera charla, hace 4 años).

Aunque la charla trata sobre educación, Sir Ken Robinson enfoca el tema desde esta perspectiva:

I meet all kinds of people who don't enjoy what they do. [...] They endure it, rather than enjoy it, and wait for the weekend.
But I also meet people who love what they do and couldn't imagine doing anything else. [...] Because it isn't what they do, it's who they are. They say, « But this is me, you know. It would be foolish for me to abandon this, because it speaks to my most authentic self ».
And it's not true of enough people. In fact, on the contrary, I think it's certainly a minority of people.

El oir de forma tan clara algo que lleva tanto tiempo incrustado en mi cabeza es como un flash. No creo que pudiera decirlo mejor... y eso que ni siquiera era el tema central de su charla...

Lo que me aterra y no comprendo es... porqué alguien decidiría voluntariamente pasar la vida soportando su trabajo. ¿Porqué no buscar algo apasionante?

Yo tengo la suerte de ser un ingeniero informático. O un programador. O cualquiera de los otros títulos que nos ponemos en los CVs para impresionar. Y en querer serlo desde que abandoné la idea de ser maquinista de tren (cerca de los 4 años).

En otras palabras soy mi auténtico yo.

Egoistamente, intento rodearme de gente similar. Gente que hace lo que le apasiona. E, invariablemente, la gente apasionada por su trabajo (sea lo que sea) es mucho mejor profesional que los que simplemente lo toleran.

Y quizá me arriesgaría a decir que también destacan fuera del plano profesional. Disfrutar de la vida (toda ella, no sólo las 8 horas que no trabajamos ni dormimos) tiene que proporcionar, por necesidad, más felicidad. Menos motivos para enfadarse. Menos frustración. Menos miedos...

Resumiendo... si no estáis contentos con lo que hacéis... buscar otra cosa. Descubrid vuestro talento y aprovechad la vida. No esperéis a que revolucionen la educación (que es el verdadero mensaje de Sir Ken Robinson)... porque ya os pilla tarde: ¡ninguno volveremos a la escuela!

Aunque, si leéis este blog, casi seguro que ya estáis en contacto con vuestro auténtico yo.

Os dejo con la charla al completo. Está en inglés pero podéis seleccionar subtítulos en muchos idiomas (includo el castellano :-) )

Aunque ejecutar los tests de un proyecto Rails en Hudson es muy sencillo y no necesita nada especial, hacer que Hudson entienda lo que Rails (Test::Unit, en realidad) está haciendo es otra cosa.

Para poder ver un gráfico como el que tienen nuestros proyectos Java (JUnit, en realidad), hace falta un poco de grasa para suavizar la relación.

Para esto, existe el plugin de rails ci_reporter, que traduce los resultados de Test::Unit a algo que Hudson puede entender... el formato XML de junit.

Para una aplicación Rails de toda la vida habrá que hacer tres cosas:

  • Instalar el plugin
gem install ci_reporter

(Si no usas rvm entonces seguramente tengas que poner un sudo delante).

  • Añadir 3 líneas a nuestro Rakefile
require 'rubygems'
gem 'ci_reporter'
require 'ci/reporter/rake/test_unit'
  • Ejecutar la tarea ci:setup:testunit antes de las pruebas
rake ci:setup:testunit test

Estos comandos son por defecto, para pruebas con Test::Unit. Si usamos otro framework, cambian. La documentación original lo explica bien.

Por defecto, los informes de las pruebas se generan en test/reports/ dentro del proyecto. Sólo hay que indicarle a Hudson que los lea tocando la configuración del proyecto.

Y acordarse de cambiar el comando para que invoque a ci_reporter en cada ejecución:

Listo, ejecuta un par de builds para poder ver el gráfico... ¡y a otra cosa!

Cada vez estoy más metido en el mundo del desarrollo con ruby on rails y hasta empiezo a disfrutarlo (¡en contra de mi intuición inicial!). Y cualquier cosa con la que haga proyectos necesita estar bajo un sistema de integración continua... yo uso hudson.

Para los no iniciados, un sistema de integración continua (como hudson) no es más que una forma de ejecutar tareas sobre el código, normalmente sobre la versión más reciente en el sistema de control de versiones. Tareas típicas son compilar, pasar pruebas, empaquetar o desplegar la aplicación en un entorno de QA (o incluso producción).

Por otra parte, ruby on rails no necesita compilación, así que lo único que necesitamos es saber que no hemos roto nada... es decir, que las pruebas pasan.

Fácil, creamos un nuevo proyecto de estilo libre y rellenamos los campos habituales para el SCM (dónde está el código fuente) y los disparadores (cuando se ejecuta la build). Yo suelo elegir el polling frecuente del SCM, para que se ejecuten las builds después del commit.

Y la parte interesante:

Añadir un nuevo paso de ejecución de tipo linea de comandos con el mismo contenido que usamos en nuestra máquina. Por ejemplo:

Recuerda que el checkout del proyecto crea un directorio, de ahí que sea necesario el cd trunk ... habrá que ajustarlo si usas otro nombre.

Hasta aquí sólo hemos conseguido que hudson se queje cuando hacemos un commit de algo que rompe las pruebas. Es un comienzo, pero estaría bien tener algo más de información, alguna gráfica... Eso, en el próximo capítulo.

Por algún motivo, todos los desarrollos que empiezo con ruby necesitan utilizar imagemagick... Y aunque no es algo nuevo, pero es algo que necesito hacer una y otra vez (buscando en google antes), hoy lo voy a dejar por escrito.

Image magick

Mi plataforma: osx 10.6 (Snow Leopard). Aunque estoy usando rvm para gestionar mis rubies, esta instalación la voy a hacer sobre la versión del sistema (rvm system)... lo que implica usar sudo (si usas rvm con otra versión, omítelo)

Lo malo de ruby con imagemagick es que necesita compilar código nativo para hacer la interfaz entre ambos, lo que a su vez significa que se necesitan los ficheros de cabecera de imagemagick para que el compilador C se quede contento (que tiempos cuando java dominaba el mundo y podías hacer copy&paste incluso entre distintos operativos y plataformas...)

Para instalar imagemagick y sus cabeceras utilizo macports

sudo port install libxml2
sudo port install ImageMagick +no_x11

... tras la segunda línea es un buen momento para tomar un café.

Por último, instalamos la gema rmagick. También tarda lo suyo...

sudo gem install rmagick

Para hacer la prueba de que todo hay ido bien...

$ irb -rubygems -r RMagick
irb(main):001:0> puts Magick::Long_version
This is RMagick 1.15.3 ($Date: 2007/01/20 15:45:29 $) Copyright (C) 2007 by Timothy P. Hunter
Built with ImageMagick 6.3.2 02/23/07 Q8 http://www.imagemagick.org
Built for ruby 1.8.5 (2006-12-25 patchlevel 12) [powerpc-darwin8.0.0]
Web page: http://rmagick.rubyforge.org
Email: rmagick@rubyforge.org
=> nil

Hasta otra!

(Con agradecimientos a este otro blog en inglés que contiene la información crítica y a la guía de instalación de rmagick que descubrí demasiado tarde)

El API java.lang.management permite, desde java 1.5 (y estamos ya camino de la versión 7) explorar varios parámetros de la máquina virtual en la que se ejecuta un programa java.

Coffee and Milk

No es una api muy extensa... partiendo de la clase ManagementFactory podemos obtener las instancias capaces de darnos los datos que nos interesan.

En mi caso, necesitaba comprobar que al lanzar una herramienta, los parámetros pasados a la máquina virtual eran los correctos (varios valores para los típicos -Xmx y similares). Esto se consigue muy fácilmente con:

ManagementFactory.getRuntimeMXBean().getInputArguments();

Durante mis breves experimentaciones he llegado a dos conclusiones:

  1. El parámetro -server no es muy fiable. En Snow Leopard aparece como -Xserver, pero en ubuntu no aparece...
  2. La memoria máxima no coincide con el valor esperado de -Xmx (aunque está cerca). Esto es verdad para Runtime.getRuntime().maxMemory() y para su análogo en la ''management api'' ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax()

...y esto es lo que he descubierto hoy. ¿Qué APIs/librerías has descubierto tú que te han sacado de un apuro?

Este fin de semana iba en un avión de una de esas líneas de bajo coste que alguna gente tanto odia (a mi me parecen útiles, pero es otro tema...).

Barricade, Vichy France

El avión iba lleno hasta los topes y para los últimos en embarcar no quedaba espacio dónde poner el equipaje de mano... yo tuve suerte, pero fui el último (o de los últimos). Para los demás, la opción era guardar el equipaje de mano en la bodega y recogerlo en la cinta... como si lo hubiesen facturado.

Alguna gente que llegó después tenía un problema... debía conectar con otro vuelo al aterrizar y no tenía tiempo para pasar por la recogida de equipaje.

Lamentablemente, la reacción de alguno de los afectados no me sorprendió en absoluto:

Si no hay espacio no es mi problema y si el avión no despega, pues no despega.

¿Es eso negociación?

Unos minutos antes, otros pasajeros (conocidos entre si) habían intercambiando sus maletas para que el que tenía un enlace no tuviese problemas y el otro, con más tiempo, simplemente tenía que esperar por su maleta al aterrizar.

¿Cómo de difícil hubiese sido preguntar a algún desconocido si podría hacer el mismo favor?

Y ahora... si aplicamos lo mismo a las empresas... ¿qué tenemos?

Tengo la sensación de que nuestra cultura iguala "negociar bien" con "conseguir todo a cambio de nada"... algo falso y peligroso.

¿Tenéis experiencias similares o yo me rodeo de bichos raros? ¿Pasa lo mismo fuera de España?

Estoy de reenganche con mis proyectos tras venirme de vacaciones (la primera vez que descanso un mes entero, se hace duro). Además, me he actualizado la versión de OSX a Snow Leopard ...

Oh, sorpresa, las pruebas de uno de los proyectos fallan con un místico Invalid memory access for location.

Mi conclusión, después de buscar mucho en google, es que se trata de algún tipo de bug en la gestión de memoria que ocurre al combinar la nueva versión de Java en Snow Leopard con las clases compiladas por el compilador de JDT (yo uso Eclipse 3.5 todavía... quizá con el nuevo Eclipse 3.6 esto no pase...).

Yo lo he solucionado haciendo que -Xms y -Xmx coincidan y poniendo suficiente PermGenSpace (aunque eso es otra guerra), tanto para Eclipse como para el lanzador de Junit.

Lo "bueno" de todo esto es que desde línea de comandos todo funciona (ya que no se usa el compilador de JDT).

Otras solución que he leído (pero no probado) es ejecutar java en modo interpretado (bastante más lento).

Cerrar