Developing Frogtek

El blog del Departamento de Tecnología

Categoría: programación (página 2 de 6)

Pomodoros de verdad

La última semana tuvimos el placer de acoger en las oficinas de Frogtek al freelance y experto en craftmanship Enrique Comba (@ecomba), el cual trabajó codo con codo con nosotros para ayudarnos a mejorar nuestro proceso.

Siendo un experto en la materia como es él, aprovechamos para preguntarle cómo mejorar nuestros pomodoros. La técnica del pomodoro es un método de timeboxing (administración del tiempo) para realizar tareas en periodos alternos de trabajo exhaustivo y pausas. Nosotros ya habíamos integrado esta técnica a nuestro trabajo habitual, y esto era lo que sabíamos:

  • Cada pomodoro consiste en un periodo de trabajo continuo de 25 minutos.
  • Durante ese tiempo, hay que trabajar concentrándose en la tareaevitando cualquier distracción (correo, twitter, etc.). Algunas distracciones, sin embargo, son inevitables, como otros compañeros preguntando una duda, una llamada al teléfono, etc.
  • Un pomodoro es indivisible (no existe medio pomodoro). Lo utilizamos como unidad atómica de trabajo.
  • Después de cada pomodoro, hay que tomar una pausa breve de 5 minutos.
  • Después de un cierto número de pomodoros (entre 3 y 5 en nuestro caso) hay que tomar un descanso largo, de entre 15 y 25 minutos.
  • Al principio de cada jornada de trabajo, hay que planificar los pomodoros y descansos que se van a realizar.
  • Además hay que estimar cuánto tiempo (medido en pomodoros) va a costar realizar una tarea determinada.

Sin embargo, Enrique nos dio algunos consejos sobre las pausas, que no estabamos aplicando:

  • Es muy importante levantarse del asiento e incluse hacer ejercicios para evitar contracturas.
  • Debe intentar dejarse la mente en blanco. Esto es debido a que nuestro cerebro almacena la información y crea conexiones o momentos de inactividad, como durante el sueño.
  • No vale mirar el correo o twitter. Si es necesario utilizarlo, mejor tomar un pomodoro de “comunicación” de 25 minutos para realizar este tipo de tareas.

Sobre las distracciones:

  • Cualquier distracción (tanto interna como externa) debe anotarse en un papel, indicando su procedencia.
  • Al acabar la jornada, habrá que revisar la lista de distracciones y comprobar si pueden reducirse de alguna manera. En caso contrario, intentar agruparlas dentro de un mismo pomodoro.

Para más información, recomiendo leer este PDF del propio creador de la Técnica Pomodoro, Francesco Cirillo.

Tiendatek y sus amigos los Periféricos

Estoy seguro de que casi todos hemos visto en alguna ocasión un Sistema Punto de Venta (POS) con su correspondiente escáner de códigos de barras, impresión de recibos, pagos con tarjetas y por qué no, un lector de huellas digital. Con la demanda actual del mercado y los avances en tecnología, un POS no tendría sentido sin la ayuda de todos o parte de estos dispositivos. La realidad dicta que no es suficiente con poder registrar una venta sino que hay que hacerlo de la forma más rápida posible, a nadie nos gusta estar esperando en la cola del supermecado, porque además al cliente le gusta tener constancia de lo que ha comprado, a nadie nos gusta que nos engañen.

Tiendatek ha conocido a diferentes amigos conforme ha ido creciendo, apartándose de aquellos que no le convenían y que le retrasaban su aprendizaje. Cuando tan solo iba a la guardería conoció a un pequeño sistema de lectura de códigos de barras a través de la propia cámara del teléfono y cuyo nombre es ZXING. Una tarea que aparentemente puede parecer sencilla, al final resultaba desesperante para el tendero, debido a su baja eficiencia. Enseguida se dio cuenta de que tenía que encontrar a alguien que de verdad estuviese diseñado para ese fin. Así, cuando empezó la primaria conoció a un lector bluetooth llamado CipherLab quién además de bonito era barato. Se podía decir, que hasta el momento, el lector es y ha sido su mejor amigo. De esas relaciones donde nada cambia con el paso de los años.

