Pensando en Red nada es tan fácil como parece serlo

27abr/100

Scrum: Ser ágil es ser rápido?

A relación a como terminé el post anterior sobre Scrum con la frase de:

Ser ágil, no significa ser rápido.

No hay nada mejor a que te hagan una pregunta en la que te contestas a ti mismo :-)

Efectivamente el uso de la metodología hace que el equipo trabaje más rápido, ya que normalmente tendemos a las naves espaciales en los desarrollos y el uso de Scrum te hace acostumbrarte a atacar la necesidad inmediata de la funcionalidad en la que estás trabajando. A consecuencia de esta reacción por parte del desarrollador, las funcionalidades se van terminando antes y cuando necesiten un cambio por si interactúa con otra funcionalidad pues ya se hará cuando toque :-)

Que me viniera a la cabeza la frase anteriormente mencionada al finalizar esa entrada en el blog, venía a cuento de que al endurecer los criterios de calidad de desarrollo hace que disminuyas la velocidad para alcanzar la funcionalidad (no puedo evitar recordar la metáfora del horno de las magdalenas) pero al disminuir la deuda técnica ¿realmente estamos cogiendo más o menos velocidad? un gran SI.

El disminuir al máximo la deuda técnica que te puede generar un proyecto es ganar en velocidad para atacar otro. Pero la sensación de alcance de funcionalidades en la iteración es menor en cuanto a velocidad. Tal vez esto venga dado por la falta de experiencia, a sabiendas de que tenemos que meter historias pequeñas para en el transcurso del sprint tengamos la sensación de ir avanzando y así ir aumentando la motivación del equipo.

Y la pregunta que desencadenó el post:

si ser Ágil no tiene que ver con la velocidad ¿por qué la única métrica que usamos es la velocidad?

Así que según respondía por Twitter me dí cuenta de lo que estaba diciendo, y no por velocidad si no que la sensación de velocidad al endurecer los criterios de calidad y manteniendo historias de mismo tamaño en iteración consigue que no tengamos la sensación de avanzar. Pero la velocidad al endurecer la calidad, aun teniendo esa sensación está en reducir al máximo la deuda técnica para poder comenzar un nuevo proyecto. En qué estaría pensando? :P

25abr/101

Cambiar el path de la carpeta Web de Symfony

A veces el servidor donde vamos a hospedar el proyecto nos puede condicionar los paths del proyecto. En un hosting compartido normalmente no puedes indicar cual es el path del document_root si no que ya te ofrecen por defecto una estructura de directorios y tienes que adaptar tu desarrollo a ello.

Bien, con symfony es muy sencillo cambiar el path del web dir.

Tenemos que editar el fichero ProyectConfiguration.class.php y cambiaremos el web dir:

$this->setWebDir($this->getRootDir().'/public_html');

Teniendo en cuenta que el proyecto se encuentra en /home/projects el document_root en symfony sería /home/projects/web, pero al agregar esa línea en el fichero de configuración nos intentaría localizar en /home/projects/public_html.

Por otro lado si queremos meter toda la estructura de symfony en una carpeta, al estilo de:

public_html //El document root
source //Toda la estructura del proyecto symfony

Tendríamos que configurar el path de public_html así:

$this->setWebDir($this->getRootDir().'/../public_html');

Ya que el $this->getRootDir() ya te ubica donde tienes el código.

Aquí dejo una chuletilla :-) para cuando me vuelva a hacer falta, si os es de utilidad pues mejor.

Etiquetado con: , , 1 Comentario
21abr/100

Tantas ideas para tan poco tiempo

Las ideas son magnificas cuando brotan, cuando de ellas salen proyectos interesantes y con corazón. Muchas de las mejores ideas se gestionan en momentos insospechables y a veces ridículos :-) pero hay que ir descartando algunas que brotan sin sentido para poder ir refinando las principales.

