Simetría

Lo siento, si alguien espera un post navideño (a pesar de los copitos cayendo por el blog) al estilo retrospectiva o propósitos de nuevo año, que se vaya buscando otro artículo. Creo que soy de esos que no tiene mucho apego por la Navidad. Sin embargo, ¡Feliz paso de año y que el 2011 os trate mejor que el 2010! (A todos, aunque hayamos sido -algo- malos) :-)

Bueno, al tema.

Picado por no haber podido estar ayer en el codingdojo de (la comunidad de Ruby en Madrid a la que, por fin, se acercó mucha gente que conozco), estaba yo practicando la codekata de los números romanos (una parte de ella, realmente, la de pasar a “romano”) y se me ocurrió hacer un pequeño cambio. En vez de usar un java.util.Map (sí, en Java, qué pasa :-) ) pensé en usar un array. Pensé que no debería afectarme mucho porque había escrito mi código haciendo mi mejor TDD (lo cuál no quiere decir que lo haga bien).

Para que tengáis una primera imagen de lo que hablo, mi método “String to_roman(int n)” es como sigue:

NUMERALS es un Map<Integer,String> ordenado para que “int find_biggest_numeral_that_fits(int i)” sea más fácil (y de paso eficiente). Pero lo que os quiero contar no es si es mejor usar un Map o un array para guardar esta tabla. De hecho, sobre esto se me ocurre otro artículo muy chulo sobre SRP (aunque no pueda superar éste de Hadi Hariri, claro). El caso es que, al cambiar la estructura de datos que soporta esto, mi algoritmo ha tenido que cambiar incluso hasta el método de más alto nivel de abstracción “to_roman”.

Recordemos el “Implementation Patterns” que, aunque no lo tengo a mano, recuerdo que hace hincapié en cuidar que nuestros métodos mantengan un nivel de abstracción coherente. En este caso es evidente que estamos llamando a “find_biggest_numeral_that_fits” para abstraernos de los detalles técnicos pero luego, en el mismo “to_roman” usamos NUMERALS para obtener el valor correspondiente. Hemos introducido una asimetría que no es muy dañina (en este caso que el problema es pequeño, que por eso es pequeño, para que podamos practicar sin que nos duela tanto como “en la vida real”).

Al refactorizar he cambiado “find_biggest_numeral_that_fits” por una llamada a “find_biggest_numeral_using_an_ordered_map” y ahí, al cambiar mi solución basada en un array y llamar al nuevo “find_biggest_numeral_using_an_ordered_array” me he dado cuenta de que no he cambiado NUMERALS y que sigue siendo un Map. .

He renombrado NUMERALS a NUMERALS_AS_MAP para que sea más evidente y así, he ocultado ese “código feo” en un bonito “String get_numeral(int i)”, lo cuál deja el método “to_roman” mucho más limpio.

Por cierto, observad también el leve cambio que he hecho en el orden de la linea 6, donde inicializo el StringBuffer. Me ha parecido que inicializarla “tan lejos” de donde la uso le daba un cierto tufillo que no me gustaba nada. ¿A que se lee mejor ahora? :-)

Espero vuestros comentarios. Seguro que se puede mejorar mucho aún.

Ea, lo dicho, ¡Feliz 2011!

Eclipse en colores

Por si queréis probar con los colores en Eclipse. El leer mejor (más fácil) nuestro código nos puede ayudar a escribirlo mejor. :-)

Yo he cambiado el color de fondo y he resaltado algunos elementos sintácticos:

El color de fondo:
Window > Preferences > General > Editors > Text Editors > Appearance color options:

  • Background color = color personalizado R:217, G:217, B: 236 (un gris clarito para distinguir la ventana de edición del resto pero suficientemente clara para no tener que hacer muchos cambios en el resto de colores)

Colores “sintácticos”:
Window > Preferences > Java > Editor > Syntax Coloring > Java:

  • Inherited Method Invocations : Pink (R: 255, G: 0, B: 255). Esto hace que las llamadas a métodos heredados destaquen pero no demasiado.
  • Method Declarations: Orange (R: 255, G: 128, B: 0) y negrita. Esto hace que el inicio de un método destaque sobre el resto del código.
  • Methods: Dark green (R: 0, G: 128, B: 0) y negrita. Esto hace que los verbos destaquen frente a los sustantivos.

En fin, espero que os resulte útil. :-)

Contenidos recuperados (I)