Ya en la secundaria, Tiendatek y LectorTek, hicieron nuevos amigos. En esta ocasión se trataba de una linda y joven impresora de recibos vía bluetooth. Desde el primer día supo como seducirlos tanto a ellos como a los tenderos pasando por los programadores y el “product owner” de Tiendatek. Apenas han pasado unos meses, pero a simple vista se ve que existe química entre ellos.

 

Todavía les queda mucho camino que recorrer y periféricos que conocer pero ¿por qué no?, ¿veremos algún día a Tiendatek saliendo a bailar con un lector de pagos con tarjeta y/o sistema de identificación por huella digital en el día de su graduación?

Lanzar un Job de Jenkins desde Google App Engine

La semana pasada estuve dándole vueltas a este problema, después de varios intentos fallidos llegué, con la ayuda de Julio, a la solución que planteo en el título del post.

Para empezar tenemos que ir al job en Jenkins que queramos lanzar desde fuera y activar la opción de “Lanzar ejecuciones remotas”

Por motivos de seguridad, Jenkins nos obliga a usar un Token que será usado al llamar al Job desde fuera.

El código que usaremos en GAE (en Python) será el siguiente:

import urllib2, base64, httplib
from urllib2 import URLError, HTTPError
from django.http import HttpResponse

def call_mlp_generator(request):

    theurl = 'JENKINS_JOB_URL?token=TOKEN'
    username = 'USERNAME'
    password = 'PASSWORD'

    request = urllib2.Request(theurl, None)
    base64string = base64.encodestring('%s:%s' % (username, password)).replace('n', '')
    request.add_header("Authorization", "Basic %s" % base64string)
    try:
        urllib2.urlopen(request)
        response = str(httplib.OK)
    except HTTPError, e:
        response = str(e.code)
    except URLError, e:
        response = str(e.code)

    return HttpResponse(response)

Bastante simple, sólo había que saber tocar las teclas adecuadas.

Entorno de desarrollo de Google App Engine en Fedora 15

Me parece interesante contar la experiencia que tuve ayer al configurar el entorno de desarrollo de GAE en una máquina Linux (Fedora 15 en este caso), sobre todo por si puede ayudar a otros desarrolladores y evitar algunos dolores de cabeza.

Aquellos que trabajen con GAE han de saber que hasta nueva orden, el sistema necesita Python 2.5 para poder funcionar correctamente. Google así lo recomienda, aunque recuerdo haberlo hecho funcionar sobre Python 2.6 en mi anterior vida (cuando era Ubuntu).

Voy a intentar reconstruir el camino correcto a seguir para configurar el entorno de desarrollo de GAE sobre un Fedora 15 (ya que di muchas idas y venidas).

La última versión de Fedora tiene por defecto Python 2.7, y si intentaba arrancar el proyecto en local usando esta versión de Python, tenía serios problemas de incompatibilidades de módulos, por ello me bajé Python 2.5.

Por otro lado instalé un par de librerías que necesitaría más adelante (esto tardé varias horas en hacerlo funcionar, por el orden en que hacía las cosas):

sudo yum install openssl openssl-devel -y
sudo yum install sqlite-devel

Una vez instaladas estas librerías era el momento de compilar el código de Python 2.5 e instalarlo. Antes de nada, hay que modificar el fichero <python-folder>/Modules/Setup.dist y descomentar las siguientes líneas:

# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
SSL=/usr/local/ssl
_ssl _ssl.c 
	-DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl 
	-L$(SSL)/lib -lssl -lcrypto

(Líneas 206-209)

De esta forma habilitamos el módulo de SSL cuando construyamos Python.

Es hora de construir Python:

su
./configure
make
make altinstall

Con el make altinstall lo que hacemos es instalar Python en una ruta diferente y no machacar la versión actual que tengamos instalada en el sistema.

Si todo ha ido bien, ahora podremos usar

python2.5 dev_appserver.py --port 8080 RutaDeTuAplicación

Si compilamos Python 2.5 sin haber instalado las librerías arriba mencionadas o sin haber habilitado los módulos de SSL podríamos encontrarnos problemas como estos a la hora de arrancar el proyecto:

AttributeError: 'module' object has no attribute 'HTTPSHandler'

o

ImportError: No module named _sqlite3

(Dependiendo de lo complejo que sea vuestro proyecto, claro.)