A que viene todo esto... viene a que desde hace ya 2 años llevo con la intención de terminar con un proyecto, un proyecto que comenzó de juntar dos ideas fantásticas! pero a veces gestionar el tiempo libre para sacarlo es difícil. Cuando el tiempo de foco en el desarrollo es breve y con pausas muy largas es complicado recuperar el contexto. Pero siempre, todas las semanas ese proyecto retumba en mi cabeza con la coletilla de "A ver si lo voy a acabando..." :-)

Lo peor de todo... que mientras llevo estos dos años arrastrando el terminar este proyecto, van surgiendo nuevas ideas. Si me gustan y parecen interesantes pero tienen que ir a la pila de ideas y a su prioridad. Tantas ideas y tan poco tiempo para ejecutarlas.

Antes me parecía más sencillo sacar proyectos web propios, los fui sacando y cerrando según iba pasando el tiempo por falta de dedicación u otras cosas. Ahora, el tiempo se reparte en muchas actividades/tareas/responsabilidades y parece costoso sacar un proyecto decente adelante. Sin duda estoy volcando esfuerzo en hacerlo, y como no escribí el post de lo que me propongo para el 2010 en enero como muchos bloguers, yo me propongo ahora casi 4 meses transcurridos en el 2010, en que en verano tengo que tener una versión Beta en producción y que a finales de año si la cosa funciona refinaremos un poco los servicios :-)

Bueno, ya está dicho públicamente. Ahora sólo queda cumplir.

21abr/100

Genera gráficos burndown de forma sencilla

Si utilizas scrum como metodología de trabajo o si has oído hablar de ella, seguramente habrás oído hablar también del gráfico burndown. Con él, de forma sencilla puede verse de un vistazo información sobre cómo va el trabajo realizado durante el sprint entre otras cosas.

Estos gráficos son muy sencillos de realizar, pero si no quieres complicarte nada la vida, tienes Yet another online burndown generator o, lo que es lo mismo, un generador de burndown online.

El funcionamiento es muy sencillo: indicamos los puntos (u horas o la unidad de trabajo con la que estés midiendo tu velocidad), los días y un título. Con estos tres datos, la aplicación te genera un PDF del tamaño de un A4 horizontal listo para imprimir con tu gráfico.

http://www.burndowngenerator.com

Como apunte a este post "fusilado" del autor. Nosotros utilizamos esta herramienta para generar burndown en el trabajo, es rápido y sencillo. Imprimimos y al panel :-) Es cierto que puedes tener tu hoja de excel... pero si me lo da una web me parece más sencillo y cómodo, los ficheros en el equipo local o se "traspapelan" o quien lo tiene que utilizar igual no lo tiene :-) Es una web sencilla con un objetivo claro, generar burndown!

Referencia: tatai.es

21abr/102

Scrum: Velocidad vs Calidad

Un título tal vez algo sensacionalista y poco acertado, pero hace unos días me entró la duda de como afrontar este dilema.

En primer lugar, el concepto de terminado que tiene el equipo tiene que estar claro para cumplir el concepto de calidad, por ejemplo:
- Código documentado
- Documentación técnica
- Refactorización de la tarea (si es necesario).

La velocidad de un equipo puede ser constante si el criterio de terminado está definido y se aplica en todas las historias, pero... ¿cuándo tenemos que dejar de refactorizar y/o optimizar?

No se trata de que en cada tarea de historia optimicemos al máximo el código ya que puede que en la demostración se pidan cambios, pero si intentar tener un criterio para no extenderse. Esto puede ser un problema si eres demasiado perfeccionista o estás desarrollando pensando en el futuro. Es bueno preveer el futuro, pero si nos centramos en la funcionalidad inmediata es más sencillo el ir cumpliendo objetivos.

Si en el desarrollo nos centramos en cumplir funcionalidad podemos ir avanzando en el proyecto a una velocidad mayor, pero si en el criterio de "Refactorización" o de "Homogeneización" de código del equipo no se cumple estaríamos generando deuda técnica para futuras iteraciones.

Creo que lo más difícil pensando en la parte técnica, es el llegar a decir "Hasta aquí..." en cuanto a dejar el código como nos gustaría que estuviese. Los técnicos solemos pecar a menudo en intentar a veces hacer naves espaciales para poder cruzar de acera... (Yo el primero) todos nos gusta tener la sensación de "Esto ha quedado dpm!" por eso el ponerse el tope de no ir más allá de donde realmente tenemos que ir, ya que todo es mejorable hasta el infinito y más allá... :-)

