A veces me vienen chispas de inspiración no meditadas. Igual que vienen, se van... pero esta la voy a escribir.

De repente he pensado en Scrum, Kanban y sus hijos bastardos (o híbridos) y me ha dado la sensación de que no tienen nada que ver con la gestión de los proyectos (requisitos, plazos, entregas, niveles de calidad, predictibilidad...).

Las reglas, o al menos las reglas principales tratan sobre la gestión de las personas. Cómo dejarlas trabajar. Cómo hacerlas reflexionar...

Pero en cuanto a metodología de gestión de proyectos... bueno, no es muy diferente de "a salto de mata". Cada cual hace lo que puede y luego (con suerte) reflexiona sobre ello.

El resultado es conocido... cada cual dice hacer scrum (o lean, o lo que sea) a su manera. Pero... ¿cuál es la diferencia entre usar una metodología (cualquiera) "a mi manera" e improvisar?

NOTA: Actualizado para usar la nueva versión del API de AMQP (evitando usar la clase @MQ@). Gracias a @michaelklishin por el feedback

Tengo el «capricho» de crear una estructura escalable para procesar tweets.

Básicamente hay dos cajas:

  • el cliente de twitter: se conecta a la streaming API y su trabajo es leer tweets tan rápido como pueda.
  • el procesador de tweets: hace la lógica pesada, quizá ayudado por una base de datos.

Para que el cliente de tweets pueda leer rápido, tengo que desacoplar los dos sistemas. Pero me gustaría que el procesador de tweets recibiese trabajo tan rápido como sea posible (en cuanto haya un tweet, nada de tareas periódicas). Vamos, lo que viene siendo un pub/sub de toda la vida.

Y aquí es dónde RabbitMQ (o, más concretamente, el protocolo AMQP) entra en juego, ya que es capaz de pasar los mensajes del publicador al consumidor al momento y el soporte para clientes Ruby es, según todas las referencias que he visto, eggscelente.

A mancharse las manos...

El servidor

Instalamos RabbitMQ usando port

sudo port install rabbitmq-server

Dejamos que se cocine un rato y cuando nos devuelva el control:

sudo rabbitmq-server

Activating RabbitMQ plugins ...
0 plugins activated:


+---+   +---+
|   |   |   |
|   |   |   |
|   |   |   |
|   +---+   +-------+
|                   |
| RabbitMQ  +---+   |
|           |   |   |
|   v2.5.1  +---+   |
|                   |
+-------------------+
AMQP 0-9-1 / 0-9 / 0-8
...
broker running

¡Sí! Great Success!! :-)

El consumidor

Vamos a dejarlo muy muy simple.

Creamos una gema:

bundle gem countwer

Añadimos la dependencia en AMQP a countwer.gemspec para poder comunicarnos con RabbitMQ

s.add_runtime_dependency('amqp', ">= 0.7.1")

Y creamos nuestro cliente en lib/countwer.rb. Dejémoslo simple...

require "countwer/version"
require "amqp"

AMQP.start(:host => 'localhost') do |connection|
  AMQP::Channel.new(connection).queue('tweets').subscribe do |h,m|
    puts "tweet: #{m}"
  end
end

El código está conectando con el servidor en localhost y nos suscribimos a la cola tweets. Cada vez que se envíe un mensaje a la cola se ejecutará el bloque e imprimiremos el mensaje.

Antes de seguir, no olvidar el bundle install

El productor

El productor es nuestro lector de tweets. Es una gema creada con bundle gem que depende de twitter-stream para leer los tweets.

Ojo!: No me meto en los detalles de twitter-stream, pero el ejemplo es más que suficiente.

La gema se prepara igual que el cliente, pero con este código:

EventMachine::run {
  connection = AMQP.connect(:host => "localhost")
  queue = AMQP::Channel.new(connection).queue("tweets")
  ...
  stream.each_item do |item|
    queue.publish(item)
  end
  ...
}

El código es distinto porque twitter-stream ya se ejecuta dentro de EventMachine (algo que amqp necesita), así que no hay que crear el bloque externo como en el cliente.

Sin embargo, el código hace casi lo mismo... conecta con el servidor local, obtiene la referencia a la cola tweets y publica en ella cada uno de los tweets que recibe.

