Developing Frogtek

El blog del Departamento de Tecnología

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

Frogtek en las noticias

Hoy es un gran día para frogtek. Si ayer nos sorprendía la aparición de la oficina de Huesca en el Telediario de Televisión Española, hoy Boris nos despertaba con la buena noticia de que nuestros compañeros de Colombia salían en las noticias CaracolTV.
Sin duda dos muy buenas noticias, y una gran alegría y orgullo para todos nosotros que vemos cómo poco a poco vamos “haciendo ruido” 🙂

Video de Caracol TV | Aquí
Video de TVE | Aquí (minuto 22:50 en adelante)

Ganador de la 1ª Edición del West Cerdito Story Awards

[Si no sabes de qué va esto del cerdito te remitimos a uno de nuestros posts anteriores]

Bueno, basta de intriga. Nuestro primer ganador ha sido…

(redoble de tambores)

Javier Linares Villuendas, más conocido como “Maestro Linares“. Él solito y en apenas dos meses se hizo la friolera de 30 US y 21 Bugs, alcanzando la meta de los 50 post-its con bastante ventaja sobre el segundo.

Aquí lo vemos recibiendo el premio (es el de la derecha, el de la izquierda es sólo la azafata) consistente en:

  1. El derecho a decidir qué se hace con el bote acumulado, la ingente cantidad de 31.65€… me parece que no llega para el anhelado humidificador, pero ya queda menos. Por cierto, que aún estamos esperando su decisión
  2. Una pegatina en forma de estrella para su monitor. Si los campeones del mundo la tienen, nosotros no vamos a ser menos.  🙂
  3. Un viaje de ida y vuelta al stand de Frogtek en el próximo SIMO Network. Es decir, 3 días currando como un ca… mpeón (como no podía ser menos, claro).

Nos consta que en Fuentes de Ebro están meditando hacerle hijo predilecto.

La 2ª Edición del West Cerdito Story está ya en marcha… ¿quién será nuestro siguiente campeón?.

Rework, de Jason Fried y David Heinemeier Hansson

Por más que lo pienso no puedo dejar de alabar este libro: Rework, de 37Signals, compañía de software y creadores de Ruby on Rails (entre otros productos).

El libro es tremendamente incisivo, en el aspecto de que no tiene problemas en ir a degüello con los problemas del día a día dentro de una empresa. Utiliza un lenguaje simple y muchas veces llega a adquirir un tono de complicidad con el lector.

Está estructurado en forma de capítulos cortos (poco más de una hoja) con títulos realmente impactantes. Para muestra un botón de algunos de ellos:

  • ASAP is poison. En una empresa, realmente todos querrían que algo se terminara cuanto antes posible. Además es inflacionario: cuanto más lo uses, menos valdrá.
  • Own your bad news.  Si algo sale mal, sé el primero en anunciarlo. Por lo menos no dependerás de la desinformación que puedan publicar otros medios.
  • They’re not thirteen. ¿Por qué poner permisos a los empleados para hacer cosas? Permíteles tomar decisiones, de lo contrario estarás poniéndoles una pegatina de “no me fío de ti”.
  • The best are everywhere. La geografía no importa. Contrata a los mejores estén donde estén. Aquí en Frogtek seguimos este patrón a rajatabla 🙂
  • Marketing is not a department. Si te encuentras en una empresa y tienes un producto final, entonces ¡toda tu empresa es marketing! Todos están trabajando para marketing a tiempo completo (o deberían).

Os recomiendo encarecidamente a todos aquellos que trabajéis en una empresa (en cualquier tipo de cargo). Además es muy fácil de leer y sin duda os hará pensar, que es el objetivo principal que debería tener un libro sobre empresas.

Cadenas html con estilos en Android

Investigando un poco más sobre Android, hemos descubierto, que no solamente es posible trabajar con textos planos, sino que también, te permite insertar e interpretar cadenas html.