Obviamente, cuando nos planteamos una iteración centrándonos en mejorar nuestro criterio de calidad la velocidad es más lenta (he descubierto el mundo xD) pero tal vez no en todos los proyectos se pueda tener la calidad que pueda ofrecer el equipo.

Nuestro amigo Ángel Medinilla siempre afirma que la calidad no es negociable, ¿pero hasta que punto?
A la hora de vender un proyecto la empresa podría ofertar productos/proyectos en diferentes calidades? si... penalizando la calidad, pero también podemos comprar diferentes calidades de un coche por ejemplo las gamas de un mismo modelo. El abanico que podría estar ofertando la empresa podría ser diferente, pero también entraría en conflicto con la posible deuda técnica que podría generar el penalizar la calidad de un servicio no siendo rentable entonces para la empresa.

Calidad, calidad de que funciona siempre! pero el resto de la calidad que no se ve podría ser la que podría variar?

Ser ágil, no significa ser rápido.

22mar/100

Google Maps API con Mootools

Aquí os dejo un clase sencilla de mootools que imprime un mapa y al hacer click o arrastrar la marca del mapa obtiene la dirección por sus coordenadas.

En el html sólo tendremos que tener una capa con id map_canvas:

<div id="map_canvas"></div>

Tenemos que obtener clave de google maps api para utilizar el mapa, y tras hacer la declaración del javascript del api de google tendremos que incluir también el framework de mootools.

La clase es muy sencilla, os animo a copiar y pegar para probar su funcionamiento. Es mi primera toma de contacto con mootools, codificando desde 0, y la verdad me está gustando.

var Gmap = new Class({
    Implements: Options,
    map: null,
    center: null,
    marker: null,
    geocoder: null,
    options: {
        center:{
            lat: 40.730885,
            lng: -3.997383
        },
        zoom: 6,
        map:{
            container: 'map_canvas',
            element: null,
            width: 500,
            height: 400
        },
        mapinterface:{
            search: true,
            infowindow: true,
            name: 'gmap'
        }
    },
    initialize: function(options){
        this.setOptions(options)
        this._drawInterface($(this.options.map.container));
        this.map = new GMap2($(this.options.mapinterface.name));
        this.geocoder = new GClientGeocoder();
        this.center = new GLatLng(this.options.center.lat, this.options.center.lng);
        this._drawMap();
    },
    _drawMap: function(){
        if (GBrowserIsCompatible()) {
            this.map.setCenter(this.center, this.options.zoom);
            this.map.setUIToDefault();
            this._addMapListener();
        }
    },
    _drawInterface: function(element){
        var map = new Element('div', {
            'id': this.options.mapinterface.name,
            'styles': {
                'width': this.options.map.width,
                'height': this.options.map.height
            }
        });
        map.inject(element);
        if(this.options.mapinterface.infowindow){
            var infomap = new Element('div', {
                'id': 'infomap',
                'styles': {
                    'width': '500',
                    'height': '200'
                }
            });
            infomap.inject(element);
        }
    },
    _addMapListener: function(){
        GEvent.addListener(this.map, "click", function(overlay, latlng){
            this.map.closeInfoWindow();
            this._createMarker(latlng);
        }.bind(this))
    },
    _createMarker: function(latlng){
        this.marker = new GMarker(latlng, {
            draggable: true
        });
        this.map.clearOverlays();
        this.map.addOverlay(this.marker);
        this._addMarkerListener();
    },
    _addMarkerListener: function(){
        GEvent.addListener(this.marker, "dragstart", function() {
            this.map.closeInfoWindow();
        }.bind(this));
        GEvent.addListener(this.marker, "dragend",function(overlay,latlng){
            //getAddress(overlay, latlng);
            this.getAddress(this.marker.getLatLng());
        //this.marker.setLatLng(latlng);
        }.bind(this));
    },
    getAddress: function(latlng) {
        if (latlng != null) {
           this.geocoder.getLocations(latlng, this._showAddress);
        }
    },
    _showAddress: function(response){
        if (!response || response.Status.code != 200) {
            alert("Status Code:" + response.Status.code);
        } else {
            //console.log(response);
            place = response.Placemark[0];
            point = new GLatLng(place.Point.coordinates[1],
                place.Point.coordinates[0]);
            //                                                                                                                                                                                                                                                                                                                                                                                                                                  marker = new GMarker(point);
            var info = '<b>orig latlng:</b>' + response.name + '<br/>' +
            '<b>latlng:</b>' + place.Point.coordinates[1] + "," + place.Point.coordinates[0] + '<br>' +
            '<b>Status Code:</b>' + response.Status.code + '<br>' +
            '<b>Status Request:</b>' + response.Status.request + '<br>' +
            '<b>Address:</b>' + place.address + '<br>' +
            '<b>Accuracy:</b>' + place.AddressDetails.Accuracy + '<br>' +
            '<b>Country code:</b> ' + place.AddressDetails.Country.CountryNameCode;
            $('infomap').innerHTML = info;
        }
    }
});
window.addEvent('domready', function() {
    var map = new Gmap();
});

