Developing Frogtek

El blog del Departamento de Tecnología

Mes: julio 2010 (página 1 de 2)

Humor para ingenieros: el Ibón* más geek…

“… el Ibón de IP”

*Ibón: Lago pirenáico de origen glaciar.

Experiencias y consejos para trabajar en casa

¿Cuáles son las herramientas básicas para que un desarrollador software realice su trabajo?

Un ordenador y una conexión a Internet.

¿Por qué no vamos a poder hacer nuestro trabajo en casa?

Teletrabajo… una palabra a la que muchas empresas le temen.

No digo que se haga siempre, pero sí de vez en cuando. Empecé a trabajar en Frogtek de esa manera, desde casa. El motivo principal era la distancia y que por razones circunstanciales no podía desplazarme de forma definitiva a Zaragoza o Huesca. Aun así, los compañeros que viven en Zaragoza tienen la opción de trabajar desde casa, una vez a la semana. ¿Se trabaja mejor? ¿Se trabaja peor? Depende de las circunstancias de cada uno. Hay gente que no se concentra en casa, que tiene mucho despiste, quizás niños correteando de un lado a otro, o lo mismo el vecino ha decidido hacer una remodelación en su casa y cree conveniente que las 8.30 es buena hora para empezar a martillear la pared (Tampoco ayuda tener una visita en casa cuando estás teletrabajando…)

Creo que de los desarrolladores de Frogtek, he sido el que más tiempo ha pasado en casa trabajando. Me gustaría compartir algunos consejos y experiencias que he ido acumulando estos últimos meses.

Es MUY importante tener un lugar fijo para trabajar. Hacerte un espacio en casa donde puedas estar tranquilo. Lo recomendable sería que fuese en una habitación aparte de donde duermes o donde haces vida normalmente (salón, por un decir… aunque no puedo aplicarlo en mi caso, ya que yo hago vida normalmente donde esté el ordenador).

La comodidad del lugar es importante. Si vas a pasar mucho tiempo sentado (que si eres desarrollador, seguramente sí) una cómoda silla de oficina con ruedas vendrá de lujo y una mesa amplia, donde tengas espacio suficiente para colocar todas tus cosas, mejor todavía.

Hay que concienciarse muy bien y marcarse unos horarios. Empezar y terminar de trabajar a la misma hora (intentando mantener un horario de oficina, por ejemplo). No vale eso de “Hoy me levanto a las 10 y trabajo hasta las 20.00, mañana ya madrugaré”, lo más probable es que mañana no madrugues y te vuelvas a levantar a las 10. Nunca hay que dejarse, hay que mantener el horario y no romper la norma que te impongas.

La indumentaria… el cómo vestirse. Bueno, lo ideal es vestirse como si se fuera a trabajar fuera (no es que te pongas de traje, pero sí algo cómodo), pero os puedo asegurar, que en verano, en Zaragoza, lo último que quieres tener puesto es una camiseta y un pantalón vaquero. En ese caso es muy posible que se dé el llamado “underwear-programming“, es bastante cómodo, pero poco serio. ¡Imagina que tienes una video-conferencia por Skype de improvisto! Más vale que tengas la ropa a mano.

Trabajar desde casa no es tan bonito como parece en un principio. Cuando pasas mucho tiempo solo en casa, trabajando delante del ordenador, echas de menos las relaciones personales; los chistes de los compañeros, las salidas a la cafetería o a “fumarse un cigarro”, el hablar con alguien directamente para preguntarle una duda, en vez de usar Skype o aplicaciones de mensajería instantánea… en fin, el teletrabajo, desde mi punto de vista, es bueno, siempre que se tenga esa opción, pero no hay nada como el ambiente en la oficina (¡¡por lo menos en la de Frogtek!!).

Otra desventaja de trabajar en casa (y sobre todo para una persona como yo, que tiene el ordenador encendido el 90% del día), es que llega un momento en que no desconectas y es dificil separar tu vida personal de tu vida profesional. Trabajar hasta altas horas de la noche (Bueno, depende de la situación a veces viene bien algo de night-programming, pero nunca después de llegar de marcha) o comer mientras estás programando. Por eso es muy importante tener un horario estricto.

Waterfall vs SCRUM vs Kanban (II)

