Pokemon Go — A Developer Review

No hay duda que Pokemon Go esta dando que hablar. Batiendo records. Haciendo a Nintendo super rentable etc. Pero no vamos a hablar de eso si no de la parte técnica. ¿Tan bueno es?

Lo bueno

Empecemos hablando por las bondades del juego. Es entretenido! :), apela a la nostalgia de una generación que jugó a los viejos juegos o veía los dibujos animados mientras merendaba.

A nivel técnico el juego no me ha dado mayores problemas. La interfaz es bastante intuitiva y simple. Vamos, no hay mucho que hacer más que caminar y tirar unas pelotitas (a.k.a Pokebolas :).

Lo malo

Para mi que venía jugando Ingress, otro juego similar de la misma empresa desarrolladora, el juego me suena conocido. En Ingress uno debe tomar portales, caminando por el mapa y yendo a ciertas ubicaciones y apuntar con la cámara para sacar recursos.

En Pokemon go uno tiene que ir a las Pokeparadas, caminando por el mapa y yendo a ciertas ubicaciones para sacar recursos. ¿No lo había escrito ya? 🙂

Las Pokeparadas están exáctamente en los mismos lugares que los portales de Ingress y se nota la falta de innovación en la forma de elegir los puntos de interés.

Lo otro que todavía tiene de malo el juego es que le faltan muchas características : no están todos los Pokemones, no se puede hacer batallas 1 vs 1 salvo en los gimnasios, no se puede desafiar amigos en un asado, cosas de hombres, vamos :).

Lo feo

El punto que menos me gusta es la experiencia de ‘Realidad Aumentada’, se ve muy trucha. Cuando enciende la cámara y te muestra el Pokemon, éste está en el aire, no reconoce las superficies (miren cualquier demo de Vuforia y van a ver que podría ser zarpada la RA!).

En las pruebas que hicimos de a varios, no vemos todos el mismo Pokemon en la misma ubicación. Sería demasiado perfecto? Yo creo que sería interesante :). Quizás fue mala suerte, pero es feo que esa experiencia no ande.

El Balance

Para el bombo que habían hecho creo que el juego deja desde el lado técnico mucho que desear. Desde el punto lúdico a mi al menos me gustó.

Solo espero en el futuro evoluciones hacia una experiencia de realidad aumentada más rica

“Funciona” no es suficiente.


No es raro en esta profesión, al revisar el trabajo de otro encontrarse con algo que no es del todo semánticamente correcto o que puede escribirse de mejor manera. Tampoco es raro que nos digan “pero así funciona”. Funciona no es, o no debería al menos, ser suficiente.

En el desarrollo de software existen muchos otros factures a considerar a futuro que no siempre tienen que ver con el funcionamiento actual de la aplicación : ¿el código se entiende?, ¿es eficiente?, ¿es fácil de extender si debemos agregar funcionalidades?. Quizás el aspecto más importante desde el punto comercial es que tanto cuesta corregir un error detectado, ya que en códigos escritos de manera pobre, corregir un error y la posibilidad que aparezca uno nuevo suele ser mayor en los casos donde no se tiene una buena disciplina.

En las siguientes secciones trataré de comentar lo que me ha servido a lo largo de los años y qué herramientas podemos utilizar. Algunos ejemplos serán específicos de Android, pero se pueden extrapolar a cualquier tecnología.


Métricas, métricas y más métricas

Un aspecto importante para saber dónde estamos parados y hacia dónde vamos es la utilización de métricas en nuestro código. Estas métricas pueden ser muy variadas, desde contar a mano cuántas líneas de código hay por archivo, clase o método, hasta medir la complejidad ciclomática de nuestro código.

Las métricas deben ser una herramienta que nos orienten, no que guíen nuestro desarrollo. Es decir, no deberían condicionar si o si la forma de escribir una porción de código porque la métrica da peor en ese caso.