Si tenéis alguna duda siempre podéis dejar un comentario.

20feb/101

Firefox – Error en el bus

Como siempre, cuando nos encontramos con un problema nos toca indagar por internet...

Esta vez no podía iniciar Firefox tras una reiniciada fortuita. Me extrañaba bastante, así que lo primero que hice fue reinstalar el paquete de firefox. No obtuve solución así que tras ejecutar el comando en consola:

~$: firefox %u

Obtenía como respuesta:

Error en el bus

Desconcertado comencé a "googlear", y encontré solución a este problema gracias al grupo de usuarios de GNU/Linux da Galiza

Esta entrada es modo "chuleta" por si me vuelve a ocurrir en otra ocasión.

El error en el bus, es debido a que alguna librería que usa la aplicación que intentamos arrancar (en mi caso, firefox) está corrupta. Para saber cual/es son y así luego poder reinstalarlos y solucionar el problema los sistemas debian poseen un paquete llamado debsums que nos permite verificar los archivos de los paquetes instalados contra MD5 checksums.

~#: aptitude search -n debsums
debsums - verification of installed package files against MD5 checksums

Instalamos el paquete debsums:

~#: aptitude install debsums

Ejecutamos el comando debsums en modo silencioso (-s) y redirigimos la salida a un fichero de texto debsums.txt para luego poder tratarlo.

~#: debsums -s &> debsums.txt

En el fichero debsums.txt tendremos líneas como:

debsums: checksum mismatch gdm file /var/lib/gdm/.gconf.defaults/%gconf-tree.xml

Si nos fijamos en el nombre del paquete aparencen en la 4 fila (obtendremos este nombre con el comando cut) y puede ser que el mismo paquete aparezca varias veces ( obtendremos como salida una única vez con el comando uniq ). Pasamos a tratar el fichero debsums.txt y a guardar en otro fichero debsums_reinstall.txt los paquetes que son necesario reinstalar:

~# cat /tmp/debsums.txt | grep "mismatch"  | cut -d " " -f4 | uniq  > debsums_reinstall.txt

En debsums_reinstall.txt tendremos los paquetes que tendremos que reinstalar. Si son muchos podremos hacer un script que los reinstale todos sin necesidad de ir metiendo el comando para cada uno de ellos:

~# aptitude install `(cat debsums_reinstall.txt)`

De esta manera conseguí recuperar el inicio de Firefox, pero claro... antes tuve que instalar epiphany para encontrar esta información :)

Referencia: http://www.glug.es/content/firefox-error-en-el-bus-solución-debsums

10feb/101

Haz de Scrum parte de tu vida

Tal vez un título muy generalista pero antes de contar el porqué comenzaré por el principio :)

La Historia