[Leer Waterfall vs SCRUM vs Kanban (I)]

Fue así como descubrimos SCRUM, una metodología ágil que implementa de una u otra manera los 4 principios fundamentales del Agile Manifesto, a saber:

  1. Que aunque los procesos y las herramientas son importantes, lo son más los individuos y sus interacciones.
  2. Que aunque la documentación exhaustiva está muy bien, es mucho mejor tener prototipos que funcionan.
  3. Que aunque negociar un contrato con el cliente es vital, es mejor aún que el cliente se involucre contigo en el proyecto.
  4. Y que aunque saber seguir un plan es una estupenda habilidad, más importante es saber cambiar dicho plan a tiempo.

SCRUM define distintos roles para las distintas personas que participan en un proyecto, no voy a entrar en detalles ya que existe multitud de literatura al respecto. Simplemente saber que existe el rol de Product Owner (en adelante PO) que es la persona que, en estrecho contacto con el cliente, define las pequeñas piezas de funcionalidad que se le van añadiendo poco a poco al producto. También se define el rol del Team (equipo de desarrolladores) que son los programadores de la cosa y el del SCRUM Master, que viene a ser el encargado de que todo el proceso que define SCRUM, el ritual periódico por el que hay que pasar inexorablemente, se lleve a la práctica como Dios manda. ¿Ritual?, ¿qué ritual?. Pues principalmente uno muy sencillo, el que sigue:

  • Como nos resulta imposible saber con antelación qué es lo que quiere el cliente dividimos el tiempo en pequeños periodos (Sprints, típicamente de entre 2 y 4 semanas) sobre los que creemos tener suficiente visibilidad. Es decir, “no tengo ni idea de cómo va a evolucionar mi producto dentro de 6 meses pero sí creo saber que mi cliente quiere ver tales características funcionando dentro de 2 semanas”… Esto tiene que ver con los puntos 3 y 4 del Manifiesto Ágil (involucrar al cliente y gestionar el cambio).
  • El PO, por lo tanto, estudia con el cliente la funcionalidad que les gustaría tener disponible en la próxima versión de la aplicación. Y luego participa en la reunión de planificación de principio de Sprint en la que, junto con el Equipo de Desarrollo, se clarifica qué hay que hacer y se decide quién hará qué y cuánto tiempo costará. Punto 1, sobre las personas y las interacciones.
  • Durante todo el Sprint el Equipo de Desarrollo lleva a cabo reuniones diarias para intercambiar información. De nuevo reforzando el punto 1 del Manifiesto.
  • Cuando se acaba el Sprint se hace una reunión de Revisión y Demo en la que el PO muestra al cliente, o los desarrolladores al PO (depende) la nueva versión del producto con las mejoras de las últimas dos semanas ya listas. Punto 2, mejor un prototipo que un infumable tocho de documentación obsoleta.
  • El ritual termina con la reunión de Retrospectiva, donde el Equipo de Desarrollo junto con SCRUM Master y POs revisan el proceso y proponen mejoras para el siguiente Sprint.

Y vuelta a empezar. Hay normas extras, peculiaridades, cosas divertidas y complicaciones sobre las que se podría profundizar mucho, pero básicamente esto es SCRUM.

En nuestro caso la cosa empezó bastante “de andar por casa”. El PO era PO y SCRUM Master a la vez, los programadores no hacían Stand-ups… Cowboy-SCRUM como bien dice Pablo. Pero bueno, la intención es lo que cuenta, durante un tiempo al menos.

Con la nueva oficina la cosa mejoró, al menos el equipo técnico ya se veía las caras. Stand-ups, Sprint Plannings, Sprint Reviews, Sprint Retrospectives… toda una plétora de reuniones salpicaba nuestro calendario. Mucha diversión mientras a la vez tratábamos de montar un entorno de desarrollo decente con pre-producción, producción, repositorios de código, branches… la juerga padre vamos. El típico momento en el que a los novatos emprendedores les empiezan a crecer los enanos y se dan cuenta de que ser profesional es difícil, muy difícil y complejo, muy complejo.