A continuación mostramos un ejemplo de cadena html perfectamente codificada y almacenada en la carpeta res/values:

Este texto es<font color='red'>Rojo</font> y <font color='blue'>Azul </font>

Un forma simple de mostrar el fragmento de texto anterior es a través de las siguientes lineas de código:

String text = getResources().getString(R.string.text);;
CharSequence styledText = Html.fromHtml(text);
((TextView) findViewById(R.id.outputText)).setText(styledText, TextView.BufferType.SPANNABLE);

Donde como resultado obtenemos:

Este texto es Rojo y Azul

Para mas información, recomendamos consultar la documentación de Android.

El findViewById(), y lo cargante que puede llegar a ser

Si no vienes del post introductorio, quizás te gustaría leerlo.

Segundo asalto. La aplicación sigue estando lenta, y no sabemos muy bien por qué. Ya no hay tantos onMeasure(); sólo los “necesarios”. Pero hay una nueva función que aparece en los primeros puestos de nuestro querido traceview: findViewTraversal(). ¿Y quién llama tantísimas veces a esta última? pues findViewById().
Y es que esta función, es la que enlaza un recurso de la interfaz de usuario de una aplicación, con una variable en nuestro código. O simplemente se encarga de acceder a ese recurso para cambiar una de sus propiedades.

Supongamos, pues, que tenemos un layout con una veintena de widgets entre layouts, Buttons, EditText, TextView, ImageView… Y que en un momento dado del ciclo de vida de la actividad, tenemos que acceder a uno ó varios de ellos para cambiar sus propiedades. Podemos acceder a ellos del modo:
((EditText) this.findViewById(R.id.edittext_cliente)).setOnClickListener(…);
Aunque también podemos guardar el valor que devuelve la función findViewById() en una variable, o variable miembro de la Activity para operar con ella varias veces a lo largo del citado ciclo de vida.

¿Cuál es la diferencia? y ya que estamos ¿cuál era nuestro error? Pues que cada vez que se llama a la función findViewById(), android recorre todo el árbol jerárquico del Layout que hemos definido previamente en XML, en busca del recurso al que queremos acceder. Como ya habréis averiguado, el costo de esa operación es muy alto si el control a encontrar es de los últimos en el árbol, o si hay muchos niveles de layouts anidados, o simplemente queremos cambiar el valor de una de las propiedades de ese recurso bastantes veces a lo largo del ciclo de vida de la aplicación.
Si a esto le sumamos que el cambio en una de las propiedades de un EditText (por ejemplo), afecta a cinco o seis widgets más; y a todos accedemos del modo findViewById(), estamos vendidos.

La solución para una Activity, cuyos widgets han de ser modificados con bastante asiduidad es el guardar el resultado de la función archinombrada en este post en variables miembro, a las cuales se accederá sin tener que recorrer (findViewTraversal()) todo el árbol jerárquico “n” veces, con la consiguiente pérdida de velocidad en la transición de un estado a otro de la Activity.
Eso sí: Podemos prescindir de estas variables miembro si accedemos una, y sólo una, vez al widget en cuestión.

Esto también hay que grabarlo a fuego en la mente.

El momento cerdito…

Junio de 2010, una sesión cualquiera de la CAS2010, el vehemente speaker azuza a las masas de developers ansiosos de ser más ágiles que nadie:

“Nosotros teníamos un bote para quien rompía la build. Si rompías la build, un euro al bote. ¿¿Vosotros no hacéis eso?? Lo malo no es el euro, lo malo es el escarnio público. Mira el ágil, ahí está poniendo otro euro. El escarnio público es un gran catalizador…”

Rodrigo Corral, CAS2010

… Y nosotros no hacíamos eso :S. ¿Necesitábamos nuestra pequeña dosis de escarnio público?, ¿se rompían demasiadas builds?, ¿se fallaban demasiados ATs fáciles?, ¿iba Rodrigo a aparecer por la oficina cualquier día a infligirnos nuestra dosis de escarnio personalmente por no tener bote?. No podíamos permitirlo.