Tras unos años en el mundo del desarrollo de software, acostumbrado a proyectos gestionados en cascada y con roles con responsabilidad determinada, en un proyecto con un proveedor de outsourcing comienzo a oír la palabra "Scrum". Nos encontrábamos embarcados en un proyecto "bicicleta", se habían recortado funcionalidades para poder entrar en costes, pero el lado comercial era un coladero de funcionalidades con poca comunicación con la parte técnica. La parte técnica  era la que estaba involucrada en el proyecto junto con el proveedor. La toma de decisiones con el cliente llegaban a la parte técnica del proyecto con "Es que hay que hacer esto porque se lo hemos dicho al cliente..."

Aunque el acceso a los jefes de proyecto y de área era muy lineal, al final a la hora de exigir responsabilidades cada uno se mantenía en su escalón aunque aguantábamos la carga general conjuntamente. Estábamos obcecados en tener un control excesivo del proyecto, notábamos falta de control y comunicación. El intentar cerrar el acuerdo con el cliente a base de contratos, el recurrir a la oferta y al contrato con el cliente para defender batallas internas de responsabilidades de la perdida que estaba generando el proyecto se estaba convirtiendo en algo frecuente y con ello la sensación de entrar a la oficina con la coraza puesta dispuesto a luchar con el que se ponga por delante.

Al final el proyecto salió, a base de horas, esfuerzos personales y negociaciones con el cliente. Aunque no era el responsable de números, estaba claro que ese proyecto fue una perdida para la empresa.

Os puedo asegurar que tuve muchos dolores de cabeza y roces con compañeros a nivel profesional a causa de este proyecto. Cuando pasa el tiempo te lo tomas a "broma" aquellos días en los que te quedas trabajando 12 o 13h porque "Hay que entregarlo mañana...", "Es para ayer...", "Tiene que estar hecho..." y el trabajo de un día de 13h se echaba a perder. A nadie le gusta invertir su tiempo en algo que luego se tira, aunque a final de mes tengamos la nómina asegurada. Esto causa desmotivación y por lo tanto bajo rendimiento.

Pero algo bueno salió de este proyecto. Scrum llegó a mis oídos y a los de mi jefe de proyecto. Comenzamos a valorar la opción de intentar aplicar Scrum en el equipo y a conocer un poco la metodología. El proveedor de servicios lo utilizaba y a él le funcionaba con sus clientes, ¿por qué no tendría que funcionar con nosotros?

En el siguiente proyecto intentamos aplicarlo. Nos creamos nuestro product backlog a base de funcionalidades y a crear sprints de desarrollo. Funcionaba! el desarrollo comenzaba a ser más visible y el dueño de producto priorizaba las funcionalidades e iba viendo su resultado.

A día de hoy

Bien esto paso hace ya casi un año, ahora en mi nueva etapa profesional he tenido la suerte de toparme con una empresa que cree fielmente en esta metodología.

Hoy ha finalizado un curso de Scrum Master impartido por Angel Medinilla en donde me he sentido identificado en muchos de los ejemplos que ha ido exponiendo a lo largo del curso. Es difícil encontrarse con un comunicador de este calibre, una persona que a parte de transmitir su experiencia, inculcarnos la manera de trabajar de manera ágil también hace ameno el aprendizaje. Sinceramente, la sensación tras finalizar el curso ha sido de: "Vamos a comenzar a utilizar esto al 100%, ya!!... " Con motivación!!

Al identificarme en muchos de los casos de "error" en el desarrollo de software no puedes evitar el que te venga a la mente todos aquellos proyectos en los que "sufriste el parto" y aún así recordar que en ese momento pensabas que lo estabas haciendo de la manera correcta. Ahora simplemente lamento haber conocido esta metodología "tan tarde" pero a tiempo!! que es lo importante y con la suerte de que no tengo que "Luchar" para incorporar esta metodología de trabajo dentro de la empresa, si no que la empresa apuesta por esta metodología al 100%.