Lo que veis más arriba era nuestro día a día por aquellos tiempos. Habíamos conseguido ya tener un proceso automático que compilaba todos los días a las 15:00 CET (a primera hora de la mañana de nuestros POs en USA y Colombia) una versión de preproducción. Al final del Sprint sacábamos dos versiones de producción, una el viernes después del Review del jueves y otra el domingo con las US (User Stories, pequeños fragmentos de funcionalidad) que nuestro programador exiliado en Santiago de Compostela hacía los fines de semana. Resultado: habíamos dado nuestro primer paso hacia un concepto que desconocíamos, la Integración Continua… y nos salían bugs por todos lados. Fue por eso que empezamos también a interesarnos por cosas como el TDD y las pruebas unitarias automáticas y nos empezáramos a preocupar de que la frase “pues en mi emulador funciona” se oyera cada vez menos.

En lo que respecta a SCRUM dimos un paso de adelante contratando el servicio AgileBuddy una página web que te permite gestionar distintos proyectos con sus respectivos Backlogs (el conjunto de funcionalidades a programar), los Sprint Backlogs (cosas a programar durante el Sprint), etc, etc. Se trata de una útil herramienta para gestionar tus proyectos usando esta metodología. Lo mejor, que te dota de un marco de trabajo donde tienes todo mucho más controlado y que te calcula automáticamente las métricas de tus proyectos (Burndown chart y demás). Lo peor, que a veces no es fácil entender la forma que tienen estas herramientas de calcular sus métricas y también que quizá entraba en demasiado detalle y era necesario desglosar tareas, imputar horas de forma no siempre tan fácil o intuitiva como nos gustaría.

No fue AgileBuddy, no obstante, la razón por la apenas 4 meses después decidimos cambiar al Kanban. ¿Cambiamos por las razones adecuadas?, ¿fue un cambio precipitado?, ¿estábamos haciendo suficientemente bien SCRUM?… Todo eso y mucho más, en el próximo capítulo.

Eficiencia en Google App Engine: Appstats

Nuestra elección a la hora de subir datos a la nube fue Google App Engine, el servicio que permite ejecutar aplicaciones web en la infraestructura de Google. El desarrollo  en esta plataforma presenta ciertas características que obligan a cambiar el chip desde un primer momento y que nos fuerzan implícitamente a tener en cuenta la eficiencia y, sobretodo, la escalabilidad. Dicho esto, siempre hay momentos a lo largo del camino en los que uno se plantea revisar la eficiencia global de la aplicación para mejorar su tiempo de respuesta, reducir los consumos de cpu y, de paso, reducir la factura cobrada por Google.

La primera vez que nos enfrentamos a esta situación decidimos usar cProfile y pstats para estudiar los tiempos de nuestro código Python centrándonos en aspectos clásicos como optimización de búsquedas, mejora de la eficiencia en la manera de concatenar cadenas, reducción del número de iteraciones en un bucle…la verdad es que de poco nos sirvió, ya que, veíamos que la mayor parte del tiempo de proceso se gastaba en algo que en el profile se indicaba con líneas como esta:

_apphosting_runtime___python__apiproxy.Wait

Es decir, que la mayor parte del tiempo nuestra aplicación estaba esperando a que se completase el proceso realizado por una llamada a alguna API de Google.

Estudiando en detalle el lugar del código en el que aparecen estas líneas, se puede averiguar a qué API se están refiriendo pero, por suerte, todo ese trabajo dejó de ser necesario gracias al descubrimiento de Appstats:

Appstats es una herramienta creada por  Guido van Rossum (creador de Python y actual empleado de Google) que forma parte del SDK y nos permite ver en detalle en qué emplea realmente el tiempo nuestra aplicación mediante el estudio de las RPC, es decir, las llamadas remotas que nuestra aplicación hace a las distintas API’s de Google. Su instalación es muy sencilla y podemos instalarla incluso en producción porque consume muy pocos recursos.

En  el siguiente video, el propio Guido, nos explica las bondades de esta herramienta indispensable:

En el video se muestra cómo instalar y usar la herramienta, una breve explicación de su funcionamiento y consumo, posibilidades de configuración y algunos ejemplos de uso como, por ejemplo, detección de ciertos patrones de ineficiencia comunes a muchas aplicaciones : Patterns of Doom!

Cargar array estático desde xml en Android