Dicho y hecho. Visita al chino más cercano, compra de una genuina hucha con forma de cerdito y creación de dos tablas más para colgar en la pared. Una con las tarifas:

  • Build rota – 0,5€ de multa para el programador
  • User Story que no pasa los AT que le hace el tester – 0,5€ para el programador
  • User Story que no pasa los AT que le hace el Product Owner – 0,5€ para el tester
  • Stand-up meeting que no empieza antes de las 9:00 CET – 1€ para el KanbanMaster

La otra se hizo necesaria enseguida, ya que la gente se suele gastar el suelto en la máquina de café (edito, acabamos de comprar una Nespresso): la tabla del cobrador del bug, donde apuntamos lo que debemos, para pagarlo una vez recuperada la liquidez.

Misión cumplida, escarnio conseguido. Todo el mundo se preocupa de hacer un poquito mejor su trabajo con tal de ahorrarse medio cochino (por lo del cerdo) euro. ¡Genial!. Y encima acumulamos un pequeño (esperemos) bote… ¿qué hacemos con él?. La resolución de este problema, qué hacer con el cochino bote,  ha supuesto la primera contribución de Frogtek a la metodología Ágil, la primera técnica inventada por nosotros que hemos integrado en nuestro proceso sin demasiado esfuerzo, ni problemas (y si resulta que ya estaba inventada espero que no venga nadie a quitarnos la ilusión).

Volvamos al problema. Los residuos que nuestro proceso de desarrollo generaba eran, en ese momento, dos principalmente: un montón de post-its bicolores (rosa bug, amarillo US) y un bote. El bote crecía internamente dentro de la barriga de nuestro amigo el cerdito y los post-its se acumulaban en la última columna de nuestra omnipresente tabla de kanban y amenazaban con echar abajo nuestra moderna pared de cristal. Solución: crear otra tabla en la pared (por paredes será…) con una fila para cada programador, una vez que una User Story (US) o un Bug está definitivamente acabada se pega en la fila de programador responsable, de forma que la barra de cada uno de ellos va creciendo a un ritmo proporcional a su “efectividad” y el primero que llega a 50 (o a 100) decide qué se hace con el bote. Una imagen vale más que mil palabras:

Más gráfico no puede ser. Esta tabla tiene un montón de cosas interesantes que ofrecer:

  • Si le pones separaciones temporales te da información sobre el avance parcial.
  • Fomenta la competitividad sana dentro del equipo.
  • Da en un vistazo una idea de la salud del proyecto (mucho rosa malo).
  • Ayuda a detectar problemas, como US demasiado largas o gente trabajando sin US.

Si el Kanban Master, es decir un servidor, se molesta en contar semanalmente los post-its de la pared se pueden obtener fácilmente gráficas de este estilo entre otras muchas.

Que muestra el número absoluto de US y Bugs finalizados semanalmente.

Que muestra el tiempo que dedicamos cada semana a US y a Bugs, (sí aproximamos la duración de 4 bugs a la de 1 US, sabemos que no es muy exacto en el corto plazo pero esperamos que sí a medio y largo).

Pero no se queda aquí nuestra innovación. Tras ver que este sistema funcionaba bastante bien, ya que es fácil y llevadero y la información que proporciona muy relevante. Decidimos darle una vuelta de tuerca más, ya que aunque estábamos reuniendo un pingüe bote no teníamos información de cuales eran los problemas que hacían que ese bote creciera y creciera y se convirtiera en el oscuro objeto de deseo del primer programador que acumulara 50 post-its. Así que introducimos unas pequeñas modificaciones. Las multas no han cambiado, sin embargo cada vez que una US/Bug no pasa el proceso de Test apuntamos los nombres de los responsables en el post-it de forma que:

  • Si la US se echa para atrás porque el Tester no la aprueba, se apunta en el post-it al programador en cuestión (que además tendrá que pagar).
  • Si la US se echa para atrás porque el Product Owner no la a prueba, se apunta en el post-it al tester y al programador (y es el tester el que paga la multa).
  • Si la US se echa para atrás porque el Product Owner no se había explicado bien o mete nuevos ATs, se apunta al Product Owner (desgraciadamente este no paga porque alimentar a nuestro cerdito vía Paypal nos parecía un tanto complicado, notar que nuestros POs está en sudamérica).