Antes de seguir, no olvidar el bundle install

Probando, probando

Tenemos el servidor ya levantado, levantamos un productor.

bundle exec ruby lib/producer.rb

De momento no hay nadie leyendo los mensajes. Puedes ver como se acumulan con:

sudo rabbitmqctl list_queues
Listing queues ...
tweets	65
...done.

Ahora lanzamos un cliente:

bundle exec ruby lib/countwer.rb

Y empezará a escupir los tweets en formato JSON

Conclusión

Me ha encantado. No sólo resuelve el problema si no que lo hace de forma muy sencilla (tanto en instalación como en API).

Bola Extra: Para no perder el norte... el objetivo era separar el lector de tweets de su procesador porque este hacía lógica pesada y si estuviesen acoplados el ritmo de lectura bajaría.

Es decir... lo único que hemos conseguido es acumular tweets en la cola de RabbitMQ porque el consumidor es más lento que el productor.

¿O no?

¡Pues no! (¡¡ta-chán!!) Sin cambiar una línea de código podemos lanzar varios procesadores que recibirán los mensajes de la cola. La única pega es que parece que RabbitMQ reparte la carga mediante round-robin así que si el tiempo de procesado no es más o menos homogéneo, me temo que seguiremos teniendo problemas.

Esto no es un post. Es una copia de mi respuesta a la opinión de Jesús sobre el AOS2011 (muy valiosa, leedla) Mi comentario es tan largo, tan "off-topic" y tan personal que he decidido publicarlo aquí.


Comparto en cierta medida la sensación de "podría haber sido mejor" (es curioso cómo con sólo cambiar las palabras la misma idea se vuelve positiva... nos viene bien la crítica, pero enfocada a hacer algo).

Por dos motivos:

En primer lugar, mi percepción de "endogamia". Aunque cerca del 50% de la gente era nueva en un AOS, yo no supe mezclarme con ellos o ellos no supieron hacerse visibles y participativos (¿es posible que a la gente nueva le interese lo mismo que a los que hemos visto ya un par de AOS?). Los comentarios en las sesiones los hacíamos "los de siempre" y lo mismo pasó con las propuestas (como en todo, salvo honrosas excepciones). Es curioso cómo las personas de las comunidades locales sí se hicieron notar (Galicia, Canarias, CyL, Zona Norte...).

Apertura Agile Open Spain 2011 - 30

En segundo, el enfoque "infinito" del evento. Mis dos charlas eran puramente técnicas y absolutamente no-ágiles (dudé mucho, pero bastante gente me animó) y sin embargo se hicieron un hueco.

Pero aun así, lo disfruté mucho. Quizá porque mis expectativas eran otras. Lo que me atrae de la comunidad ágil es la "densidad" de gente preocupada por su oficio comparado con otros entornos. Gente con ideas. Gente con propuestas. Es la gente con la que me gusta estar (incluso si sus ideas no son las mías) y si esa gente hiciese cualquier cosa no ágil para mi no habría diferencia.

Para rematar... Yo creo que el cambio se hace creando empresas (o departamentos) que "hagan las cosas bien". Y quizá, después, se consiga cambiar a las empresas que ya existen. Es más fácil hacer una casa nueva dónde se necesita que mover una que ya existe.

Vaya ladrillazo de comentario... 

¿Cómo uso twitter?

Este fin de semana le comentaba a @jmbeas en un descanso de la #xgn mi forma de utilizar twitter. Al final le convencí para probarlo. Él lo comento en twitter y su comentario ha generado bastantes respuestas (interesantes todas ellas).

Básicamente, mi forma de utilizar twitter es muy promiscua. Intento seguir a casi todo el mundo que conozco en persona. También a sus empresas. Y también a cualquiera que me siga y que parezca tener algo interesante que decir (esto lo decido en unos 2 segundos mirando los 5-10 últimos tweets que aparecen en su timeline).

La consecuencia es que leer todos los tweets de toda la gente que sigo sea imposible.

Así que me comporto como si estuviese en una gran fiesta:

  • tengo a mis amigos, a los que siempre presto atención... así cómo a otros conocidos
  • me muevo por la fiesta y, si en algún momento escucho algo interesante, participo en la conversación
  • si alguien habla conmigo, le hago caso