Espero que esta pequeña guía sirva de ayuda para aquellos que tengan los mismos problemas que tuve en su momento.

Compartir es poder.

Frogtek libera PoisonFrog

Llevabamos un tiempo queriendo dar esta noticia. Es un gran honor para todo el equipo de Frogtek presentar PoisonFrog.

Nuestro producto requiere un acceso a la base de datos que sea muy configurable y adaptable a los cambios, así como abrir varias bases de datos desde la misma aplicación. Realmente Android no permite hacer esto como a nosotros nos gustaba. Así que desde hace ya mucho tiempo teníamos una librería interna para hacer estas tareas.

Por eso pensamos que sería de mucha utilidad devolver a la comunidad mucho del conocimiento que nosotros hemos adquirido de ella. Por eso hemos liberado esa librería bajo licencia Apache 2. El nombre surgió tras un gran debate interno en el que se propusieron infinidad de nombres. Las Poison Frog son ranas  que cumplen caracteristicas que creemos que son comunes con la librería y con Frogtek.

  • Son las reinas de su entorno por ser venenosas.
  • Son vistosas dado su color.
  • Hay varios colores (Portar la librería a más sistemas)
  • Viven en centroamérica y sudamérica, exactamente donde desplegamos nuestro producto, tiendatek.
  • Son ranas, igual que el nombre de nuestra empresa. Vamos a ayudar a la comunidad con un “leap frog” para ir de los “early 80’s to the XXI century in terms of database connection”.

Aquí os dejo la web del proyecto.

https://code.google.com/p/poisonfrog/

Por favor sentíos libres de comentar, commitear y criticar constructivamente.

También queremos dar las gracias a nuestra gran diseñadora Kristel Aranda por hacernos el diseño del logo.

¡Gracias!

Android y sus Layouts

Imaginad que al realizar una aplicación web compleja, en vez de hacerla para que se vea bien en todos los navegadores, la hacéis solo para una resolución de pantalla concreta y un navegador específico. Sería un infierno tener que repasarla entera, una vez acabada, para que se adapte a cualquier navegador y resolución, ¿verdad?.

Android Layout

Pues algo así nos pasó a nosotros, pero en Android. Parte de culpa tuvimos, he de reconocer, por no ser previsores y tirarnos por el camino fácil. Aunque diré en nuestra defensa que cuando se empezó nuestro producto Android estaba en pañales y no existía tanta tablet y teléfono en el cual ejecutar tu aplicación.

Aquí van pues una serie de recomendaciones. Para que no cometáis los mismos errores que nosotros.

  • Entended cómo funciona el tema de las pantallas en Android, no es lo mismo una densidad que otra, el tamaño de pantalla, etc.
  • No uséis la unidad de medida px. Mejor dp, o sp si son tamaños de texto.
  • Tened claro como elige Android los recursos que ponéis a su disponibilidad.
  • Evitad en toda medida posible usar layouts con medidas absolutas, hacedlos adaptables (fill_parent, wrap_content). Os ahorrareis muchos quebraderos de cabeza.
  • Si no podéis evitarlo y tenéis que usar valores en vuestros layouts. Extraedlos a un xml y definidlos como Dimensions. Así os será más fácil adaptar la aplicación a las distintas configuraciones que queráis soportar, pues con definir el archivo de dimensiones para cada modalidad de recursos os valdrá.
  • Usad el atributo android:drawableTop, android:drawableLeft…, para introducir imágenes en botones. No os pase como a nosotros que o pedíamos el fondo ya con la imagen o introducíamos un elemento adicional, recargando el layout.
  • No os dejéis enamorar por las bondades de los RelativeLayout. No son malos. Pero a veces un LinearLayout con sus pesos puede ser más fácilmente adaptado a varias pantallas.

Y nada más. Si se os ocurre alguna más que nosotros no hemos nombrado, compartidlo con todos!

 

Excepciones para controlar tu lógica

Hace unos días apareció en nuestro board una User Story que tenía como título:

“Pop-up warning when Cost is higher than Price”

En sus AT’s aparecían las pantallas donde debería hacerse esta comprobación. Así que nos pusimos manos a la obra y estudiamos cuál sería el impacto de este cambio. Vimos que tendríamos que añadir una condición en todas las pantallas y en todos los sitios donde son susceptibles de cambio las dos variables que nos atañen.