En Android podemos definir nuestros propios arrays estáticos en xml y guardarlo en la carpeta res/values. De este modo lo tendremos siempre a mano (a través de la clase R) y soportará multi-idioma.

Podremos crear arrays de los siguiente tipos:

Y la manera de definir un array es:


   Modo Aprendiz
   Modo Experto

Para poder acceder posteriormente desde código es tan sencillo como hacer esto a través de un objeto Context:

String[] helpModesArray;
helpModesArray = getResources().getStringArray(R.array.helpModes);

Eficiencia en Android

Continuamos con nuestro afán por tener una aplicación más eficiente e iremos escribiendo con lo que nos vamos encontrado: tenemos una tabla con datos para sincronizar y mientras se sincronizan actualizamos una barra de progreso en la status bar. Actualmente, actualizábamos la barra de progreso cada vez que se procesaba una fila, con lo cual, actualizábamos la barra de progreso tantas veces como filas teniamos.

Julio (QA) al percatarse de que esta operación costaba mucho tiempo, lanzó su herramienta más preciada…, el traceview. Se pasó por mi mesa y vimos que la clase Notify de Android se nos estaba llevando un gran tiempo debido al problema explicado en el párrafo anterior.

Con lo que nos pusimos manos a la obra y escribimos el correspondiente método estático que nos calcula el porcentaje y nos dirá si tenemos que actualizar la progress bar, de este modo siempre la actualizaremos 100 veces. Ahí va:

/*** This method retuns true if an update is needed in the progess bar
 *
 * @param itemsCount The total number of items
 * @param iCount The actual item to be processed
 * @return True if is necesary to update the progress bar
 */
 public static boolean isNeededProgressBarUpdate(int itemsCount, int iCount) {
    if (itemsCount != 0 && iCount !=0) {
        int perActual = (iCount * 100) / itemsCount;
        int perPrevious = ((iCount - 1) * 100) / itemsCount;
        if (perActual == perPrevious) {
            return false;
        } else {
            return true;
        }
    } else {
       return true;
    }
 }

Por otro lado también hemos notado que el Log de Android consume bastantes recurso y así lo comentan en la documentación. Pero no tenemos muy claro qué pasa con el Log.d (DEBUG). Según dice en la documentación, no se escribe en tiempo de ejecución, pero… creemos que depende de si marcas el teléfono para debug o no.

Como conclusión final hemos conseguido reducir un proceso que le costaba una hora a unos 20 minutos.

Cadenas dinámicas en Android

Al programar aplicaciones en Android, resulta ineludible el hacer uso del recurso “strings.xml”, un archivo en el que podemos escribir todas las cadenas de texto que aparecen en nuestra aplicación. Las ventajas son claras:

  • Localización: disponemos de todas las cadenas de texto en un mismo archivo. Ideal para realizar correcciones o encontrar rápidamente un texto.
  • Reutilización: con total certeza una misma cadena aparecerá más de una vez en distintas partes de nuestra aplicación. Al almacenarlas de esta forma, facilitamos su reciclaje.
  • Multi idioma: incluso la aplicación más modesta puede necesitar en un futuro estar traducida a distintos idiomas. Con crear un archivo strings.xml adicional para el nuevo idioma, queda solucionado.

Pero ¿qué pasa cuando queremos construir cadenas complejas? (u otras estructuras como enlaces). Pues bien, Android nos facilita el crear cadenas complejas mediante la utilización de parámetros dinámicos. Imaginemos que queremos crear una cadena como la siguiente:

Bienvenido a Developing Frogtek.
Hoy es miércoles, 21 de julio.

de forma que la fecha cambie en función del día actual.

Podríamos crear una cadena de este tipo en el archivo strings.xml:

Bienvenido a Frogtek.org.n Hoy es %s

Después en nuestra aplicación podríamos mostrar la cadena de la siguiente forma:

getString(R.string.welcome_text, "http://developing.frogtek.org", Calendar.getDate())

Como se puede ver, la función getString acepta cualquier número de parámetros, al estilo del printf de C.

Notificando en Android

El API de Android nos permite varias maneras de requerir la atención del usuario. Lo que resulta realmente difícil es decidir qué tipo de notificación usar en cada momento. Os vamos a mostrar qué tipos de notificaciones usamos en Frogtek y para qué.