Con todo esto el Kanban Master puede hacer recuento todos los lunes y dibujar gráficas como ésta.

De donde se pueden extraer la siguientes conclusiones:

Si la mayoría de cerditos recaen del lado de los developers (proporcionalmente a su número claro) hay que buscar la manera de mejorar el código que creamos o de que estos aprendan a leer los ATs. Si la mayoría de cerditos recaen del lado de los testers, quizá sea que tienen mucho trabajo y no les da tiempo de probar como Dios manda, o que tienen que concienciarse para ser más minuciosos. Si la mayoría de cerditos son para los POs quizá hay que enseñarles a escribir, o necesitan ayuda para definir las US porque tienen mucho trabajo, o aún están en proceso de adaptación (relacionarse con programadores vía redacción de Acceptance Test no es tarea fácil). Lo bueno de saber que tienes un problema y dónde está es que puedes intentar arreglarlo.

En el próximo post desvelaremos quien ha sido el primer ganador de nuestra particular competición y cuales sus premios.

Saludos!.

PD: El ánimo de esta técnica es la de motivar al equipo, dar trasparencia y detectar problemas o cosas mejorables. El objetivo de la competición es siempre premiar y nunca censurar. Somos conscientes de que no todo el mundo compite en igualdad de condiciones ya que ningún proyecto es comparable al resto y porque el tamaño de las US y Bugs no siempre es homogéneo. No nos importa porque lo único que tratamos de hacer es pasarlo bien mientras trabajamos, nos conformamos con que podamos decir que hemos montado un sistema que se ajusta a nuestra realidad a medio y largo plazo.

Diseño de layouts XML, sucios pero eficientes, en android

Si no vienes del post introductorio, quizás te gustaría leerlo.

Bien, pues a medida que añadíamos nueva funcionalidad a la aplicación en la tablet, experimentábamos una lentitud tremenda en alguna de las actividades que abríamos. No era normal que si en el teléfono, el mismo layout funcionaba perfectamente, ¿por qué al unir dos layouts en uno sólo, pero más grande, vaya tan lento? Respuesta: no hay nada que el traceview no solucione. Nada.

Rápidamente, Julio comenzó a ver que había miles de llamadas a una función nativa de android que se llama onMeasure(). La misma, se encarga de que cada vez que hay que posicionar un widget dentro del layout, hacer las medidas necesarias de lo ya presente en el mismo para así determinar dónde debe de ir colocado. ¿Y qué problema hay con esto? Pues que si tu layout tiene muchos widgets, y estos widgets tienen algunas de sus propiedades (como el layout_width, o layout_height) con valores wrap_content o fill_parent, todo resultará en un festival de onMeasure(). Creo recordar, que el 90% del tiempo de carga de una pantalla ineficiente nuestra, se lo llevaba esta función. Obviamente, pasamos de medio segundo para cargar una pantalla determinada en el teléfono, a 2 ó 3 (incluso más) en la tablet.
Por lo tanto, uno de los nuevos mandamientos que hay que grabarse a fuego es que: siempre darás medidas a tus widgets (Button, TextView, Layouts, EditText, etc), en lugar de que las decida android. Siempre, a no ser que sea estrictamente necesario; que alguna vez lo es.
Este es el primer paso para que la aplicación fluya un poquito más rápido que antes. Pero sólo un poquito.