Esto hace que las métricas en si mismas no sean lo importante. Lo que nos debería importar es la tendencia de las mismas. Para poder medir tendencia entonces debemos poder consultar un histórico, por lo que con cierta regularidad deberíamos calcular esas métricas, anotarlas y ponerlas en un gráfico.

Siempre que la tendencia sea negativa es un buen signo, que se mantenga no está mal. Si la curva crece con pendiente leve en un período corto y luego se estabiliza o baja no debería ser preocupante.

Nuestros puntos de alarma deberán ser crecidas de más de un 30/40% de golpe entre una medición y otra. En general cuando hay picos de crecimiento es porque se está trabajando en alguna característica nueva y todavía no se empezó la etapa de estabilización. Lo importante es atacar el problema en ese momento y ver donde podemos mejorar.

Automatización : la clave para no abandonar

En la teoría esto de las métricas es fantástico. Hasta que llega nuestro Manager o Jefe y nos dice “pero teníamos que salir ayer a producción” y todo se va al diablo :). Escribimos lo que podemos para que “simplemente funcione”, no tomamos métricas y a veces ni probamos :).

Luego de dos o tres veces que salimos del apuro nuestro código seguramente ya sea inmanejable y si calculábamos las métricas a mano perdimos historial importante para ver la evolución.

La automatización de esta tarea es crucial, ya que nos permite ir calculando de manera automática y de manera periódica la salud del proyecto.

Para automatizar es que existen los servidores de “Integración Continua” (o CI de sus siglas en inglés) como Jenkins o Travis. Estos son lo suficiente flexibles para ser configurados según nuestras necesidades y contienen cientos de plugins que nos harán la vida más fácil.

En el caso de Jenkins podemos usar los plugins de “Android Lint” y “Report violations” para recolectar métricas y que nos haga un gráfico de la evolución de las mismas.

Personalmente no me gusta que el proyecto se marque como “fallado” si las métricas no están en cero. Prefiero simplemente un aviso de que la aplicación está “inestable” y definir yo si tengo un problema o no.

Métricas en Jenkins

Como punto final, queda definir en cada caso cada cuánto corres las métricas. Podría ser por hora, a una hora fija, por semana, etc. Dependerá del proyecto.

Yo prefiero calcularla en “tiempo real” cada vez que alguien sube código al proyecto. Para eso solo debemos configurar el servidor de CI para que detecte que hay un nuevo código, lo baje y corra las métricas.

Las Herramientas

Para ir terminando por hoy vamos a mencionar algunas de las herramientas que podemos usar para medir métricas :

  • FindBugs : Java/Android. Detecta errores comunes y recomienda buenas prácticas
  • PMD : Java/Android/Objective-C. Analiza el código en busca de variables sin uso, condiciones que se pueden simplicficar, objetos que estamos creando de más, etc.
  • Lint : Existe un programa “lint” casi por cada lenguaje/framework que existe. Existen desde 1979, usalo :)!
  • Codenarc : Groovy/Grails. Permite analizar malas práticas, errores de estilo, etc.
  • Checkstyle : Java/Android. Chequeos básicos para escribir Java con buenas prácticas (nombres de variables, organización del código, etc).
  • Clang Static Analyzer : Objective-C/iOS. Similar a Checkstyle.

Siempre se puede mejorar …

Para cerrar, simplemente eso. Siempre se puede mejorar. Lleva tiempo? Al principio un poco, si. Pero una vez que el camino está sentado el proyecto avanza solo.

A medida que veamos los warnings de las herramientas iremos recordándolas, entonces al escribir el código antes de todo ya lo haremos pensando en buenas prácticas, minimizando el problema desde el principio.

Por último y no por eso menos importante, nuevamente decirles que estas herramientas deben ser una guía!, no deberíamos buscar el Santo Grial de tener en cero nuestras métricas, eso podría llevarnos a lugares peores que no tener métricas. Vean tendencias y saquen conclusiones 🙂

Hacer Aplicaciones Android Mantenibles