Si optábamos por ese camino, esto iba a oler a bug, en el que te reportan que no se muestra el pop-up en un lugar que no tuviste en cuenta a la hora de añadir la condición. Con lo que decidimos no optar por la solución a priori mecánica y sencilla. De repente, la palabra “Excepciones” vino a nuestras mentes, Rubén de Biko2 estuvo durante tres días inculcando su sabiduria en el equipo de Frogtek y algo de lo que nos contó salía a la luz.

Así que decidimos implementarnos una excepción que se lanzase desde la lógica hacia la UI si esta condición se daba. De este modo el impacto sería mucho menor y desde la UI solo tendríamos que controlar dicha excepción y mostrar el pop-up, y además sería imposible saltarnos ningún sitio, puesto que tendríamos error de compilación. Así quedo nuestra clase:

package org.frogtek.tiendatekcore.exceptions;
  public class CostHigherThanPriceException extends Exception {
        public CostHigherThanPriceException() {
            super("Cost is higher than price");
        }
    }

En este caso el mensaje no es importante para nosotros: solo queremos capturar el momento en el que sucede esta condición.

El método del bean que lanzaba la excepción quedaría así:

    public void setPurchaseCost(long purchaseCost) throws CostHigherThanPriceException {
        if (purchaseCost != this.mPurchaseCost) {
            if (this.mPurchasePrice < purchaseCost) {
                throw new CostHigherThanPriceException();
            } else {
                this.mPurchaseCost = purchaseCost;
            }
        }
    }

Después de esto surgieron por la oficina las dudas filosóficas de si estabamos tomando el camino correcto al usar excepciones para esto, o de si un excepción no debería controlar solo errores que no se pueden manejar. Esta es la definición oficial de java:

An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions.

Muy abierta y si os dais cuenta no habla en ningún momento de errores. Habla de eventos.

Conclusiones que en Frogtek hemos obtenido:

  • Que tener a una persona de fuera de la oficina con el espíritu y con las ganas de hacer bien las cosas es increíble.
  • Que usar excepciones es una muy buena estrategia para definir tu lógica. Nosotros somos un equipo de 7 personas tocando y retocando el mismo código a diario. Ayuda mucho que tú tengas que llamar a un método que lance una excepción: desde el primer momento estás advertido de que ese método puede lanzar algo y estás en la obligación de controlarlo.

Cambiar de entorno de programación

Es común encontrarse con equipos “Java”, “.Net” o “Cobol”, los cuales trabajan solo y para un entorno. Está claro que si te sientes cómodo programando en Java, te dará algo de respeto meterte a programar en .Net, o lo mismo el jefe no quiere que pierdas tu tiempo programando en Java, si ya lo haces bien en .Net.

“Es una pérdida de tiempo y el cliente quiere el proyecto para ayer”.

Como programador, valoro mucho el poder trabajar en diferentes entornos de desarrollo, por varios motivos:

  • A veces trabajar sobre una tecnología demasiado tiempo (en mi caso, Android) me ofusca sobremanera. Hacer alguna Historia de Usuario en Python me relaja y ayuda a recuperarme un poco de la ofuscación.
  • Sacarme de la comodidad habitual de un entorno muy conocido puede ayudar a la motivación, a pensar nuevas estrategias y nuevas formas de desarrollar. Llevando esta analogía al mundo friki… ¿Es lo mismo jugar con los Marines Espaciales que con los Eldar en el Warhammer 40.000? Seguro que no, cada uno tiene sus estrategias, sus ventajas e inconvenientes.
  • Aprender nuevas tecnologías. ¿Hay algo más hermoso para un developer?

– “Hala, venga, trabajad en Python,”

– “¡Pero si no tengo ni idea!”

Esto pasa, si no tienes ni idea de un lenguaje, como decía antes,  te da algo de respeto cambiarte. Es posible que la primera vez no seas 100% productivo (siéntete afortunado si lo eres un 20%)  y no hagas las cosas bien del todo, pero lo mismo la segunda ya lo haces mejor y a la tercera vez que te cambias ya lo dominas mucho más. Es recomendable que las primeras veces haya algún “experto” en la materia que pueda guiarte por esos momentos de incertidumbre y confusión.