Lo que, traducido a cristiano significa:

  • tengo una lista con la gente que está realmente próxima a mi o cuya opinión me interesa especialmente y otras listas segmentando temas
  • miro el timeline de forma ocasional y sin preocuparme de leerlo todo... muchas veces lo ojeo cuando viajo en metro, mientras espero en una cafetería, mientras pasan los tests de integración...
  • intento contestar todas las @menciones y los mensajes directos

Para mi, seguir a un número inmanejable de personas tiene dos puntos positivos muy interesantes:

  • amplia mi mente: es más que probable que acabe leyendo artículos enlazados por personas con un perfil muy distinto al mio... me obliga a salir de mi "zona de confort" en cuanto a la información que consumo
  • permite que un montón de gente me contacte de forma privada... cuando sigues y te siguen, los DMs se convierten en una herramienta poderosa

¿Devalúa mi marca personal? Puede. No lo sé. No estoy construyendo una marca de forma activa. Posiblemente no haya demasiada diferencia entre mi yo online y mi yo offline...

¿Es mejor seguir a pocos, leer el timeline completo y enterarse de lo importante a través de los RTs de otra gente?
Es una opción, pero para mi gusto te pierdes la posibilidad de leer opiniones diversas. Sólo te llegan las noticias más mediáticas y la información que quieres oir (la del grupo selecto al que sigues)

¿Hay riesgo de procrastinación? Garantizo que sí, mucho :-).

¿No es más lógico seguir a los habituales y meter al grueso en una lista? Si no sigo a alguien no puede enviarme DMs, así que pierdo un canal de comunicación. Además, seguir a alguien es muy simple (un click) pero ponerlo en una lista es menos cómodo.

No es la única manera de usar twitter. Es la mia y estoy cómodo con ella. ¿Cómo lo usas tú?

Esta es una de esas entradas para recordarme la solución a cosas que me han dado problemas.

En este caso es relativo al comportamiento que tiene ActiveRecord al asignar valores a las relaciones.

post = Post.new(:comments => [ Comment.new, Comment.new])
post.count # => 0
post.size # => 2

Parece razonable. Como todavía no se ha guardado el post ni sus comments el count devuelve cero (lo que devolvería la base de datos). Sin embargo @size@devuelve la longitud correcta del array.

Sin embargo, esto es muy molesto durante las pruebas, dónde intentamos evitar los accesos a la base de datos.

let(:post) { mock_model(Post) }
before(:each) do
  post.comments = [mock_model(Comment), mock_model(Comment)]
end

Si el código que probamos usa size, el test es el que queremos. Si usa count, entonces no. Y sería muy malo hacer que el test dependiese de la implementación elegida.

La solución (o una de ellas) es mockear la asociación para evitar la lógica de active record:

let(:post) { mock_model(Post) }
before(:each) do
  post.stub(:comments).
       and_return [mock_model(Comment), mock_model(Comment)]
end

Porque, sí... los arrays devuelven el mismo valor para count que para size (y, ya puestos, para length).

¿Qué te parece? ¿Hay una solución mejor?

Hace ya algunos meses que estoy ayudando a mi familia con su tienda. Como buen informático, hago de chico para todo... lo mismo instalo un wordpress que hago spam en twitter.

Las Bellotas

Pero lo que me ha dado mucho qué pensar es... ¿Por qué soy yo el que gestiona los productos en la tienda online? ¿Por qué no la gestionan los dueños de la tienda?

En realidad creo que tengo una respuesta. Las herramientas de e-commerce no están a la altura de los negocios tradicionales. Funcionan muy bien para tiendas 2.0 dónde toda la gestión es digital e, incluso, es posible que no exista una tienda física. Pero para las tiendas que trabajan cara al público, internet les queda muy lejos.

Podemos decir que «hay que ponerse al día», «renovarse o morir» o muchas otras frases que no ayudan en nada a estos negocios. A esas tiendas tiendas en las que confías para tus compras del día a día. Lo que necesitan es un camino que les permita iniciar la transición a un modelo híbrido, vendiendo en la tienda física y añadiendo valor extra en su tienda online.