Una de las cosas más complicadas a lo largo del tiempo es poder mantener el código fuente de una aplicación Android en un nivel de simplicidad que nos permita a futuro introducir nuevas mejoras, arreglar errores de manera más simple o solamente poder leer el código y decir “ah, si, esto es lo que hace acá”. No siempre lo logramos, ya sea por impericia (todavía no sabemos hacerlo mejor) o por tiempo (nos apuran y en lugar de pensar la mejor manera simplemente escribimos el primer código que se nos ocurre para lograr sacar en tiempo la aplicación).

En general los problemas de impericia se solucionan con capacitación, lectura y pruebas. Es mi idea ir contando varias soluciones que vengo aplicando ya hace un tiempo en cuanto a libraría, patrones y técnicas que nos ayudan día a día a crear mejores productos de software.

En los problemas de tiempo lamentablemente no puedo ayudarlos, ya depende de cada organización y de quién está arriba de nosotros :), pero si sepan que teniendo un buen set de herramientas y saber usarlas, soluciona parte del problema ya que no deberíamos tener que alejarnos de nuestras buenas prácticas.

Para ir finalizando esta introducción, quiero contarles un poco de qué voy a hablar en futuras entradas.

Lo primero que vamos a tratar es cómo manejar el proyecto. Que herramientas podemos usar para medir “calidad”. Luego vamos a seguir con algunos patrones que nos serán de utilidad y bibliotecas que nos ayudarán a seguir esos patrones. Y para terminar vamos a hablar un poco de testing automatizado y que ventajas hay haber utilizado todo lo anterior.

No les puedo dar fechas exactas de cuando iré escribiendo sobre todo esto, pero si les quiero dejar un post en inglés por si quieren ir viendo de que se trata. Es apenas una ápice de lo que la comunidad Android está escribiendo sobre cómo deberían estar tratándose los desarrollos y cómo sumar calidad a tus aplicaciones.

http://artemzin.com/blog/android-development-culture-the-document-qualitymatters/

III Semana del Emprendedor Tecnológico Rionegrino 2015

La semana que viene voy a estar en la III Semana del Emprendedor Tecnológico Rionegrino 2015 presentando un proyecto en el que venimos trabajando hace unos meses con mi primo y unos amigos.

Lo que más me divierte de este proyecto es que no es software, sino un producto tangible, que por una vez en la vida se lo puedo tirar por la cabeza a quién lo critique 🙂 (con los DVDs podía hacerlo pero si justo tienen algo de filo puede ser mortal y no es la idea).

Luego del encuentro la idea es publicar la experiencia en este tipo de eventos, comentar que cosas interesantes vimos y que será del futuro de este producto que estamos desarrollando.

Por el momento, solo les dejo un montón de incógnitas 😛

Tablas rápidas para Grails

Si hay algo odioso cuando hay que hacer una interfaz de administración, es armar la lista para cada modelo del dominio para los AMBs. Esta semana me tocó mejorar el diseño para una aplicación grails, por lo que decidí ver como se podían generar “helpers” o TagLibs en nomenclatura grails.

El siguiente código genera usando bootstrap3 una tabla con paginado, botón de editar y eliminar de forma genérica:

package test