Está claro que en la parte técnica es fácil que pueda cuajar esta metodología, pero no es sólo trabajo de los "pica teclas". Introducir esta metodología en una empresa con una estructura piramidal firme y acostumbrada a desarrollar proyectos de manera convencional seguro que es una tarea difícil. Tiene que ser un esfuerzo conjunto por todos los roles que forman parte de la corporación, ya que sin esta convicción el equipo de desarrollo nunca será ágil y la lucha "Técnico vs Comercial" se mantendrá por la eternidad...

Desde mi incorporación hemos utilizado esta metodología y fui adquiriendo conocimientos que no tenía de Scrum, pero el curso ha sido una manera de reflexionar y reforzar esos conocimientos que me estaban transmitiendo mis compañeros de trabajo.

Desarrollar utilizando Scrum es divertido, tengo que reconocer que tengo una fiebre extrema por los gráficos burn down que me presenta Jira pero he aprendido a hacerlos a mano y como interpretarlos con un simple vistazo. No sólo nos han explicado como funciona Scrum, si no la combinación con otras metodologías como Extreme Programing y Kanban.

Conclusión

Hoy estoy tan convencido del uso de Scrum que me estoy planteando la opción de utilizar Scrum para la gestión de mi agenda personal :-) Scrum-Alone

Referencias de interés

Scrum Definición de Scrum en Wikipedia

Programación Extrema (XP) Definición de Programación Extrema en Wikipedia

Kanban Definición de Kanban en Wikipedia

http://www.presionblogosferica.com/ Blog de Angel Medinilla

http://www.agile-spain.com/ Comunidad sobre métodos ágiles.

Manifiesto Ágil

http://groups.google.es/group/agile-spain Lista de correo de la comunidad de Agile Spain

Etiquetado con: , , 1 Comentario
25ene/1035

Android SDK con NetBeans 6.8

La primera toma de contacto que tuve con el SDK de Android fue con Eclipse, pero por otro tipo de decisiones he pasado a utilizar el IDE NetBeans y ¿por qué no usar este fantástico IDE para desarrollar en Android?

La verdad es que ahora crear el emulador, como veremos más adelante, es relativamente sencillo y hacer que funcione con NetBeans bastante más sencillo aún :-)

Todo lo que voy a explicar en este post es sobre Ubuntu 9.10, lo siendo por los usuarios Windows ^_^aunque en la mayoría de los casos es todo prácticamente igual.

Bien primero tendremos que hacernos con la versión de NetBeans 6.8 y con el SDK de Android:

Descarga de NetBeans 6.8

Descarga de Android SDK

1. Instalar Netbeans

chmod +x netbeans-6.8-ml-linux.sh

./netbeans-6.8-ml-linux.sh

2. Descomprir android sdk en ~/android_sdk/

~/Descargas$ tar xfvz android-sdk_r04-linux_86.tgz

~/Descargas$ mv android-sdk-linux_86 ../android_sdk

24ene/103

Como configurar Google Gtalk en Pidgin

Siempre que pasa un formateo en mi equipo tengo que recurrir a nuestro amigo Google para encontrar un mini-howto para hacer esta tarea. Así que aquí va mi mini-howto para localizarlo la próxima vez con más rapidez.

Primero vamos a la gestión de cuentas y seleccionamos protocolo GTalk.

Aquí podemos rellenar la información para una cuenta de gmail.com o para un dominio que esté en google apps, cambiando el dato de "Dominio".

Protocolo: Google Talk
Nombre de usuario: tu_usuario
Dominio: gmail.com
Recurso: Home
Contraseña: *******

No he probado con otro nombre de recurso, pero supongo que no será un campo obligatorio :-)

La parte importante es en la pestaña de Avanzadas:

Dejando la configuración como se muestra en la imagen ya tendríamos configurado nuestro Pidgim con la cuenta de Gtalk.

Este mini-howto está basado en la información que he encontrado en http://www.congdegnu.es/2009/01/29/como-configurar-google-talk-en-pidgin

No hay mucho más que aportar a estos how-to, simplemente mis mini-pantallazos de la app y esta chuleta que dejo en el blog para mis futuras configuraciones, ya que es imposible acordarse de todos los pasos de las configuraciones de todo.

Etiquetado con: , 3 Comentarios

Page optimized by WP Minify WordPress Plugin