android:theme="@android:style/Theme.Dialog"

Este diálogo bloquea el hilo de la interfaz, incluso podemos decir que no sea        cancelable y evitar así que desaparezca cuando el usuario pulsa el botón                    “BACK”, así nos aseguraremos que siempre pase por nuestro código para                cancelarlo.

  • Barra de estado: en frogtek usamos esta barra para notificar al usuario y no requerir su interacción inmediata, por ejemplo para:
    1. Mostrar que hay una nueva actualización de la aplicación disponible.
    2. Realizar un proceso en background y que el usuario pueda ver el proceso si le interesa.

    NotificationManager mNotificationManager;
    mNotificationManager = (NotificationManager)
    theContext.getSystemService(android.content.Context.NOTIFICATION_SERVICE); 
    
    PendingIntent contentIntent = PendingIntent.getActivity(theContext, 1, notificationIntent, 1);
    
    long when = System.currentTimeMillis();
    
    Notification notificationStatus = new Notification(icon,text,when);
    
    notificationStatus.setLatestEventInfo(theContext, title, text, contentIntent);
    mNotificationManager.notify(notificationID,notificationStatus);
  • Toast: este tipo de notificación en Android es idóneo para informar al usuario en la pantalla principal sin distraerle demasiado y dejando que el hilo principal siga su ejecución. En nuestra aplicación lo usamos para indicar el importe estimado en caja después de cada operación. Incluso podemos personalizar las vista de un toast (en nuestro caso cambiamos los colores del fondo):
  • View layout = inflater.inflate(rLayout, viewGroup);
    TextView text = (TextView) layout.findViewById(rIdText);
    text.setText(textToShow);
    
    Toast toast = new Toast(ctx);
    toast.setDuration(Toast.LENGTH_LONG);
    toast.setView(layout);
    toast.show();

  • Animaciones: no tienen su finalidad directa en notificar al usuario, pero en Tiendatek probamos qué tal quedaría una animación shake que agitase el total de una venta cada vez que el usuario añadía un producto. De este modo el usuario era consciente de dónde repercutía su acción y por otro lado simulábamos un efecto de añadir dinero.

Debemos tener cuidado a la hora de notificar al usuario, a lo largo de nuestra experiencia hemos observado los siguientes puntos clave:

  • Homogeneidad. En el caso de Tiendatek, al ser una aplicación de contabilidad decidimos pintar las cifras/mensajes en relación con la dirección del dinero. De este modo estamos educando la vista del usuario. De un rápido vistazo sabrá el sentido de una operación.
  • Bloqueante. A lo largo de la vida de la aplicación hemos ido cambiando notificaciones dependiendo de si se necesita bloquear el hilo principal o no.
  • Claridad en los botones de respuesta. No podemos sacar un pop-up bloqueante informando de algo con un botón de respuesta “SÍ”. Este tipo de situaciones pueden desorientar al usuario.

Para terminar de recorrernos las notificaciones en Android, nos queda hablar de las luces LED y de los sonidos; estos últimos los hemos usado en Tiendatek para cuando un producto es leído por el lector de códigos de barras. Quizás Jose en un futuro post nos puede contar como añadir sonidos a una aplicación Android.

Waterfall vs SCRUM vs Kanban (I)

Ha llegado la hora de profundizar un poquito más en la pequeña historia de Frogtek.

Cuando a finales de 2008 se empezó el desarrollo de un primer prototipo la situación era la siguiente. Un CEO que vivía en Nueva York, que quería crear una herramienta en un teléfono móvil para ayudar a los tenderos de países emergentes (México, Colombia) a llevar la contabilidad y un par de programadores en Huesca y Zaragoza (España) que en sus ratos libres aprendían a programar para Android. Interesante panorama, y no porque CEO y programadores estuvieran deslocalizados o Android fuera una plataforma en pañales, ni nada por el estilo… si no porque la probabilidad de que el bueno de David diseñara algo remotamente útil para un comerciante de Bogotá y lo especificara sin ambigüedad para su desarrollo en España era exactamente igual a cero. Sin embargo, se intentó. Ahí va una de waterfall…