class ResourceTableTagLib {
    /**
     * Creates a bootstrap3 compatible datatable.
* * @emptyTag * * @attr list REQUIRED List of domain models to show * @attr count REQUIRED Total registers (for pagination) * @attr labels REQUIRED Comma-separated values for the columns headers * @attr columns REQUIRED Comma-separated of model attributes to show */ def table_for = { attrs -> def writer = out def list = attrs.list def count = attrs.count def labels = attrs.labels.split(/,/).collect { x -> x.trim() } def columns = attrs.columns.split(/,/).collect { x -> x.trim() } writer << '
' writer << '' writer << '' writer << '' labels.eachWithIndex { a, i -> writer << "" } writer << '' writer << '' writer << '' writer << '' list.eachWithIndex { a, i -> writer << " " writer << " " columns.eachWithIndex { c, j -> if (j != 0) { writer << "" } } writer << ' ' writer << '' } writer << '' writer << '
${a}
" writer << g.link(action: "show", id: a.id, a."${columns[0]}") writer << " ${a."${columns[j]}"}' writer << g.form(url: [resource:a, action:'delete'], method: "DELETE") { writer << g.link(class: "btn btn-default btn-sm", action: "edit", resource: a, "Editar") writer << " " writer << g.actionSubmit(class: "btn btn-danger btn-sm", action: "delete", value: "Eliminar", onclick: "return confirm('¿Eliminar curso?');") } writer << '
' writer << '
' writer << '
' def offset = params.offset as Integer ?: 0 def page_start = offset + 1 def page_end = Math.min(offset+10, count) writer << "
Mostrando ${page_start} a ${page_end} de ${pluralize(count: count, singular: "registro")}
" writer << '
' writer << '
' writer << g.paginate(total: count) writer << '
' writer << '
' writer << '
' } def pluralize = { attrs, body -> def plural = attrs['plural'] ?: attrs['singular'] + "s" out < 1 ? plural : attrs['singular'] ) } }

PD : Seguramente exista forma de sacar el nombre de columna desde el nombre del atributo del modelo, pero todavía no lo encontré.

Para usarlo simplemente basta con agregar en nuestro template :

10 hechos sobre los programadores que deberías conocer

El otro día leyendo el artículo “Ten hilarious programmers facts that only programmers can understand” me dí cuenta que muchas de las respuestas que doy siempre están reflejadas en estos simples hechos, por lo que decidí hacer una traducción libre y criolla del asunto. A continuación, mis “10 hechos sobre los programadores que deberías conocer

Hecho #0

Empezamos a contar desde 0, no desde 1.

Desde nuestros primeros pasos nos encontramos que todo lo que tiene “posiciones” arranca de 0, es por eso que se nos hizo costumbre.

Hecho #1

Los programas que usas, son como una cámara de una rueda de tu bicicleta.

Anda, se infla, rueda. Pero puede estar llena de parches, improvisaciones y manotazos de ahogado que tuvimos que agregar cinco minutos antes de la entrega para que parezca que ande como se había acordado. No te preocupes, en la próxima versión cambiamos la cámara por una nueva (y seguramente le meteremos más parches aún :D)

Hecho #2

El 35% de nuestro tiempo de trabajo se utiliza en pensar qué cosas podrías, vos, el usuario, hacer mal al usar nuestro programa.

Y tratar de evitarlo. Si tan solo pensaran como programadores …

Hecho #3

Irse a dormir con un problema en la cabeza, realmente puede derivar en una solución.

Nos ha pasado a casi todos, despertar de madrugada y sentarse en la PC a terminar de programar eso que no nos salió durante todo el día. Luego a seguir durmiendo 🙂

Hecho #4

Programar es Pensar, no Escribir.

Si me ves mirando el monitor sin hacer nada, o mirando Youtube, seguramente estoy pensando de qué disfrazarme para atender a un pedido ridículo :D.

Hecho #5

Un programador NO es un reparador de PC.

Que entienda que significa RAM, ROM, CPU no significa que sepa que le pasa al puto Windows! (más aún cuando hace años que uso Linux 🙂

Hecho #6

Somos noctámbulos. Supérenlo.

Nos gusta la noche, pero no en el sentido que están pensando, bueno, un poco ;). La noche trae paz, la paz trae momentos de reflexión, cuando pensamos, bueno, ya vimos en el 5to hecho, programamos (Nota del redactor, recordar que contamos desde cero, el 5to hecho, es el Hecho #4 :D!).

Hecho #7

Un padre puede matar a su hijo. Es legal. punto.

En una computadora, un programa (llamémoslo proceso) puede tener varios hijos (o hilos, o threads en inglés). Cuando el padre decide que no se va a seguir ejecutando, puede matar a sus hijos y terminar con toda ejecución.

Hecho #8

Mientras que a Uds no les interese la informática, no esperen que a nosotros nos interese el mundo real.

No me interesa la política, a quién vas a votar, quién va al bailando o quien le hizo un hijo a no se quién que es de no se donde!, salvo que quieras hablar de los beneficios de la computación cuántica, algoritmos evolutivos o de búsqueda de textos.

Hecho #9

Programar no es tan fácil como parece.

Pero dedicándole tiempo, todos somos capaces de hacerlo. Para más detalles los invito a ver code.org.

 

Volviendo a PHP

Hace fácil 5 años que no hago nada serio en PHP, empezando desde cero. Mayormente me ha tocado retocar cosas andando o parchar bugs boludos. Sin embargo el otro día tuve que hacer un demo chiquitito en PHP. El principal limitante era el tiempo, por lo que tenía que hacerlo rápido.

Al principio intenté el viejo HTML+PHP all-in-one con ifs $_GET, $_POST, etc. Una locura, no podía avanzar. Mi mente me decía “esto va en el controlador, esto en el view” :D. Borre todo y empecé de nuevo. Pensé dos segundos y dije “tiene que haber algo”. No, CakePHP no es ese “algo”. Era mucha config al pedo, bloated y cada vez que tuve en mi poder un site de Cake para poner en producción terminé a los cabezazos.

Googleando me topé con SlimFramework un micro framework para hacer apps (el Sinatra de CakePHP 😀 ?) y la verdad que dije “ah, mirá, en php también se puede programar como al gente”. No tiene ORM, solo un modo fácil de declarar rutas, con arguments y verbos REST (post, delete, put, etc) y un body para ejecutar la lógica.

Los templates son modulares, podemos llamar a otro .php que genera HTML o usar HAML, Smarty (dios que alguien de de baja este proyecto :P) o armar el propio. Un hola mundo :

get('/hello/:name', function ($name) {
    echo "Hello, $name";
  });
  $app->run();
?>

Simple, no?. La documentación está bastante completa y no tuve mayores drama en sacar andando el demo. Lo único que no me gustaba era que los “views” no podían tener un main template (al menos en la version básica de usar php como template language). Es decir, tenía que poner <? require “header.php”; ?> <? require “footer.php” ?> por todos lados, por lo que decidí implementar me propia “view” :

setTemplate($template);
        extract($this->data);
        ob_start();

        $this->setTemplate("template_pre.php");
        require $this->templatePath;

        $this->setTemplate($template);
        require $this->templatePath;

        $this->setTemplate("template_post.php");
        require $this->templatePath;

        return ob_get_clean();
    }
}
?>

Simplemente hago los 3 render y así tengo view con layout a’la Rails :P.

El segundo punto a resolver era el acceso a la base de datos. Hoy en día laburar con mysql_query, mysql_fetch es inpensable, al menos para prototipado ;). Otra vez, googleando me topé con Idiorm, “A lightweight nearly-zero-configuration object-relational mapper and fluent query builder for PHP5”, o sea, un Arel para PHP, super limiteado pero suficiente por el momento.

Este ORM nos pemite encadenar condiciones y luego obtener objetos, manipularlos y guardarlos de nuevo :

$user = ORM::for_table('user')
    ->where_equal('username', 'j4mie')
    ->find_one();

$user->first_name = 'Jamie';
$user->save();

Si queremos más abstracción todavía el mismo autor implementó Paris, una implementación de ActiveRecord sobre Idiorm. Yo en mi caso no la usé así que lo dejo a criterio del lector probarla.

A modo de ilustrar como quedó mi demo, les comparti el método del index, que obtiene la lista de registros y hace un render del view acorde :

$app->get('/', function () use ($app) {
  $contacts = ORM::for_table('contact')->find_many();
  $app->render('home.php', array('contacts' => $contacts));
});

Y la vista (recortada) :

Contactos

... data['contacts'] as $contact) { ?> ...
nombre ?> <form action="/contacts/id ?>" method="POST" class="form-inline"> <a href="/contacts/id ?>/edit" class="btn">Modificar
Agregar