¿Qué, que aún no hemos ensuciado el layout? Bien, pues este punto tiene que ver con el nivel en que un widget se encuentra anidado. Podemos tener un layout muy sencillo, con un RelativeLayout y dos Button dentro, o podemos tener algo como esto (o peor). Es por esto lo que un día dije en la oficina. Somos unos barrocos.
Por lo tanto, desde frogtek recomendamos encarecidamente que, a poder ser, se tenga un RelativeLayout padre con todos sus hijos al mismo nivel. Si se tienen 4 o 5 widgets en el layout, serás afortunado; si tienes 30 o 40 como en alguno de nuestra tablet, puedes volverte loco buscando uno en concreto en el Outline de eclipse. Cierto es que queda todo mucho más ordenado si vamos anidando widgets dentro de Layouts, pero se pierde rapidez al cargar, ya que también hay muchos más onMeasures() que si estuviesen todos al mismo nivel. Y traceview no miente.

Por lo tanto, el primer paso para agilizar la carga (o recarga) de una pantalla, pasa por dar medidas a todo widget al que podamos dar medidas absolutas, e intentar que nuestros layouts sean lo menos barrocos posibles en cuanto a ordenación jerárquica se refiere.

Consejo extra que se me ocurre mientras escribo: si utilizas el LayoutInflater para cargar layouts dentro de otros, tener un layout con uno o dos niveles de anidación ayudará mucho. Nosotros, que tenemos layouts dentro de layouts, y de nuevo dentro de layouts (por necesidad), lo hemos notado.

Optimizar una aplicación android (Introducción)

Hacía como mes y medio que quería escribir sobre este tema, pero me habría precipitado ya que desde esa fecha hasta ahora hemos aprendido mucho más sobre la optimización de una aplicación para android; aunque aún no quedan muchos conocimientos por adquirir.

Como ya hemos contado alguna vez, desde hace casi dos años, desarrollamos nuestro producto para teléfonos; teléfonos con una resolución fija. Y durante este verano, hemos dado el salto a una tablet. Suerte que todo el núcleo de la aplicación lo teníamos bien separado en un .jar. Por lo que el 2% del tiempo lo hemos invertido en retocar un poquito el núcleo, y el 95% restante ha sido armar una interfaz de usuario muy bonita, pero que nos ha dado bastantes quebraderos de cabeza, y que voy a intentar plasmar en una serie de posts.

Tras unas cuantas iteraciones y un empujón espectacular, teníamos muy avanzada la versión para la tablet. Pero el cambio de una pantalla de 320 x 480, a una de 800 x 480 conlleva problemas de memoria y de rendimiento (con un hardware superior al del teléfono, todo iba mucho más lento). Por que no es oro todo lo que reluce. Con un buen procesador, y bastante memoria no todo va a funcionar como pensabas. Por lo menos, en android. Nos hemos rascado mucho la cabeza, hemos sufrido, pero finalmente hemos aprendido muchas cosas; sobretodo de nuestros errores.

Es por ello, que nos gustaría compartir con vosotros los siguientes temas:

A medida que vayamos redactando la serie de posts, se actualizarán los puntos con enlaces a las URLs.

Frogtek canta a los Beatles

Compra ya el cd de “Los desarrolladores de Frogtek cantan a los Beatles”Beatles
con todos sus grandes éxitos:

  • Let it build
  • All you need is code
  • Submit and shout
  • Here comes the run
  • I want to hold your bug
  • Pair together
  • A .jar day’s night
  • y muchos más…

Los 10 mandamientos de Java

Quizás todavía hemos hablado poco de Sonar, pero es necesario indicar que se trata una de las herramientas indispensables a la hora de crear código elegante. Básicamente, esta utilidad nos permite analizar nuestros proyectos en busca de código poco eficiente o mejorable, ordenando estas infracciones (suena mejor que violaciones) por su gravedad (blocker, critical, major, minor e info).

Con esfuerzo, hemos conseguido eliminar todas las infracciones críticas de nuestros proyectos, pero como sabemos que volveremos a tropezar dos veces con la misma piedra, necesitábamos algún tipo de recordatorio que nos permitiera tener siempre en mente el no volver a cometer esas infracciones.