Entonces... ¿qué pasará con estas tiendas? ¿Están condenadas a desaparecer frente a los nuevos comercios virtuales? ¿Debemos renovar todos nuestro parque de pequeños comercios? ¿Deben los comercios invertir un dinero que no tienen en externalizar a una empresa o a un pariente que sepa de eso de interné su presencia online? ¿Existe alguna solución especialmente diseñada para estos negocios?

Lamentablemente, ahora mismo sólo tengo preguntas. Si tenéis alguna respuesta... aquí tenéis los comentarios.

La parte mala de estar en OSX viene cuando el resto del mundo decide compartir documentos contigo que usan fuentes «raras». A decir verdad, esto puede ocurrir siempre que alguien tenga (y use) una de esas fuentes raras en sus documentos.

La fuente «rara» en cuestión es Calibri... una de las fuentes de Windows Vista y Office 2007. Hasta dónde sé, Calibri es la nueva Arial y es la fuente por defecto. Así que si trabajáis con gente que use windows, lo más probable es que sus documentos estén escritos en Calibri (o cualquier otra de las fuentes nuevas).

Por suerte, estas fuentes se distribuyen en los productos de Microsoft para OSX. Incluso (y esto es lo bueno) en los gratuitos.

Así que, lo fácil es descargarse el Open XML Converter (que, por otra parte sirve para convertir los docx en doc de toda la vida).

Al abrir el DMG, no es necesario instalar nada... simplemente usad el botón derecho y la opción Mostrar contenido del paquete.

En la carpeta Contents/Packages tenéis el instalador para las fuentes: OpenXML_all_fonts.pkg.

¡Doble click y ya! Las fuentes instaladas vivirán a partir de ahora en /Library/Fonts/Microsoft

Muchas veces se usa la frase de la calidad no es negociable como argumento para hacer cualquier cosa que los técnicos queramos hacer.

Mi duda siempre ha sido... «¿pero qué es la calidad?». Hay muchas definiciones. En su momento, la famosa ISO9000 caracterizaba la calidad como poder repetir el mismo proceso para llegar al mismo producto dentro de una holgura determinada (más o menos...). Es decir, podías hacer un producto totalmente decepcionante usando las peores formas de trabajo pero tener un sello de calidad en él. Porque siempre lo haces igual de mal.

quality control 2

En realidad, la calidad es subjetiva. El consumidor tiene una visión y la ISO tiene otra. Obviamente, el equipo de desarrollo tendrá la suya y el cliente que les encarga el trabajo otra más.

Me ha llamado la atención el último artículo de Gojko Adzic sobre Mapas de efectos. Y no por la idea de los mapas (que es interesante) si no porque le dedica una sección al tema de la subjetividad en la calidad.

Es más, ataca esta subjetividad y sugiere que la calidad se defina explícitamente en función de quién es el beneficiario del valor que se está generando. De esta forma todos los implicados están alineados en sus objetivos. Además la definición no se realiza (sólo) a bajo nivel (esa definición podría ser el Definition of Done de cada tarea) si no que intenta que la definición sea de alto nivel para que pueda guiar el proyecto.

Lo curioso de definir así la calidad en un proyecto que incluye software es que el beneficiario del trabajo entiende qué es la calidad. No se basa en conceptos técnicos no relacionados con el negocio... no es opaca. Por otra parte, es muy posible que la definición de la calidad tal como la entienden muchos técnicos no sea importante a la hora de generar valor.

Demasiadas veces he oído cómo se usa la calidad (técnica) para justificar el retraso en las fechas de entrega o en la aproximación para resolver un problema del usuario. Crear una definición de calidad compartida desde el primer momento puede ayudar a evitar esto.

Y todo lo demás (pocos bugs, muchas pruebas, automatización del proceso de desarrollo) no es calidad. Es el sello de una buena ingeniería y lo que permite entregar la calidad que busca el cliente/consumidor/usuario.

¿No habéis notado que cada vez hay más startups? Sí, seguro que sí. Seguro que estáis hartos de que hasta el hijo de la portera está montando su startup. Sí... va a vender las madalenas de su madre por internet.

Cupcake Fail