Por fin he conseguido recuperar mis contenidos del viejo blog en Blogger después de que Google y sus maléficas hordas de robots me lo robaran. Pero no creáis que lo que ha pasado es que Google se ha apiadado de mi y me los ha devuelto. Ni mucho menos. De hecho, sigo sin recibir noticias de Skynet. Creo que fue Leo Antolí el que me puso en la pista cuando me dijo que él podía leer mi blog con el Google Reader. Así que vi que había una API no documentada pero relativamente fácil de ir encontrando cómo extraer todo el contenido de mi blog desde el principio. Y me puse a ello. El resultado es que, a veces a ratos, a veces a sesiones más largas, ha dependido un poco del tiempo libre disponible, he conseguido:

  • extraer el contenido de mi viejo blog usando Google Reader,
  • lo he guardado en un fichero xml (luego explicaré un poco sobre el formato)
  • y ese mismo fichero lo he importado en el WordPress que mi amigo Carlos Blé ha sido tan amable de cederme en iExpertos.com para alojar mi nuevo blog.

He aprovechado que tenía que escribir este programita para poner en práctica lo que aprendí en el curso de Groovy al que asistí no hace mucho. Groovy es un lenguaje lo suficientemente parecido a Java como para que la curva de aprendizaje no sea una barrera, y además incorpora toda una serie de simplificaciones de la vida normal del programador que hace que ponerse a hacer algo y que funcione sea muy atractivo.

Lógicamente he practicado un poco de TDD, pero sinceramente, la experiencia de refactorizar en un lenguaje dinámico como Groovy hace que sea bastante pesado y a veces desmotivador. El IDE no te ayuda tanto (no puede hacerlo en parte por la naturaleza del lenguaje) y eso se nota. Hay que ser mucho más cuidadoso, ir más despacio… buff. Y lo peor es que te tienes que pensar muy bien los nombres de las cosas porque renombrar un método o una variable implica hacerlo a mano, con mucho cuidadito.

En cualquier caso, es estupendo programar usando TDD: te obligas a que tu diseño sea testeable, lo cuál te obliga a pensar muy bien en las responsabilidades de cada objeto. Se hace muy fácil ir explorando el problema simplemente añadiendo consideraciones en los tests.

Mi estrategia ha sido ir escribiendo todo lo que era necesario en el test para conseguir mis objetivos. Inicialmente lo que quise fue obtener el contenido de cada artículo del viejo blog en HTML y guardarlo (por si acaso, ya sabéis) :-) Más tarde, después de pensar un poco en cuál debería ser mi estrategia, decidí que lo mejor era guardar esos contenidos en un fichero para ser importado en el nuevo blog: un WordPress.

El primer objetivo era más bien jugar, practicando Groovy e ir escribiendo lineas de código para ir desentrañando la API de Google Reader. Una vez hecho esto, me olvidé un poco del código escrito (lógicamente aproveché trozos, pero no hice un trabajo de refactorización propiamente dicho). Lo interesante de esta primera parte fue que me ayudó a sacar varias conclusiones y afinar el entorno de trabajo:

  • trabajé con NetBeans y Eclipse y, aunque no está afinada la integración con Groovy en ninguno de los dos casos, me he de quedar con Eclipse. Por varias razones:
    • La más importante (para mi) es la fuerza de la costumbre. Estoy quizás demasiado acostumbrado a Eclipse y todos sus “keystrokes” (y eso que no programo últimamente demasiado)
    • La integración con Maven (uso el plugin m2eclipse -lo siento, Abel, no uso IAM)
    • El IDE de SpringSource, que apuesta decididamente por Grails y Groovy, está basado en Eclipse
  • La integración del plugin de Groovy y el plugin de JUnit es pésima. Hay que tener mucho cuidado porque te puedes encontrar persiguiendo fantasmas: se ejecutan tests que ya no están escritos, no se ejecutan tests que acabas de escribir o cosas por el estilo. Compilas, vuelves a compilar… y nada.
  • Llamar a Google Reader y procesar el JSON que devuelve como resultado usando Groovy es muy, muy, muy sencillo:
    def result = command.toURL().text
    JSON resultAsJSON = new JsonSlurper().parseText(result)
    
  • Extraer el contenido de cada artículo embebido en algún lugar de ese JSON se hace también muy, muy, muy fácilmente con Groovy:
    feed.items.each { item ->
      String title = item.title
      String content = item.content.content
      def out = prepareWriter(item.alternate[0].href - 'http://jmbeas.blogspot.com/')
      out << composeContentAsXhtml(title,content)
      out.close()
    }
    

De momento lo dejo aquí. En un par de días completo este artículo con la segunda parte, donde os explicaré cómo he generado el fichero en formato WXR (un RSS 2.0 extendido con etiquetas propias de WordPress), que tampoco está precisamente documentado.