Waterfall (o cascada) es la metodología clásica industrial que define distintas fases secuenciales a la hora de implementar un producto. Simplificándolo mucho sería algo así como:

  1. Planificación y análisis
  2. Diseño
  3. Implementación
  4. Test

Qué fácil ¿no?. Pues no. ¿Y por qué no?. Pues como diría nuestro amigo Medinilla:

porque el software no es un tornillo“.

Parece una afirmación de perogrullo y doy fe de que esgrimida delante de cualquier grupo de estudiantes de ingeniería provoca una media sonrisa que bien puede venir a querer decir “cada día traen a tipos más raros a dar charlas” o “eso lo he entendido”, una de dos. Para los más curiosos: el software no es un tornillo porque, y que no se me enfade ningún ferretero (seguro que el mundo de los tornillos es también complejo y está lleno de magia y pasión), los tornillos son “fáciles”. Cuando uno dice “tornillo” todo el mundo piensa en algo más o menos parecido y si además le añades las palabras “cabeza plana”, “4 mm de sección”, “paso de rosca de 1 mm”, “dextrógiro”, “de latón”… seríamos incluso capaces de construir tornillos idénticos de forma totalmente independiente (el que sepa como diablos se hace un tornillo, claro, que no es mi caso). Lo curioso es que, si bien todos parecemos estar más o menos de acuerdo en que “el software no es un tornillo”, intentemos aplicar el mismo método de fabricación para un tornillo que para… pongamos… ¿Facebook?.  😉

Pero volvamos al caso de Frogtek. Nuestro intento de crear un documento de requisitos para TiendaTek (nuestra caja registradora inteligente para teléfonos móviles) vía Waterfall-Cowboy (¡gracias por la corrección Pablo!) reunía todos los ingredientes para un fracaso sin paliativos…

  1. Sistema complejo de describir, ¿alguien ha intentado describir en un word y sin ambigüedad ninguna Facebook?, pues una caja registradora no es mucho más fácil.
  2. Producto final desconocido, como toda start-up que se precie de serlo una cosa es la idea original y otra lo que alguien acabe comprándote.
  3. Cliente remoto, ya no es que cambie de idea, es que ni siquiera es único, son millones, en países exóticos y lejanos y con prácticas y problemas que ni aquí, ni en Estados Unidos podemos entender.

… así que el análisis en cuestión no pasó de la versión 0.9. Enseguida, cansados de actualizar un documento infumable que siempre estaba obsoleto decidimos (o más bien David “el devora blogs” decidió) que tenía que haber una manera mejor de hacer las cosas. Una manera que no se basara en intentar adivinar qué necesita un cliente que desconoces, y que no planificara el trabajo de varios meses en base a dicha esotérica “adivinación” (interesante temática para un post, por cierto). Se trataba principalmente de no trabajar en balde… nos gusta programar, pero no tanto.

To be continued…

Servidor de desarrollo

Servidor de desarrollo

Os presento a nuestro servidor de desarrollo: DarwinFrog.

Debido a nuestra pasión por la integración continua, las revisiones de código, las herramientas de calidad y los tests automáticos; el pobre servidor está pluriempleado.

A modo de recuento las herramientas que habitan nuestro servidor y nos ayudan en nuestras tareas diarias son:

  • Hudson servidor de integración continua, lleno de plugins para adaptarse al desarrollo en Android y Gae.
  • Subversion en estos momentos nuestro sistema de control de versiones, estamos pensando migrar a algo más moderno como Git o Mercurial, pero no encontramos el momento adecuado.
  • Sonar plataforma de control de calidad del código, muy completa y visual.
  • Review Board herramienta de revisión de código muy útil y fácilmente enlazable con Subversion y otros sistemas de control de versiones.
  • Nexus gestor de repositorios muy útil para almacenar artefactos propios generados por Maven y así no tener que preocuparse de las versiones de las librerías, ni de las dependencias.
  • Seleniumhq plataforma para realizar tests funcionales web, versátil y fácilmente integrable con Hudson. Permite grabar los test de forma muy sencilla desde firefox entre otros.

En próximos posts intentaremos entrar en más detalle y contaros más a fondo como utilizamos y para que cada una de las herramientas.

Antiguas entradas