12ago/100

Drupal el incomprendido y desconocido CMS

por mariotux 1 comentario »

Hace ya bastante tiempo, desde que me muevo en la tecnología LAMP, que conozco Drupal. Nunca le dediqué el tiempo necesario para ser conocedor de esa potencia interna que cuando miramos las tripas nos hace dudar que tenga. Drupal es un CMS agnóstico en contenido y que gracias a su extensa comunidad hay una cantidad de módulos y documentación (a veces demasiada) sobre como hacer proyectos en Drupal.

Tal vez, el problema de no haber invertido más tiempo en Drupal es por su sencillez tras la instalación y no conocer lo que realmente podía ofrecer. Una de las razones también muy importantes por las que no me decidía a investigarlo era la parte técnica, donde escasea la POO y hace algo muy raro :-)

Recientemente en el entorno laboral nos ha surgido la oportunidad de invertir tiempo en conocerlo, realmente me ha sorprendido. La primera sensación en la toma de contacto con el CMS es que se puede desarrollar sites dinámicos sin tirar una línea de código. Esta sensación duró hasta que nos enfrentamos a un proyecto real, en donde funcionalmente podíamos atacar muchos requisitos del proyecto pero a la hora de entrar en las tripas para personalizarlo nos dimos cuenta que hay algo más allá. El código es prácticamente funciones, y el core (no se como lo hace) simula la sobrecarga de métodos pero con  funciones en donde parece ser que sólo puede existir una sobre-escritura.

La verdad es que ahora mismo tengo un poco de fascinación por Drupal, y cuando hace unos 3 años un amigo me intentaba vender la “moto” de Drupal yo siempre le ignoraba :-) lo siento Diego! ha tenido que ser tres años más tarde.

Supongo que a partir de ahora, retomaré el blog con algún que otro artículo de Drupal.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Blogplay
  • email
  • Meneame
  • Netvibes
  • PDF
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
27abr/100

Scrum: Ser ágil es ser rápido?

por mariotux 1 comentario »

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

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Blogplay
  • email
  • Meneame
  • Netvibes
  • PDF
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
25abr/101

Cambiar el path de la carpeta Web de Symfony

por mariotux 2 comentarios »

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.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Blogplay
  • email
  • Meneame
  • Netvibes
  • PDF
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
21abr/100

Tantas ideas para tan poco tiempo

por mariotux 1 comentario »

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.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Blogplay
  • email
  • Meneame
  • Netvibes
  • PDF
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
21abr/100

Genera gráficos burndown de forma sencilla

por mariotux Sin comentarios »

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

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Blogplay
  • email
  • Meneame
  • Netvibes
  • PDF
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
21abr/102

Scrum: Velocidad vs Calidad

por mariotux 5 comentarios »

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.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Blogplay
  • email
  • Meneame
  • Netvibes
  • PDF
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
22mar/100

Google Maps API con Mootools

por mariotux 1 comentario »

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.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Blogplay
  • email
  • Meneame
  • Netvibes
  • PDF
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks