Primer coding dojo en #xdp

El pasado jueves 28 de abril, la comunidad #xdp celebró su primer coding dojo en Sevilla, con la colaboración de emergya que nos facilitó sus instalaciones.

Un coding dojo no es más que juntarse un grupo de personas a resolver un ejercicio de código (kata) por el mero hecho de practicar, con el objetivo de mejorar nuestras habilidades y discutir sobre el código que vamos produciendo.

Juanma Laó escogió para la ocasión el ejercicio de abril propuesto por la iniciativa 12 meses 12 katas, la kata del bowling.

Nos juntamos 6 personas, y tras las presentaciones de rigor y una breve introducción a TDD empezamos a analizar el problema.

Javi Soler y Juanma Laó (juanlao)
Javi Soler y Juanma Laó (juanlao)
Javi Fernández (Mudi) y Pablo Escribano (huelvafriki)
Javi Fernández (Mudi) y Pablo Escribano (huelvafriki)
Christian López (penyaskito) y Víctor Ramírez (virako)
Christian López (penyaskito) y Víctor Ramírez (virako)

Menos mal que vino Javi Soler que sabía jugar a los bolos, porque el enunciado me resultó un poco complicado de entender.

Javi Soler nos explica la puntuación de los bolos
Javi Soler nos explica la puntuación de los bolos

Nos sentamos por parejas, y empezamos a hacer las pruebas. En contra de las otras 2 parejas que eligieron c#, Virako y yo elegimos python, con la librería unittesting para las pruebas.

Tras unos cuarenta minutos de programación, pronto iniciamos una discusión sobre qué pruebas habíamos hecho. Unos optamos por implementar las pruebas sugeridas por el problema, otros por pruebas más simples en función de distintas partidas con distinta complejidad de cálculo de puntuación de la partida… También discutimos sobre cómo habíamos o no decidido prematuramente el algoritmo a utilizar para calcular la puntuación. Es curioso como tres parejas distintas abordamos de forma totalmente distinta tanto los algoritmos como el enfoque de la kata.

Al final se nos hizo tarde, y tras tres horas de (poco) código y (mucha) discusión, disolvimos la reunión no sin antes hacer la retrospectiva de la sesión. Para mi, siendo mi primera kata en grupo, la experiencia fue muy enriquecedora.

Imagen de la pizarra tras la retrospectiva
Imagen de la pizarra tras la retrospectiva

If programmers have make a plane…

ASP.NET: Getting the absolute url of a web page

Recently, I needed the way of getting the absolute URL of a web page in ASP.NET. With absolute URL, I mean the url what clients have to point to their browsers (this URL will be sent by mail), not the absolute URL relative to the web app, like the ASP.NET API seems to understand ‘absolute’.

I thought that there would be some method in the .NET Framework, but if it exists, I missed it. I looked at System.Web.VirtualPathUtility, System.IO.Path, System.Web.UI.Page and System.Web.HttpServerUtility, but no luck.

So I had to implement this. It is only a line of code, but I think that this can be useful for anyone else (including Future Me).

           String url = new Uri(Context.Request.Url, 
                            ResolveUrl("~/Example.aspx")).ToString();

If you’re using the development server Cassini, included with Visual Studio, it will return something similar to http://localhost:1234/Example.aspx. In production on IIS, it will return something like http://example.com/Example.aspx.

If you know a better way of getting the absolute URL from a page, feel free to leave a comment.

Cola: Real-Time Shared Editing

Today when updating my RSS reader I found a link to a very interesting video in Vimeo. It is a demo about the new ‘cooperation mode’ in Eclipse. I felt in love with Gobby the first time I saw it, but never found the chance of using it.

But Cola, of the Eclipse Communication Framework team, can really revolutionize what we understand for pair programming and increase the adoption of this practice.

Check Mustafa K. Isik’s blog for further details.

Nueva lista de correo sobre ecosistemas software

Leo en lo de Manuel Recena:

En esta ocasión escrito para comunicar que se ha creado una nueva lista de correo (http://groups.google.com/group/ecosistemas-software ) para tratar temas relacionados con ecosistemas software basados en herramientas con licencias de código abierto. La lista de correo acaba de ser creada y esperamos que sea bien aceptada por la comunidad de desarrolladores.

Particularmente mi aportación estará centrada en las herramientas con la que tengo experiencia, sin embargo, tengo mucho interés por conocer otras configuraciones de ecosistemas software. Esas herramientas son Maven, Archiva y Continuum, todas ellas de Apache Foundation.

Logotipo de Apache Foundation

Yo ya estoy apuntado… ¿Lo harás tú?

Manipulación de cadenas en Java

Debatíamos Bastian y yo en los comentarios de la entrada sobre FindBugs acerca de la necesidad o no de realizar las concatenaciones de cadenas en Java utilizando las clases String o StringBuilder. Bastian apuntaba que en [1] se decía que el compilador de Sun desde la versión Java 1.5 ya realizaba estas optimizaciones.

Al final la conversación quedó en que como deberes yo haría una prueba, y durante un viaje en autobús la realicé.

El código de ambos tests es el siguiente:

Test con String:

    public class LoopsStringConcatenation {
    	public static void main(String[] args) {
    		long t0 = System.currentTimeMillis();
    		String s = new String();
    		for (int i=0; i<10000; i++) {
    			s += "a";
    		}
    		long t = System.currentTimeMillis() - t0;
    		System.out.println(t);
    	}
    }
&#91;/sourcecode&#93;
Test con StringBuilder:
&#91;sourcecode language="java"&#93;
    public class LoopsStringBuilder {
    	public static void main(String&#91;&#93; args) {
    		long t0 = System.currentTimeMillis();
    		StringBuilder s = new StringBuilder();
    		for (int i=0; i<10000; i++) {
    			s.append("a");
    		}
    		long t = System.currentTimeMillis() - t0;		
    		System.out.println(t);
    	}
    }
&#91;/sourcecode&#93;
Si ejecutamos los dos tests, podemos comprobar que el método que utiliza String es bastante más lento que el método que usa StringBuilder (sí, "bastante más lento" va a servir en este caso, no voy a poner números pues esto es una prueba no formal).

No obstante, vamos a comprobar las instrucciones de bytecode que se generan en ambos casos, y vamos a ver cuál es la diferencia.

Bytecode del test con String:
&#91;sourcecode language="java"&#93;
 0 invokestatic #16 <java/lang/System.currentTimeMillis>
 3 lstore_1
 4 new #22 <java/lang/String>
 7 dup
 8 invokespecial #24 <java/lang/String.<init>>
11 astore_3
12 iconst_0
13 istore 4
15 goto 41 (+26)
18 new #25 <java/lang/StringBuilder>
21 dup
22 aload_3
23 invokestatic #27 <java/lang/String.valueOf>
26 invokespecial #31 <java/lang/StringBuilder.<init>>
29 ldc #34 <a>
31 invokevirtual #36 <java/lang/StringBuilder.append>
34 invokevirtual #40 <java/lang/StringBuilder.toString>
37 astore_3
38 iinc 4 by 1
41 iload 4
43 sipush 10000
46 if_icmplt 18 (-28)
49 invokestatic #16 <java/lang/System.currentTimeMillis>
52 lload_1
53 lsub
54 lstore 4
56 getstatic #44 <java/lang/System.out>
59 lload 4
61 invokevirtual #48 <java/io/PrintStream.println>
64 return

Bytecode del test con StringBuilder:

 0 invokestatic #16 <java/lang/System.currentTimeMillis>
 3 lstore_1
 4 new #22 <java/lang/StringBuilder>
 7 dup
 8 invokespecial #24 <java/lang/StringBuilder.<init>>
11 astore_3
12 iconst_0
13 istore 4
15 goto 28 (+13)
18 aload_3
19 ldc #25 <a>
21 invokevirtual #27 <java/lang/StringBuilder.append>
24 pop
25 iinc 4 by 1
28 iload 4
30 sipush 10000
33 if_icmplt 18 (-15)
36 invokestatic #16 <java/lang/System.currentTimeMillis>
39 lload_1
40 lsub
41 lstore 4
43 getstatic #31 <java/lang/System.out>
46 lload 4
48 invokevirtual #35 <java/io/PrintStream.println>
51 return

Como vemos, es cierto que el compilador utiliza StringBuilder en vez de String. Sin embargo, la diferencia de rendimiento se debe a que la variable local s es un String, y en cada iteración se invoca a toString() para poder asignarlo, lo que nos crea un nuevo objeto String en cada iteración.

Veamos pues en qué caso esta optimización del compilador es útil.
Si realizamos sucesivas concatenaciones, en distintas sentencias, estamos en el mismo caso que el anterior. El resultado debe ser un String, por lo que se realizar diversas llamadas al método toString() que nos penalizan.

Si concatenamos cadenas en una misma sentencia, siendo éstas variables, entonces el compilador si usa StringBuilder, y en este único caso si es interesante usar el operador + para mejorar la legibilidad.

Como curiosidad, en caso de que sean constantes (por ejemplo, s += “a” + “a” + “a”;) en tiempo de compilación ya se optimiza (en el ejemplo, quedaría bytecode equivalente a s += “aaa”;).

Volviendo a nuestro caso de concatenación de variables en una misma sentencia, sea el siguiente fragmento de código:

        String t = "a";
        String s = new String();
        s += t + t + t;

Genera:

 4 ldc #22 <a>
 6 astore_3
 7 new #24 <java/lang/String>
10 dup
11 invokespecial #26 <java/lang/String.<init>>
14 astore 4
16 new #27 <java/lang/StringBuilder>
19 dup
20 aload 4
22 invokestatic #29 <java/lang/String.valueOf>
25 invokespecial #33 <java/lang/StringBuilder.<init>>
28 aload_3
29 invokevirtual #36 <java/lang/StringBuilder.append>
32 aload_3
33 invokevirtual #36 <java/lang/StringBuilder.append>
36 aload_3
37 invokevirtual #36 <java/lang/StringBuilder.append>
40 invokevirtual #40 <java/lang/StringBuilder.toString>
43 astore 4

Podemos comprobar que aquí si ahorramos las llamadas a toString(), y por tanto es igual de eficiente que usar StringBuilder y se mejora la legibilidad.

Resumiendo, veamos cómo debemos manejar las cadenas:

  1. Usa el operador + si se concatena en una misma sentencia. Es más legible y el bytecode generado es el mismo.
  2. Usa StringBuilder en otro caso.
  3. En este caso no hemos tenido en cuenta si diversos hilos acceden a la misma cadena. En caso de que eso pudiera ocurrir, debes usar StringBuffer. Es algo más lento que StringBuilder, pero es thread safe

Espero que os haya gustado, y que Bastian se dé por satisfecho. Por mi parte, sólo queda agradecerle el hacerme más amenos los viajes en autobús.

Revisiones de código

Una de las cosas que siempre me han gustado es leer código de otros. Se aprende mucho, y es divertido intentar buscar optimizaciones, o bugs. En ArgoUML he estado haciendo esto alguna vez con FindBugs, y leo con calma todos los diffs enviados a la lista de commits.

Hoy Rodrigo Corral hacía un llamamiento en su blog, preguntándose cómo se podrían calcular las horas que han pasado desde principio de año hasta una fecha dada.

También habló Ricardo sobre revisiones de código en Subversion hace algún tiempo, y aún espero con ilusión que algún caminante deje un comentario a ese post sobre alguna herramienta que yo desconozca.

Hoy alguien ha mandado unas simples optimizaciones para la clase Int32 a la lista de desarrollo de Mono, un proyecto muy maduro, por lo que me sorprende que esta optimización no se haya realizado hace tiempo.

Por lo que se me ocurre una pregunta… ¿Cuántos ojos ven tu código?
Da igual la licencia que tenga, que el código esté disponible no significa que alguien lo lea.
¿Qué soluciones usas para las revisiones de código? ¿Es el Pair Programming algo realmente factible para un negocio?