Hoy me he levantado con ganas de ganarme enemigos. Así que, vamos a poner las cartas sobre la mesa.

No estás montando una startup

Asúmelo. Tu idea no es una startup...

No, no, espera... vamos un paso más atrás

¿qué diablos NO es una startup?

Casi toda la gente que habla de su startup está hablando de poner en marcha un proyecto de internet.

Mal.

Borra la palabra proyecto y empieza a pensar en negocio. Las palabras importan... «negocio» lleva asociados conceptos como ingresos, gastos, costes... que en «proyecto» quedan ocultos.

Bien, entonces digamos que estás montando un negocio en internet. Eso es algo difícil y muy loable, no dejes que nadie te quite la idea de la cabeza.

Pero todavía no es una startup. De la misma forma que la cafetería de mi barrio no es un Starbucks, tu negocio puede no tener la escala suficiente. Insisto, puede ser un negocio perfectamente rentable... pero no tiene la capacidad de crecer órdenes de magnitud en muy poco tiempo. Es una pyme.

Alguno estará pensando «¿Starbucks es una Startup?». No, por supuesto que no. Ya no, al menos. Es una empresa establecida, con dinámicas de negocio muy diferentes a una startup. Digamos que ser una startup es, también, un estado mental. O una fase del negocio. Igual que un emprendedor es algo diferente a un empresario (o un creador es distinto a un gestor), una empresa establecida es algo diferente a una startup.

Ok, ok... ya oigo a mis colegas técnicos desde detrás de sus pantallas... «nosotros somos pequeños e innovadores, estamos desarrollando un algoritmo revolucionaria que va a cambiar el estado del arte».

Aquí puede que te hayas «pasado de frenada» (puede que no, piénsalo friamente). Si lo que tienes va a revolucionar el status quo tanto como crees, es muy posible que ni siquiera tengas un mercado. Así que, aunque en teoría podrías multiplicar el valor de tu empresa, en la práctica seguramente sea difícil encontrar los clientes necesarios.

En este caso, es probable que tu empresa funcione mejor con subvenciones de I+D+i, o como una rama dentro de otra empresa. Quizá seas una startup, pero tu inversión en marketting será tan grande, o mayor, que la tecnológica. Espero que lo hayas incluido en tus cálculos. Y cuidado con no estar cultivando un mercado para que lo coseche algún otro...

Entonces, una startup, ¿qué es?

Me voy a lanzar con mi definición... ajustándola un poco a internet y a España.

  • Es un negocio: te lo tomas en serio, piensas no sólo en la parte técnica (la más fácil... a veces hasta irrelevante).
  • No es un hobby: Repito... te lo tomas en serio. Aunque quizá tengas que hacer otras cosas para poder pagar el desarrollo de la empresa (sobre todo si decides no buscar inversión), esas otras cosas son un mal necesario.
  • Es «el siguiente paso lógico»: Lo que plantea la startup debe ser comprensible (o mejor: obvio) una vez que te lo cuentan. No puede ser un salto demasiado grande que se anticipe a las necesidades reales, ni algo que repita lo que ya es mainstream.
  • Puede fallar: Una Startup está empujando los límites de los modelos de negocio y/o soluciones existentes. Quizá vaya en la dirección correcta, quizá no. Se mueve en un entorno incierto y todo puede pasar. Por eso te lo tomas en serio. Hay riesgo real de perder dinero y quedarte en el paro... no esperes que el estado te proteja.
  • Es invertible: independientemente de que aceptes o no inversión, las oportunidades reales de crecimiento deben ser jugosas.

En otros paises/entornos seguramente mi lista de características sería distinta. Por ejemplo, la inversión en revoluciones no es destacable en España. Y lo de «el siguiente paso lógico» seguramente no sea tan evidente para industrias como la ingeniería biomédica.

¿Y tengo que ser una startup?

No, por supuesto que no.

La mayoría de los negocios que hay sobre el planeta no son startups. Generan ingresos y beneficios. Dan empleo estable a millones de personas. Hacen que el mundo siga en marcha.

Si tienes la intención de montar una tienda online, ¡estupendo! (dicen que el ecommerce por fin despegará este año). Pero lo tienes muy difícil para convertirte en un Amazon o un Etsy.

Si vas a montar una consultora en informática, te puede ir genial. Pero estarás siempre limitado por las personas cualificadas que puedas encontrar (aunque algunas consultoras sí que son capaces de conseguir inversión).

12meses12katas es una idea muy interesante para poner a disposición de todo el mundo (para escarnio o inspiración) soluciones a problemas muy acotados.

Partiendo de que repetir una y otra vez este tipo de problemas no tiene el mismo valor que resolver problemas reales (no acotados), sí que tiene sus usos.

<I will find the droids I'm looking for I will find the droids I'm looking for I will find the droids I'm looking for

Uno de esos usos es colaborar en mejorar las katas (mediante peer review).

¿Qué?

La idea es simple: Estudiar la kata de otra persona.

Si encuentras defectos, crea y comparte con el autor los casos de prueba necesarios para demostrarlo (quizá con algún refactoring para hacer el código más testable). De esta forma el autor puede corregirlos y tú volver a revisarlos, iniciando una especie de diálogo.

Elegir de quién vamos a aprender

Lo primero es elegir una implementación de las que han sido publicadas en el github de 12meses12katas

Después tendremos que localizar el fork del autor. Con un poco de suerte, su usuario en github será el mismo del directorio y el proyecto se llamará igual que en 12meses12katas.

En mi caso, mi carpeta es amuino, por lo que mi url será:

https://github.com/amuino/Enero-String-Calculator.git

Si esto no funciona para localizar el fork, habrá que mirar la red del proyecto.

Preparar nuestra copia

Queremos enviar nuestros casos de prueba al autor de la kata, así que tendremos que configurar nuestro clon del repositorio para apuntar al clon del autor de la kata (de forma que trabajemos todos con el mismo código).

Mi opción para ello es crear una rama que siga al repositorio del autor:

git remote add -f -m master amuino https://github.com/amuino/Enero-String-Calculator.git
git checkout -b amuino amuino/master

Ya está, nuestro repositorio local tienes una rama amuino que sigue a mi repositorio. Además, estás usando esa rama.

(cambia amuino por el nombre del usuario que corresponda)

Enero-String-Calculator $ git branch
* amuino
  master

Cuando necesitemos volver a seguir nuestro repositorio, simplemente cambiamos a la rama master: git checkout master

Escribir los casos de prueba

Nada especial aquí... excepto, tal vez, que deberemos aprender lo básico del lenguaje en el que se haya hecho la kata para poder escribirlo y ejecutarlo (si es uno en el que no tengamos soltura).

Commit & Push

Tampoco hay nada especial en el commit.

git add .
git commit -m "Test para XYZ"

En el push, hay que recordar indicarle a git que debe crear una rama remota:

git push origin amuino

Desde este momento podremos ver la rama en nuestro proyecto de github.

Pull request

Todos los pasos se hacen en la web tu fork en github

Primero, cambia a la nueva rama (en mi caso, yo he usado la kata de Jorge Uriarte).

Cambio de rama en github

A continuación, iniciamos una pull-request. Por defecto, estará preparada para enviarla al repositorio de 12meses12katas:master. Haciendo click podemos cambiarlo seleccionando cualquiera de los forks. Hay que localizar el que nos interesa (si es el mío: amuino/Enero-String-Calculator).

Para confirmar el cambio, pulsamos el botón Update Commit Range.

Y ahora continuamos con el proceso normal de escribir un título y una descripción para la pull-request.

¡Listo!

El autor recibirá su notificación y podrá ponerse en contacto con vosotros si lo necesita para discutir el problema o aceptar el pull y mejorar su kata (o pasar de todo, que siempre es una opción).

¿Te mola la idea?

¡Pues no necesitas pedir permiso!

Puedes usar twitter para solicitar reviews o discutir la idea usando el tag #katabreakers

Otras opciones

Hay más formas de hacer lo mismo. Puedes usar parches y adjuntarlos a una issue en github, puedes hacer code reviews sobre los commits...

Si te gustan más, úsalas. Lo interesante es que aprendas del trabajo de otro y le ayudes a eso otro a aprender del tuyo.

Happy breaking!

Cerrar