De ahí surgió la idea de crear una tabla con los diez mandamientos de Java. Aquí tenéis la versión final. Explicaré cada punto en detalle.

Los 10 mandamientos de Java
I. Thou shall not access non-static variables in a static manner.

Esta infracción se repetía bastante en nuestro código. Si tenemos un método estático , no debería poder acceder a variables que no están pensadas para llamarse de forma estática. El compilador lo permitirá, claro, pero manda al garete la filosofía de los métodos estáticos.

II. Do not write a static variable from an instance method. Ever.

Parecida a la anterior, pero al contrario. Si tenemos una variable estática, no deberíamos poder escribirla desde un método perteneciente a un objeto instanciado. Sirva de ejemplo:

private static String mTitle;
...
public void showDialog(String title, String message) {
   mTitle = title;

III. Thou shall not leave empty if-else/switch statements.

¿Cuántas veces habrá pasado? Dejamos un todo en el if y asunto resuelto. Pues a partir de ahora, pecado mortal.

if (item != null) {
   newPurchase();
} else {
   // no purchase yet
}

Aunque no lo pone, esto también se aplica a los bucles vacíos.

IV. Thou shall not repeat code in a if-else/switch statement.

A veces por dejadez, mantenemos dos bloques de un condicional exactamente iguales. Veamos un ejemplo con un switch:

switch(gafas){
   case 1: return "de lejos"; break;
   case 2: return "progresivas"; break;
   case 3: return "del cerca"; break;
   default: return "de lejos"; break;
}

Podría modificarse quitando el caso 1 o fusionándolo con el default.

V. Thou shall not leave a private method not being called from anywhere.

Sencillo: no creemos métodos que no sean utilizados en ninguna parte. Si el título del metodo tiene un rayica amarilla, mal asunto. Siguiente.

VI. Remember to not null-check a value which is already null.

Si estamos seguros al 100% de que algo tiene como valor null, no tiene sentido hacer una comprobación. Lo mismo para el caso contrario: si es imposible que una variable tenga valor null, resulta redundante el comprobarlo.

VII. Thou shall not use short variable names.

Pecadores todos aquellos que utilizáis nombres de variables como “cursor c”, “RelativeLayout rl” o “String s”. Quedan excluidas las variables de iteración dentro de un bucle.

VIII. Do not take the visibility of variables in vain

Qué bonito sería el mundo si todas las variables fueran public. Nos ahorraríamos más de un disgusto. Pero si una variable sólo se utiliza dentro de el entorno de una clase, debemos declararla como private, o arder en el infierno. Lo mismo con protected, claro.

IX. Remember to write javadocs and keep it holy.

Método que dejamos sin Javadoc, 10 flagelaciones.

X. Avoid duplicate literals, if it is repeating, create a variable.

if (numPiscinas == 1) {
   show("mensaje", 1);
} else if (numPiscinas == 2) {
   show("mensaje", 2);
} else if (numPiscinas >= 3) {
   show("mensaje", 4);
}

Si la cadena “mensaje” es usada en el código continuamente, mejor escribir una variable propia con la cadena, que seguro que nos resuelve la vida.

Y eso es todo. Podemos crear código sin hacer caso de estos mandamientos, y obtendremos un buen resultado. Pero seguro que si los seguimos a rajatabla, adquirimos unas costumbres de programación muy saludables. Por supuesto, estos puntos son cuestionables, no se trata de los más críticos, sino simplemente de los que más suelen repetirse en nuestro código. Os animo a que elaboréis vuestra propia lista de mandamientos y la colguéis bien alta para tenerla siempre en mente. Y para acabar, me despediré con una frase de Charles Reade:

“Siembra un acto y cosecharás una costumbre. Siembra una costumbre y cosecharás un carácter. Siembra un carácter y cosecharás un destino.”

Antiguas entradas