“¿Qué carajo es jQuery?”

¿Merece la pena bajar un poco la productividad por que haya más gente que sepa un poco de todo? Si tienes en tu equipo a un hacker en Cobol y solo él sabe del proyecto… ¿Qué probabilidad hay de que se vaya todo al carajo si a este hacker se lo lleva un autobús por delante? Bueno, quien dice un autobús….  dice que se va de vacaciones y se jode algo del proyecto… o algo más dramático (pero no tanto como lo del bus), que se vaya a otra empresa. Reducir ese factor de riesgo es positivo para la empresa (para una empresa que se preocupe de sus proyectos, la calidad de los mismos y la salud mental de los developers).

“No estoy programando en Python, sino que estoy programando en Python como si fuera Java”

Esto pasa… Cuando no conoces un lenguaje, sueles agarrarte a lo que conoces, si conoces Java tenderás a desarrollar código Python como si fuese Java… Luego, cuando vayas cogiendo más experiencia, conociendo la API y la sintaxis te darás cuenta de la diferencia, del cambio de chip y de crear código Python en sintonía con Python (luego corres el riesgo de volver a Java y escribir código Java como si fuera Python….).

A pesar de las pequeñas incomodidades (que en el fondo deberían ser alicientes para romperse la cabeza), recomiendo cambiar de entorno de vez en cuando y siempre y cuando la empresa te lo permita, claro.

De hecho, estoy bastante cansado de Android… me voy a poner a hacer algo en Python.

PD. Donde pone “Python” en este artículo, cambiar por el lenguaje que os gustaría aprender/practicar. He personalizado el post a mi caso, podría haber puesto “.NET”… pero entonces no habría sido yo el que hubiese escrito el artículo. 😛

Revisión de código

Code Review

¿Revisar código?

¿Para qué?

¿Lo has probado?

Pues ya está ¿no?

Pues no. O al menos en Frogtek no nos vale. Y se agradece, la verdad. Veamos cómo y cuándo hacemos las revisiones de código.

Actualmente realizamos tres tipos de revisión de código:

  • Revisiones de código de las User Stories. Una vez terminadas y subidas al repositorio se revisan usando ReviewBoard, dando feedback, cuando sea necesario, a través de la herramienta. Dicha revisión se realiza dos veces. La primera por un programador y la segunda, por el tester antes de realizar el testing y verificación de la User Story.
  • Reuniones de revisión de código. Consisten en unas reuniones semanales en las cuales nos juntamos todos a ver, revisar, comentar… una funcionalidad nueva o un refactor especialmente delicado. Cualquier programador puede proponer código para ser revisado y nos animamos unos a los otros a ello.
  • Pair programinng de User Stories o parte de ellas. Aunque lo realizamos menos de lo deseado, lo usamos sobre todo cuando la funcionalidad que programar es complicada o propensa a errores. Nos ha dado muy buenos resultados siempre que lo hemos utilizado.

Solo llevamos alrededor de un año aplicando estás técnicas de manera exhaustiva, pero creo que las mejoras han sido sustanciales en la calidad de nuestro código y de nuestras habilidades.

Personalmente, lo que más me ha gustado es el conocimiento que se adquiere de toda la aplicación gracias a las revisiones. Ya no solo sabes lo que tú has hecho, sino gran parte de lo que el resto ha programado también.

Como nota final, un vídeo gracioso sobre Pair programing. En Inglés, lo siento.

Aquí huele a cuco (V)

Código del Jurásico encontrado en tiendatek.

 
        if (enteredAmount == 0) {
            mTheProduct.setProdPrice(0);
        } else {
            mTheProduct.setProdPrice(enteredAmount);
        }

Al parecer los cambios en la Pangea nos afectaron un poco.

¿Algún comentario o mejora?

Nuestro amigo Eduardo Moreno propone una versión mejorada:

if (enteredAmount * enteredAmount == 0) {
   mTheProduct.setProdPrice(Math.round(3.5* Math.cos(Math.PI/2)));
} else {
   mTheProduct.setProdPrice(enteredAmount * Math.exp(0));
}
Antiguas entradas Recientes entradas