El Blog de Ana Buigues http://anabuigues.com Wed, 07 Dec 2011 16:07:47 +0000 es-ES hourly 1 http://wordpress.org/?v=3.4 Cómo fue el Global Day of Coderetreat 2011 en Madrid http://anabuigues.com/2011/12/06/como-fue-el-global-day-of-coderetreat-2011-en-madrid/ http://anabuigues.com/2011/12/06/como-fue-el-global-day-of-coderetreat-2011-en-madrid/#comments Tue, 06 Dec 2011 20:42:01 +0000 Ana Buigues http://anabuigues.com/?p=3734

El pasado 3 de diciembre se llevó a cabo en todo el mundo el evento denominado Global Day of Coderetreat, el cual reunió a unos 2000 desarrolladores alrededor del mundo, todos participando el mismo día en una actividad denominada coderetreat.

¿Y qué es un coderetreat? según Corey Haines que es el impulsor de todo esto, es una práctica que se realiza durante todo un día, centrada en los fundamentos del diseño y desarrollo de software. Suelen resolverse problemas sencillos en un entorno en el que solo es importante aprender. El formato del coderetreat ha demostrado ser un medio altamente efectivo para mejorar nuestras habilidades.

Se realizan iteraciones de 45 minutos realizando pair programing y TDD. Después de cada iteración se realiza una retrospectiva para saber como ha ido, se cambia de pareja, se borra el código y se empieza con la resolución del problema desde cero. No importa si después de 45 minutos no hemos logrado escribir una sola línea de código o no hemos resuelto el problema completo, siempre y cuando esa línea o todo el código lo hayamos escrito de la mejor manera posible.

El Coderetreat de Madrid se celebró en Camon, tuvimos como facilitador a Enrique Comba que nos guió en el clásico problema del Juego de la Vida de Conway durante las diferentes iteraciones realizadas.

1ª Iteración

En esta primera iteración no había ninguna restricción, sirvió como toma de contacto con el problema. Lo que aprendí en esta iteración es a no empezar a construir la casa por el tejado!

2ª Iteración

Las restricciones en esta iteración eran que no podíamos usar tipos primitivos, todo tenía que estar en objetos y no podíamos usar ifs. En esta iteración no tuvimos ningún problema, siempre pensando en OO.

3ª Iteración

Varias restricciones… de primeras no podíamos tener métodos de más de 2 líneas. A mitad de la iteración se añadió la restricción de programar haciendo ping-pong en silencio. El hecho de no poder hablar con tu compañero hizo que se nos atragantase bastante la iteración. Lo que aprendí es que tenemos que escribir los test y la lógica de una manera suficientemente sencilla y clara para que otro programador sea capaz de entender que hemos hecho.

4ª Iteración

En esta iteración teníamos que escribir el peor código que se nos ocurriese, y a mitad de iteración teníamos que hacer lo contrario, intentar cambiar el código escrito para que quedase de la mejor forma posible. Al iniciar esta iteración pensaba que lo de escribir un código feo y malo iba a ser sencillo, pero tengo que decir que la verdad es que nos resulto bastante complicado después de 3 iteraciones escribiendo buen código. Aunque en la retrospectiva me di cuenta que todo era cuestión de imaginación! nombres que no tengan nada que ver lo que se está haciendo, escribir código innecesario simplemente para que no sea legible etc…

5ª Iteración

En esta iteración la restricción era TDD as if you meant it, hacer todo el código en el propio test y sólo sacarlo a método cuando se repita, y luego si hay métodos que tengan pinta de clase sacarlos. Es una práctica difícil y dura pero a la vez interesante ver como pasito a pasito se llega a una sencilla solución. Es la iteración que más me gusto.

6ª Iteración

Es esta iteración las restricciones eran clases inmutables, no podíamos utilizar fors y no podíamos utilizar algoritmos. Esta iteración nos fue bastante bien, creo que por ser la última.

Fue mi primer coderetreat  y tengo claro que voy a repetir, es un día en el que practicas y te diviertes a la vez, cosa que muchas veces no ocurre. Conoces a gente estupenda y te llevas muchos tips a mejorar.

Finalmente podéis ver el vídeo que grabó Enrique Comba, y así ver lo bien que nos lo pasamos!

]]>
http://anabuigues.com/2011/12/06/como-fue-el-global-day-of-coderetreat-2011-en-madrid/feed/ 10
Must Read: Diseño Ágil con TDD de Carlos Blé http://anabuigues.com/2011/11/13/must-read-diseno-agil-con-tdd-de-carlos-ble/ http://anabuigues.com/2011/11/13/must-read-diseno-agil-con-tdd-de-carlos-ble/#comments Sun, 13 Nov 2011 13:24:43 +0000 Ana Buigues http://anabuigues.com/?p=3624 Recientemente he leido Diseño Ágil con TDD de Carlos Blé y considero que su lectura es una magnifica forma de introducirse en el mundo de la practica del Test Driven Development.

Para los que desconozcan que es TDD es una técnica de desarrollo de software enmarcada dentro de la metodología eXtreme Programming que tiene la virtud de minimizar el número de defectos del código y maximizar su calidad creando un código limpio que funcione.

El libro se divide en dos partes, un teórica y una práctica. En la parte teórica realiza una pequeña introducción sobre la importancia del Agilismo. Pasa a explicarnos el algoritmo del TDD y realiza un recorrido por los distintos tipos de test como son los Test de Aceptación, Test Funcionales, Test de Sistema, Test Unitarios y Test de Integración. También nos explica cuando usar los dobles de prueba y como escribir código que cumpla con los principios de diseño S.O.L.I.D.

La lectura de esta primera parte resulta realmente enriquecedora, introduce muchos aspectos del “como se deben realizar las cosas”, se nota que la artesanía del software es un papel importante dentro de esta técnica de desarrollo, bueno y del desarrollo en general.

La segunda parte es puramente práctica, dónde se aplica todo lo aprendido en la parte teórica paso a paso. Se realiza un ejemplo partiendo de los test de aceptación, de esta forma nos centramos específicamente en el problema a resolver. Se van desarrollando los test utilizando TDD y se observa como el código va cambiando y adaptándose a los requisitos de una manera incremental.

Qué beneficios obtenemos:

  • Escribimos código de calidad.
  • Los diseños son más simples, nunca escribimos más código del necesario.
  • Aumenta la fiabilidad del código gracias a los test.
  • Conseguimos código muy reutilizable.
  • La tranquilidad de realizar modificaciones, si rompemos algo un test nos lo dirá.

Qué problemas encontraremos:

  • La técnica en sí es muy sencilla, pero llevarla a cabo cuesta, hay que cambiar nuestra forma de pensar las cosas.
  • Estamos acostumbrados a escribir código que funcione y punto, ni refactorizaciones ni principios…El dilema del “no tengo tiempo o no hay tiempo” ya no vale.

Los ejemplos del libro están escritos en C#, yo los realicé en Java, los podéis encontrar aquí.

]]>
http://anabuigues.com/2011/11/13/must-read-diseno-agil-con-tdd-de-carlos-ble/feed/ 8
Diviértete practicando TDD con Pulse y TDGotchi http://anabuigues.com/2011/09/20/diviertete-practicando-tdd-con-pulse-y-tdgotchi/ http://anabuigues.com/2011/09/20/diviertete-practicando-tdd-con-pulse-y-tdgotchi/#comments Tue, 20 Sep 2011 17:41:33 +0000 Ana Buigues http://anabuigues.com/?p=3597 El Test Driven Development  o desarrollo guiado por pruebas es una técnica de diseño de software que se basa en tres sencillos pasos:

  1. Rojo: escribimos la prueba primero cuando la funcionalidad está todavía por implementar, provocando el rojo.
  2. Verde: escribimos el código más sencillo que haga que la prueba funcione, provocando el verde.
  3. Refactorización: arreglar el código, extrayendo métodos, quitando duplicados, mejorando el nombre de métodos, clases, atributos…

Es importante que sigamos los pasos al pie de la letra, porque de lo contrario, no llegaremos a exprimir al máximo la técnica como herramienta de diseño.

Pulse y TDGotchi son dos plugins de Eclipse que nos ayudan a divertirnos mientras practicamos TDD.

Pulse

Pulse hace una analogía a lo que sería la representación de los latidos de nuestro corazón en los monitores de los hospitales, de forma que nos muestra nuestro pulso practicando TDD. Cuando obtenemos un rojo en nuestros test se mostrará un pico hacia abajo, cuando obtengamos un verde se mostrará un pico hacia arriba y cuando refactorizemos se mostrará un pequeño pico azul hacia arriba. Se muestra como una vista en Eclipse.

¿Y para qué nos sirve? pues para comprobar que realmente seguimos los pasos de TDD, a mi me ayudó para darme cuenta de que algunas veces me saltaba algún paso. Además podemos guardar nuestras sesiones de pulsos para posteriormente ver nuestro progreso, o compararlas con otros compañeros a modo de pique por ver quién lo hace mejor :P

TDGotchi

TDGotchi funciona como los famosos tamagotchi que se pusieron de moda hace tiempo (yo tuve uno). Es una mascota virtual que se alimenta de tus tests y tus refactorings. El sistema de puntuación para alimentar a nuestra mascota es el siguiente:

Como veis, obtener un doble rojo es penalizado de una forma bastante elevada así que cuidado con ellos porque cuando realizamos tres o cuatro de ellos la puntuación negativa es tan alta que casi imposible de remontar, lo bueno (o malo según se vea) es que cuando abrimos de nuevo nuestro Eclipse, la puntuación vuelve a estar a 0.

La mascota irá aumentado o disminuyendo de nivel, dependiendo de nuestra puntuación, nos podemos convertir en un zombi con una puntuación negativa o ir mejorando nuestro nivel cuanto mayor sea la puntuación obtenida.

Este plugin ayuda a seguir el sistema de tres pasos de TDD a raja tabla, ya que nadie quiere convertirse en un zombie!!!

Por último felicitar a su creador @Sebastian por el gran trabajo realizado y hacer que practicar TDD sea tan divertido.

]]>
http://anabuigues.com/2011/09/20/diviertete-practicando-tdd-con-pulse-y-tdgotchi/feed/ 12
Implementación de un Scaffolding con Grails http://anabuigues.com/2011/09/12/implementacion-de-un-scaffolding-con-grails/ http://anabuigues.com/2011/09/12/implementacion-de-un-scaffolding-con-grails/#comments Mon, 12 Sep 2011 17:47:13 +0000 Ana Buigues http://anabuigues.com/?p=3604 Problema: necesito crear una interfaz web sencilla para rellenar una base de datos.

Solución: realizar un scaffolding con Grails

¿Qué es Scaffolding?

El Scaffolding es un término introducido por Rails y que está presente en otros frameworks como Grails, permite la generación automática de código para las cuatro operaciones básicas de cualquier aplicación que son la creación, lectura, edición y borrado, en inglés se conoce como CRUD. La idea es que partiendo del esquema de base de datos, generar el código necesario para implementar el CRUD. En Grails se consigue escribiendo muy pocas líneas de código.

Grails permite dos tipos de scaffolding, dinámicos y estáticos. En el scaffolding dinámico el código se genera en tiempo de ejecución, de modo que  cualquier cambio en las clases de dominio genera un nuevo scaffolding,  el estático, genera código estático tanto de vistas como de controladores de forma que después podemos modificarlo como queramos.

Para mi problema, con el scaffolding estático me salgo.

Crear el proyecto Grails

Para la creación del proyecto he utilizado el Netbeans, bien te descargas la versión del Netbeans que incluye Grails o bien lo instalas como un plugin desde el Netbeans. Al crear el proyecto veremos la siguiente estructura:

Las partes que nos interesan son:

  • Configuration: entre otras cosas contiene los ficheros de configuración de la base de datos (DataSource.groovy). Por defecto viene configurado hsqldb. Si queremos otra base de datos hay que cambiar la configuración.
  • Controllers: donde crearemos los controladores.
  • Domain Classes: donde crearemos las clases de dominio.

Implementación del Scaffolding

Primero he cambiado la configuración de la base de datos a Mysql:

dataSource {
    pooled = true
    driverClassName = "com.mysql.jdbc.Driver"
    username = "root"
    password = ""
}
development {
        dataSource {
            dbCreate = "update" // one of 'create', 'create-drop','update'
            url = "jdbc:mysql://localhost:3306/clm_web"
        }
}

Creamos las clases de dominio que necesitemos, para ello, hacemos click derecho sobre Domain Classes -> Nuevo -> Grails Domain Class. Por defecto todas las propiedades en un objeto de dominio son obligatorias, y grails realiza una validación automática en el momento de guardar el objeto en base de datos. Para controlar la validación de las propiedades podemos definir restricciones mediante la palabra reservada constraints.

class Category {
    static mapping = {
        table 'categories'
    }
    static constraints = {
        id(blank:false,nullable:false)
        seo_url(blank:false,nullable:false)
        title(blank:false,nullable:false)
        description(blank:false,nullable:false)
    }
    Integer id
    String seo_url
    String title
    String description
}

Para cada uno de los dominios creamos un controlador para los que se desee tener un scaffold, hacemos click derecho sobre Controllers -> Nuevo -> Grails Controller.

Modificamos el controlador de la siguiente forma:

class CategoryController {
    static scaffold = true
}

Lanzamos las aplicación y en la página inicial podremos ver un enlace que nos lleva al CRUD del objeto de dominio que hemos creado. Si queremos cambiar el orden en que muestra los campos, es tan simple como cambiar el orden en el código del objeto y reiniciar.

Las vistas que ofrece son las siguientes:

  • Listado

  • Añadir un elemento nuevo

  • Modificar o borrar elementos ya creados

]]>
http://anabuigues.com/2011/09/12/implementacion-de-un-scaffolding-con-grails/feed/ 16
Apache Barcamp Spain 2011, ¿te lo vas a perder? http://anabuigues.com/2011/09/03/apache-barcamp-spain-2011-%c2%bfte-lo-vas-a-perder/ http://anabuigues.com/2011/09/03/apache-barcamp-spain-2011-%c2%bfte-lo-vas-a-perder/#comments Sat, 03 Sep 2011 18:58:28 +0000 Ana Buigues http://anabuigues.com/?p=3626 Por si alguien no se ha enterado todavía, el 8 de octubre de 2011, se celebrará en Sevilla la Apache Barcamp Spain. Un evento creado por desarrolladores para desarrolladores, en formato Open Space y por si fuese poco, gratuito.

Cualquiera puede proponer su charla y entre todos los asistentes votaran las que crean más interesantes para componer el panel final de sesiones, y no solamente se limita a frameworks, tecnologías y productos de Apache, se espera que haya talleres introductorios y especializados de todo tipo de lenguajes como: Ruby, .NET, Python, Java, Scala, Groovy, Lisp JavaScript o HTML5,  soluciones prácticas y debates teóricos sobre escalabilidad y concurrencia, esto promete!

La idea del evento es compartir con otros, aprender de otros y divertirte con todos! así que no te lo puedes perder.

Además Atlassian patrocinará la fiesta de despedida, invitando a todos los asistentes al acabar con un cargamento de cerveza y tapas gratis después del largo día de sesiones.

Podéis seguir el evento desde  la página web,  la cuenta de twitter, la lista de correo y hasta tiene su  propio lanyrd. También podéis ayudar a su difusión sumandoos a la campaña de ¡Yo también voy!

]]>
http://anabuigues.com/2011/09/03/apache-barcamp-spain-2011-%c2%bfte-lo-vas-a-perder/feed/ 6
Code Kata – FizzBuzz http://anabuigues.com/2011/03/31/code-kata-fizzbuzz/ http://anabuigues.com/2011/03/31/code-kata-fizzbuzz/#comments Thu, 31 Mar 2011 16:41:59 +0000 Ana Buigues http://anabuigues.com/?p=3437 Siguiendo con la iniciativa de 12meses12katas paso a contaros el desafío de este mes, en si el problema es muy muy sencillo, la idea es la siguiente:  para el intervalo de números entre 1 y 100, si uno de ellos resulta múltiplo de 3 o contiene un 3, el resultado debe ser la palabra “Fizz”, si el número es múltiplo de 5 o contiene un 5, el resultado debe ser la palabra “Buzz”, si el número es múltiplo tanto de 3 como de 5, el resultado debe ser “FizzBuzz”. ¿Sencillo verdad?

Bueno, nos ponemos a ello, este mes he decidio realizarla en Javascript, ya que nunca he realizado TDD sobre Javascript y tenía mucha curiosidad. Así que lo primero fué investigar que frameworks hay disponibles y para mi asombro he visto que hay muchos! como por ejemplo QUnit, jqUnit, JsUnit, YUI Test, JSTestDriver, Jspec, Inspect, Jasmine etc… yo me he decantado por Jasmine, ya que es muy sencillito de utilizar, su sintaxis es muy clara y apenas requiere configuración. Además tiene una interfaz para mostrar el resultado de los test, la podeís ver al final del post.

Como siempre recomendaros que os paséis por github del proyecto para ver las distintas soluciones que están aportando a la iniciativa.

A continuación os dejo el código de la kata

function FizzBuzz() {
};
FizzBuzz.prototype.fizz = "Fizz";
FizzBuzz.prototype.buzz = "Buzz";
FizzBuzz.prototype.say = function(number) {
 var result = "";
 if (this.isMultipleOfThree(number) || this.containsTree(number))
 result += this.fizz;
 if (this.isMultipleOfFive(number) || this.containsFive(number))
 result += this.buzz;
 if (result.length == 0)
 result += number;
 return result;
};
FizzBuzz.prototype.isMultipleOfThree = function(number) {
 return number % 3 === 0;
};
FizzBuzz.prototype.isMultipleOfFive = function(number) {
 return number % 5 === 0;
};
FizzBuzz.prototype.containsTree = function(number) {
 return number.toString().indexOf('3') != -1;
};
FizzBuzz.prototype.containsFive = function(number) {
 return number.toString().indexOf('5') != -1;
};

Los tests realizados con Jasmine

describe("FizzBuzz", function() {
 var fizzBuzz;
 beforeEach(function() {
 fizzBuzz = new FizzBuzz();
 });
 it('should return number', function() {
 expect(fizzBuzz.say(2)).toEqual('2');
 expect(fizzBuzz.say(4)).toEqual('4');
 expect(fizzBuzz.say(7)).toEqual('7');
 expect(fizzBuzz.say(19)).toEqual('19');
 });
 it('should return Fizz', function() {
 expect(fizzBuzz.say(3)).toEqual('Fizz');
 expect(fizzBuzz.say(13)).toEqual('Fizz');
 expect(fizzBuzz.say(18)).toEqual('Fizz');
 expect(fizzBuzz.say(96)).toEqual('Fizz');
 });
 it('should return Buzz', function() {
 expect(fizzBuzz.say(5)).toEqual('Buzz');
 expect(fizzBuzz.say(20)).toEqual('Buzz');
 expect(fizzBuzz.say(95)).toEqual('Buzz');
 expect(fizzBuzz.say(100)).toEqual('Buzz');
 });
 it('should return FizzBuzz', function() {
 expect(fizzBuzz.say(15)).toEqual('FizzBuzz');
 expect(fizzBuzz.say(35)).toEqual('FizzBuzz');
 expect(fizzBuzz.say(54)).toEqual('FizzBuzz');
 expect(fizzBuzz.say(75)).toEqual('FizzBuzz');
 expect(fizzBuzz.say(90)).toEqual('FizzBuzz');
 });
});

Aquí os muestro la interfaz que nos ofrece Jasmine para ver el resultado del los test:

]]>
http://anabuigues.com/2011/03/31/code-kata-fizzbuzz/feed/ 7
Un colacao muy social http://anabuigues.com/2011/03/07/un-colacao-muy-social/ http://anabuigues.com/2011/03/07/un-colacao-muy-social/#comments Mon, 07 Mar 2011 18:21:16 +0000 Ana Buigues http://anabuigues.com/?p=3417 Llevaba cierto tiempo queriendo comprar una taza para el colacao mañanero (no soy de café, ¿qué le vamos a hacer?). El problema es que quería una taza diferente, personal, algo geek y muy muy molona por lo que aunque había encontrado muchas opciones en la red ninguna terminaba de convencerme hasta que encontré avatarmugs, donde resulta que además de otros muchos tipos de tazas, pueden hacerte una personalizada con tu perfil de tu red favorita (facebook, twitter…).

En ese momento lo vi… mi perfil de twitter en mi taza… ya podía notar el calorcito de la leche en mis manos. Así que me puse manos a la obra, contacté con ellos porque tenía algunas dudas y resulta que son una empresa de valencia y además muy majos, me respondieron muy rápido y encargué mi taza. En un par de días la tenía en casa.

Al día siguiente la llevé al curro y conseguí que la taza fuese el trendin topic del día… de hecho creo que alguno ya está pensando en hacerse la suya y puede que tu también ehhhh.

Bueno ya solo queda enseñaros mi taza. Espero que os guste… y si os hacéis alguna parecida avisadme que quiero verlo!!!!!!

]]>
http://anabuigues.com/2011/03/07/un-colacao-muy-social/feed/ 11
Code Kata – RomanNumerals http://anabuigues.com/2011/02/15/code-kata-febrero-romannumerals/ http://anabuigues.com/2011/02/15/code-kata-febrero-romannumerals/#comments Tue, 15 Feb 2011 21:49:25 +0000 Ana Buigues http://anabuigues.com/?p=3391 Siguiendo con la iniciativa lanzada por 12meses12katas en la que ya participé el mes pasado realizando mi primera code kata, este mes sigo experimentando en el mundo de las katas. Recomiendo a todo programador, que si tiene un poco de tiempo (las katas se realizan en un tiempo máximo de 2 horas) que prueben la experiencia, ya que estos ejercicios te permiten mejorar la técnica de desarrollo, aplicando TDD, que implica escribir los tests primero, provocar un fallo, implementar la corrección del fallo y refactorizar.

La kata de este mes trata de resolver el problema de las conversiones entre números enteros y romanos.  Para hacer que la kata sea un reto mayor, he decido resolverla en Python que representa un poco más de dificultad que si la realizase en Java, ya que estoy más acostumbrada a programar en Java, En Python soy una principiante,  por lo que seguramente el código escrito para solucionar la kata se podría mejorar, así que sí veís algún fallo no dudeís en comentarlo!

Podeís ver las distintas soluciones que estan aportando a la iniciativa desde el github del proyecto. Os aconsejo que os paseís por ahi para ver la multitud de soluciones que se pueden dar a un mismo problema y la diversidad de lenguajes de programación con la que se resuelven.

A continuación os dejo el código de la kata

class RomanNumerals(object):
    def __init__(self):
        #inicializaciones para la conversión de entero a romano
        self.values =[ 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 ]
        self.symbols =[ "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" ]
        #inicializaciones para la conversión de romano a entero
        self.value =[ 1000, 500, 100, 50, 10, 5, 1 ]
        self.symbol = "MDCLXVI";
    def intToRoman(self, num):
        '''
            Realiza la conversión de un número entero a romano.
        '''
        output = ""
        index = 0
        #finalizamos cuando el número es 0
        while num > 0:
            while num >= self.values[index]:
                #añadimos el símbolo a la solución
                output = output + self.symbols[index]
                #restamos el valor númerico
                num = num - self.values[index]
            index = index + 1
        return output
    def romanToInt(self, num):
        '''
            Realiza la conversión de un número romano a entero
        '''
        indexSymbol = 0
        output = 0
        index = 0
        valid = True
        lastValue = 0
        while valid and index < len(num):
            #obtenemos el símbolo
            car = num[index]
            #obtenemos el índice del símbolo
            indexSymbol = self.symbol.index(car)
            if(indexSymbol >= 0):
                #sumamos su valor correspondiente
                output = output + self.value[indexSymbol]
                # si el valor es mayor que el último valor, tenemos que restar el último valor sumado
                if self.value[indexSymbol] > lastValue:
                    output = output - 2 * lastValue
                lastValue = self.value[indexSymbol]
            else:
                valid = False
            index = index + 1
        return output

Con su correspondiente test

import unittest
from RomanNumerals import RomanNumerals
class Test(unittest.TestCase):
    def setUp(self):
        self.roman = RomanNumerals()
    def testSimple(self):
        self.checkConversion(1,"I")
        self.checkConversion(4,"IV")
        self.checkConversion(5,"V")
        self.checkConversion(9,"IX")
        self.checkConversion(10,"X")
        self.checkConversion(40,"XL")
        self.checkConversion(50,"L")
        self.checkConversion(90,"XC")
        self.checkConversion(100,"C")
        self.checkConversion(400,"CD")
        self.checkConversion(500,"D")
        self.checkConversion(900,"CM")
        self.checkConversion(1000,"M")
    def testTens(self):
        self.checkConversion(11,"XI")
        self.checkConversion(12,"XII")
        self.checkConversion(13,"XIII")
        self.checkConversion(14,"XIV")
        self.checkConversion(19,"XIX")
        self.checkConversion(20,"XX")
        self.checkConversion(24,"XXIV")
        self.checkConversion(31,"XXXI")
        self.checkConversion(38,"XXXVIII")
        self.checkConversion(45,"XLV")
        self.checkConversion(71,"LXXI")
        self.checkConversion(87,"LXXXVII")
        self.checkConversion(99,"XCIX")
    def testHundreds(self):
        self.checkConversion(109,"CIX")
        self.checkConversion(203,"CCIII")
        self.checkConversion(303,"CCCIII")
        self.checkConversion(304,"CCCIV")
        self.checkConversion(450,"CDL")
        self.checkConversion(546,"DXLVI")
        self.checkConversion(671,"DCLXXI")
        self.checkConversion(788,"DCCLXXXVIII")
        self.checkConversion(888,"DCCCLXXXVIII")
        self.checkConversion(999,"CMXCIX")
    def testThousands(self):
        self.checkConversion(1010,"MX")
        self.checkConversion(1111,"MCXI")
        self.checkConversion(1234,"MCCXXXIV")
        self.checkConversion(2342,"MMCCCXLII")
        self.checkConversion(2999,"MMCMXCIX")
    def checkConversion(self,numeral, roman):
        self.assertEquals(roman, self.roman.intToRoman(numeral))
        self.assertEquals(numeral, self.roman.romanToInt(roman))
if __name__ == "__main__":
    unittest.main()

]]> http://anabuigues.com/2011/02/15/code-kata-febrero-romannumerals/feed/ 5 Cómo configurar Hibernate sin ningún xml http://anabuigues.com/2011/02/07/como-configurar-hibernate-sin-ningun-xml/ http://anabuigues.com/2011/02/07/como-configurar-hibernate-sin-ningun-xml/#comments Mon, 07 Feb 2011 17:56:12 +0000 Ana Buigues http://anabuigues.com/?p=3359 Realizar la configuración de Hibernate con ficheros xml puede llegar a ser bastante engorroso, especialmente en aplicaciones muy grandes. Afortunadamente podemos inicializar la unidad de persistencia de forma programática y realizar los mapeos de las entidades mediante anotaciones, de esta forma conseguimos no tener que utilizar ningún fichero xml para la configuración.

A continuación un ejemplo de cómo hacerlo.

Creación de la unidad de persistencia:

public class PersistenceUnitStarter {
	//Añadimos las propiedades que queramos a la unidad de persistencia
	private static Properties getProperties() {
		Properties properties = new Properties();
		properties.setProperty(Environment.DRIVER, "org.h2.Driver");
		properties.setProperty(Environment.URL,
				"jdbc:h2:db;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0");
		properties.setProperty(Environment.USER, "");
		properties.setProperty(Environment.PASS, "");
		properties.put(Environment.SHOW_SQL, "true");
		properties.put(Environment.FORMAT_SQL, "true");
		properties.put(Environment.FLUSH_BEFORE_COMPLETION, "false");
		properties.put(Environment.TRANSACTION_STRATEGY,
				PersistenceUnitTransactionType.RESOURCE_LOCAL);
		properties.put(Environment.HBM2DDL_AUTO, "create");
		return properties;
	}
        //Le pasamos una lista con las clases que queremos añadir a la entidad de persistencia
        //Las clases tienen que estar definidas con anotaciones
	public static EntityManagerFactory createPersistenceUnit(List<Class> entities) {
		Ejb3Configuration conf = new Ejb3Configuration();
		conf.addProperties(getProperties());
		//añadimos los entities declarados con anotaciones
		for (Class clazz : entities) {
			conf.addAnnotatedClass(clazz);
		}
		return conf.buildEntityManagerFactory();
	}
}

Creamos las entidades mediante anotaciones

@Entity
public class Persona {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;
	@Column(nullable = false)
	private String nombre;
	@Column(nullable = false)
	private String apellido;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getNombre() {
		return nombre;
	}
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	public String getApellido() {
		return apellido;
	}
	public void setApellido(String apellido) {
		this.apellido = apellido;
	}
}
]]>
http://anabuigues.com/2011/02/07/como-configurar-hibernate-sin-ningun-xml/feed/ 3
Mi primera Code Kata http://anabuigues.com/2011/02/01/mi-primera-code-kata/ http://anabuigues.com/2011/02/01/mi-primera-code-kata/#comments Tue, 01 Feb 2011 17:40:00 +0000 Ana Buigues http://anabuigues.com/?p=3344 Ayer hice junto a Héctor Rodes mi primera Code Kata, gracias a la iniciativa de 12meses12katas, donde cada mes se propone una nueva kata. Abierta a todo el mundo y a todos los lenguajes de programación, excelente para poder practicar y aprender.

Y…¿qué es una Code Kata? pues una Code Kata hace referencia a un ejercicio de programación en el cual se resuelve un problema más o menos complejo donde el objetivo es mejorar las cualidades de un programador mediante la práctica y resolución repetitiva de problemas.

Lo que obtenemos de todo esto es obligarnos a encontrar una solución a un problema y además nos permite contrastar nuestra solución con la de otras personas, de esta forma podemos descubrir nuevas formas de resolver el mismo problema, y si la programas en parejas es todavía más divertido.

Para Enero el ejercicio de la Code Kata era el String Calculator, la idea es hacer un programa que sume  los números de una cadena separados por diferentes delimitadores, por ejemplo: “8*5%3″ . Si queréis ver el código de la gente que ha realizado la Code Kata podéis visitar el github del proyecto. El nuestro está en el directorio de animalaes.

Nuestra solución

La hemos realizado en Java, con la ayuda de la clase Scanner de Java para parsear la cadena mediante expresiones regulares. Se admiten sugerencias sobre mejoras o lo que sea.

package com.anabuigues;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Pattern;
/**
 * Implementación sencilla de la calculadora para la kata de enero.<br />
 * <br />
 * La implementación está realizada usando java 6 estándar apoyándose en la
 * clase Scanner que permite trocear al vuelo un imput a partir de un o n
 * delimitadores. Para ello extrae los delimitadores y construye una expresión
 * reguar válida para el scanner al que se le solicitan los diferentes enteros
 * para ir sumándolos.
 *
 *
 * @author A. Buigues (@animalaes), H. Rodes (@hector_rodes)
 *
 */
public class StringCalculator {
	public int add(String numbers) throws Exception {
		int returnValue;
		if (numbers == null || numbers.isEmpty()) {
			returnValue = 0;
		} else {
			ByteArrayInputStream bais = new ByteArrayInputStream(
					numbers.getBytes());
			Scanner sc = new Scanner(bais);
			String delimiters = null;
			// Delimiters
			if (numbers.startsWith("//")) {
				sc.useDelimiter("//|\n");
				if (sc.hasNext()) {
					delimiters = sc.next();
				}
			}
			delimiters = getScannerFormattedDelimiters(delimiters);
			// Process number lines with numbers to be added
			sc.useDelimiter(delimiters);
			int sum = 0;
			int currentNumber;
			List<Integer> negativeValues = new ArrayList<Integer>();
			while (sc.hasNext()) {
				currentNumber = sc.nextInt();
				if (currentNumber < 0) {
					negativeValues.add(currentNumber);
				} else if (currentNumber <= 1000) {
					sum += currentNumber;
				}
			}
			checkNegativeValues(negativeValues);
			returnValue = sum;
		}
		return returnValue;
	}
	/**
	 * Método auxiliar que comprueba si hay números negativos y forma el mensaje
	 *
	 * @param negativeValues
	 *            Lista de números negativos
	 * @throws Exception
	 *             Si la lista de números negativos contiene algún número
	 */
	private void checkNegativeValues(List<Integer> negativeValues)
			throws Exception {
		if (negativeValues != null && negativeValues.size() > 0) {
			StringBuilder sb = new StringBuilder("negatives not allowed");
			for (int negative : negativeValues) {
				sb.append(" ").append(negative);
			}
			throw new Exception(sb.toString());
		}
	}
	/**
	 * Genera la cadena de delimitadores necesaria para ser usada en el scanner
	 * y así poder procesar los números.<br />
	 * Siempre introduce el \n como un delimitador válido.<br />
	 * En caso de que los delimiters sean vacÌos o nulos usa la , y el \n como
	 * delimitadores por defecto
	 *
	 * @param delimiters
	 *            Los delimitadores introducidos
	 * @return Cadena con los delimitadores en el formato que espera el Scanner
	 */
	private String getScannerFormattedDelimiters(String delimiters) {
		String delimitersExpression;
		if (delimiters == null || delimiters.isEmpty()) {
			delimitersExpression = ",|\n";
		} else {
			String currentDelimiter;
			StringBuilder sb = new StringBuilder();
			Scanner scDelimiters = new Scanner(delimiters).useDelimiter(Pattern
					.quote("]") + "|" + Pattern.quote("["));
			while (scDelimiters.hasNext()) {
				currentDelimiter = scDelimiters.next();
				if (!currentDelimiter.isEmpty()) {
					sb.append(Pattern.quote(currentDelimiter)).append("|");
				}
			}
			sb.append("\n");
			delimitersExpression = sb.toString();
		}
		return delimitersExpression;
	}
}

Y su test

package com.anabuigues;
import junit.framework.Assert;
import org.junit.Test;
/**
 *
 * @author A. Buigues (@animalaes), H. Rodes (@hector_rodes)
 *
 */
public class CalculatorTest {
	private StringCalculator calculator = new StringCalculator();
	@Test
	public void basicCalculator() throws Exception {
		Assert.assertEquals(0, calculator.add(""));
		Assert.assertEquals(1, calculator.add("1"));
		Assert.assertEquals(10, calculator.add("7,3"));
		Assert.assertEquals(10, calculator.add("7\n2,1"));
		Assert.assertEquals(27, calculator.add("5\n5\n8,2,4\n2,1"));
	}
	@Test
	public void simpleDelimiterCalculator() throws Exception {
		Assert.assertEquals(16, calculator.add("//[*]\n5*5*6"));
		Assert.assertEquals(20, calculator.add("//[*]\n5*5*6\n4"));
		Assert.assertEquals(20, calculator.add("//[*][;][,]\n5,5;6\n4"));
		Assert.assertEquals(20,
				calculator.add("//[*][;][pollofrito]\n5pollofrito5;6\n4"));
	}
	@Test
	public void bigNumbersCalculator() throws Exception {
		Assert.assertEquals(1005, calculator.add("//[*]\n5*1000*1001"));
	}
	@Test
	public void negativeNumbersCalculator() throws Exception {
		try {
			Assert.assertEquals(1005, calculator.add("//[*]\n5*-23*45*-34"));
		} catch (Exception e) {
			Assert.assertTrue("-23 must be in error message ", e.getMessage()
					.indexOf("-23") != -1);
			Assert.assertTrue("-34 must be in error message ", e.getMessage()
					.indexOf("-34") != -1);
		}
	}
	@Test
	public void notDefinedDelimiterCalculator() throws Exception {
		try {
			Assert.assertEquals(8, calculator.add("//[*]\n5;3"));
			Assert.fail("Delimiter ; is not allowed but it has been used");
		} catch (Exception e) {
		}
	}
}

Ahora toca ponerse con la de febrero!!

]]> http://anabuigues.com/2011/02/01/mi-primera-code-kata/feed/ 4 Feliz Navidad y Próspero Año Nuevo 2011 http://anabuigues.com/2010/12/25/feliz-navidad-y-prospero-ano-nuevo-2011/ http://anabuigues.com/2010/12/25/feliz-navidad-y-prospero-ano-nuevo-2011/#comments Sat, 25 Dec 2010 18:45:05 +0000 Ana Buigues http://anabuigues.com/?p=3313 Espero que paséis una Feliz Navidad y desearos lo mejor para el año 2011, que el nuevo año sea mucho mejor que el pasado y que todos los deseos se cumplan.

]]> http://anabuigues.com/2010/12/25/feliz-navidad-y-prospero-ano-nuevo-2011/feed/ 0 The Big Bang Theory, la mejor serie de humor que he visto http://anabuigues.com/2010/11/07/the-big-bang-theory-la-mejor-serie-de-humor-que-he-visto/ http://anabuigues.com/2010/11/07/the-big-bang-theory-la-mejor-serie-de-humor-que-he-visto/#comments Sun, 07 Nov 2010 13:27:06 +0000 Ana Buigues http://anabuigues.com/?p=3174 Cuando vi el primer capítulo de la serie me dije… ufff, creo que es demasiado friki incluso para mi, aún así, continué viéndola ya que por lo que había leído de la serie la ponían como muy buena. Después de unos cuantos capítulos ya no podía parar!!!

The Big Bang Theory narra la vida de Sheldon y Leonard, dos jóvenes científicos que comparten piso y trabajan en el mismo lugar. Son algo frikis, sabiondos e inteligentes, pero cuando tienen que tratar con la gente normal son algo patosos y cortitos. Tienen dos amigos Howard y Raj que son del mismo estilo. Entonces aparece Penny, una chica sociable, muy normal y con cuerpo de escándalo, es por ello que a Leonard le entra por el ojo nada más verla.

La serie va contando la historia de éstas cinco personas repleta de situaciones y comentarios frikis de lo más graciosos, combinando terminología científica sin ningún sentido con referencias del mundo real. El humor de la serie no está destinado para cualquier tipo de público, más que nada por las continuas referencias frikis que alguna gente no entenderá y por consiguiente no le harán gracia. Pero aún así yo os recomiendo que le deis una oportunidad, es una serie fresca y entretenida, con un argumento que engancha.

Algo que llama la atención enseguida es el desfile de camisetas frikis que hay en la serie. Sobre todo las que lleva Sheldon, fijaos en la camiseta de flash de la foto :D . Han causado tanto furor entre los fans que hay páginas centradas solo en esas camisetas como la que podéis encontrar aquí.

En este blog podéis estar al día de todo sobre la serie.

Y ya para despedirme os digo una de las frases de Sheldom con las que intenta hacerse el gracioso y que más me gusta de la serie “ZAS!! EN TODA LA BOCA!”

]]>
http://anabuigues.com/2010/11/07/the-big-bang-theory-la-mejor-serie-de-humor-que-he-visto/feed/ 9
Comparator vs Comparable en Java http://anabuigues.com/2010/09/17/comparator-vs-comparable-en-java/ http://anabuigues.com/2010/09/17/comparator-vs-comparable-en-java/#comments Fri, 17 Sep 2010 16:17:12 +0000 Ana Buigues http://anabuigues.com/?p=1145 Diferencia entre Comparable y Comparator

La diferencia principal entre Comparable y Comparator es que Comparable es utilizado para implementar el orden natural, sin necesidad de especificar un Comparator, por ejemplo, los String son comparados alfabéticamente. Usamos Comparator cuando queramos crear otro tipo de orden que no sea el natural.

El contrato que implica implementar Comparable requiere de un parámetro extra, el objeto con el que comparar compareTo(obj1) de forma que la comparación se realizará del objeto en si (this) con el objeto pasado como parámetro. Comparator, sin embargo obliga a implementar el método compare (obj1, obj2) de forma que los dos objetos a comparar son pasados como parámetros y el objeto que implementa el método compare simplemente sirve de apoyo a la comparación.

Sobreescritura de los métodos compareTo y compare

La forma de sobreescribir estos métodos es muy similar al equals. Los dos métodos cumplen las mismas restricciones que podemos objtener del API de Java:

  • Devolvemos un número negativo si el objeto es menor, devolvemos un cero si es igual y un número positivo si el objeto es mayor.
  • Comparamos el objeto con otro objeto del mismo tipo. Si no son del mismo tipo, lanzamos un ClassCastException.

La notación sgn(expresion) es la función matemática signum, la cual devuelve -1,0, o 1  según sea negativo, zero o positivo

  • Debemos asegurar que: sgn(compare(x,y)) == -sgn(compare(x,y)), para todo x, y. Esto implica que compare(x,y)) lanzará una excepción sii compare(x,y) también la lanza.
  • Debemos asegurar que la relación es transitiva: compare(x,y) > 0 && compare(y,z) > 0 implica que compare(x,z) > 0
  • Debemos asegurar que: compare(x,y) == 0 implica que sgn(compare(x,z)) == sgn(compare(y,z)), para todo z.
  • Se recomienda, aunque no es estrictamente neceario, nos puede evitar poblemas al usar colecciones que implementen esta interfaz. (compare(x,y) == 0) == (x.equals(y))
  • El orden natural para una clase “c”  tiene que ser consistente con el equals si y solo sí: compare(e1,e2) == 0 tiene que ser el mismo resultado que para e1.equals(e2) para cada e1 y e2 de la clase “c”.

Uso de Comparable y Comparator

Podemos usarlos en listas y arrays mediante los métodos Collections.sort y Arrays.sort.También como claves en un mapa ordenado TreeMap o como elementos en un set ordenado TreeSet.

En el caso de Comparable los objetos tienen que implementar esta interfaz para que los ordene automáticamente. Para el caso del Comparator debemos especificar el Comparator.

Ejemplo Comparable

//Ejemplo Comparable
public class Person implements Comparable<Person> {
 private String firstName;
 private String lastName;
 public Person(String firstName, String lastName) {
  if (firstName == null || lastName == null)
   throw new NullPointerException();
  this.firstName = firstName;
  this.lastName = lastName;
 }
 @Override
 public String toString() {
  return String.format("%s, %s", firstName, lastName);
 }
 @Override
 public int compareTo(Person p) {
  int lastCmp = firstName.compareTo(p.firstName);
  return (lastCmp != 0 ? lastCmp : lastName.compareTo(p.lastName));
 }
 public static void main(String[] args) {
  Set<Person> p = new TreeSet<Person>();
  p.add(new Person("Ana", "Rodes"));
  p.add(new Person("Hector", "Lopez"));
  p.add(new Person("Ana", "Buigues"));
  p.add(new Person("Carlitos", "Perez"));
  for (Person person : p)
   System.out.println(person);
 }
}

La salida será:
Ana, Buigues
Ana, Rodes
Carlitos, Perez
Hector, Lopez

Ejemplos Comparator

//Ejemplo Comparator
public class LengthComparator implements Comparator<Person> {
 @Override
 public int compare(Person p1, Person p2) {
  if (p1.toString().length() < p2.toString().length())
   return 1;
  else if (p1.toString().length() > p2.toString().length())
   return -1;
  else
   return 0;
 }
 public static void main(String[] args) {
  List<Person> p = new ArrayList<Person>();
  p.add(new Person("Ana", "Rodes"));
  p.add(new Person("Hector", "Lopez"));
  p.add(new Person("Ana", "Buigues"));
  p.add(new Person("Carlitos", "Perez"));
  Collections.sort(p, new LengthComparator());
  for (Person person : p)
   System.out.println(person);
 }
}

La salida será:
Ana, Rodes
Ana, Buigues
Hector, Lopez
Carlitos, Perez

También lo podemos utilizar de forma anónima

Set<Person> persons = new TreeSet<Person>(new Comparator<Person>() {
  @Override
 public int compare(Person p1, Person p2) {
  if (p1.toString().length() < p2.toString().length())
   return 1;
  else if (p1.toString().length() > p2.toString().length())
   return -1;
  else
   return 0;
 }
});
]]>
http://anabuigues.com/2010/09/17/comparator-vs-comparable-en-java/feed/ 23
La mala educación http://anabuigues.com/2010/09/10/la-mala-educacion/ http://anabuigues.com/2010/09/10/la-mala-educacion/#comments Fri, 10 Sep 2010 21:07:50 +0000 Ana Buigues http://anabuigues.com/?p=1148 El otro día estaba desayunando en un bar cercano a mi trabajo cuando la dueña empezó contarme lo caro que le había salido la vuelta al cole. La mujer me comentaba que los libros de texto para sus dos hijos le habían costado sobre los 700€, además de tener que comprar todo el material que el colegio les exigía, que si lápices de la punta tal, que si libretas con el cuadrado de tipo canario etc… por lo que no podía comprar cualquier tipo de libreta de 0’60€ Tampoco entendía porque a su hijo pequeño no le servían los libros del mayor y tenía que volver a comprarlos, con lo que le suponía más gasto cuando en realidad ya había pagado por unos libros similares para su hijo mayor.

La realidad es así de cruda, cada año escolar que empieza para las familias es todo un problema y más aún en la crisis en la que estamos. ¿Por qué no sirven los libros de un año para otro? ¿Tanto cambia geografía española como para tener que cambiar el libro de un año para el siguiente? Además, ¿Qué hacemos con los libros viejos? Mis libros del colegio y bachillerato están en un cajón guardados muertos de risa y sin usar.

¿Existe una verdadera necesidad de cambiar los libros con tanta frecuencia? ¿No se podría idear un sistema de reutilización de los libros? Ahh no, claro que no, así las editoriales de que vivirian? Desde mi punto de vista es un gran lastre que arrastramos desde hace muchos años y que nos lleva a no avanzar. Se supone que estamos en la era digital, ¿por qué no hacemos como los estadounidenses y nos pasamos a los libros digitales?

Nos dirigimos hacia un gran cambio en el sistema educativo, queramos o no, la tecnología impulsará mejoras en la educación, los estudiantes ya no irán con 10 libros en su mochila, sino simplemente con un mini-ordenador (ipad, tablet…) que les permitirá acceder a todo lo necesario su aprendizaje en un instante, porque yo también sueño con una eduación 2.0.

]]>
http://anabuigues.com/2010/09/10/la-mala-educacion/feed/ 9
Cómo sobreescribir los métodos equals y hashCode de Java http://anabuigues.com/2010/07/06/como-sobreescribir-los-metodos-equals-y-hashcode-de-java/ http://anabuigues.com/2010/07/06/como-sobreescribir-los-metodos-equals-y-hashcode-de-java/#comments Tue, 06 Jul 2010 20:18:23 +0000 Ana Buigues http://anabuigues.com/?p=1051 En la clase java.lang.Object (y por lo tanto, por herencia, en todas las demás clases) tenemos métodos que a veces olvidamos y que son importantes:

  • public boolean equals(Object o)
  • public int hashCode()

Estos métodos son especialmente importantes si vamos a guardar nuestros objetos en cualquier tipo de colección: listas, mapas… y más aun si los objetos que vamos a guardar en la colección son serializables.

Estos métodos tienen formas explicitas de cómo hay que implementarlos. Sobreescribir estos métodos puede parecer simple, pero en realidad hay muchas formas de hacerlo incorrectamente lo que nos puede llevar a muchos crebraderos de cabeza. Lo vemos a continuación.

Sobreescribir el método equals

Cuando sobreescribimos el método equals tenemos que tener en cuenta lo que se especifica en el API de Java para Object sobre este método. Debe cumplir las siguientes propiedades:

  • Reflexiva: para cualquier referencia no nula para un valor x, x.equals(x) debe devolver true.
  • Simétrica: para cualquier referencia no nula para valores x e y, x.equals(y) debe devolver true sii y.equals(x) devuelve true.
  • Transitiva: para cualquier referencia no nula para valores x, y,z, si x.equals(y) devuelve true y y.equals(z) devuelve true, entonces x.equals(z) debe devolver true.
  • Consistente: para cualquier referencia no nula para valores x e y, múltiples llamadas al método x.equals(y) deben consistentemente devolver siempre true o consistentemente devolver false. Siempre y cuando no se modifique la información usada en las comparaciones.
  • No nulo: para cualquier referencia no nula para un valor x, x.equals(null) debe devolver false.

Ahora que sabemos lo que tiene que cumplir, vamos a ver que pasos podemos seguir para su implementación:

  • Usamos el operador == para comprobar si el argumento es una referencia al mismo objeto.
  • Usamos el operador instanceof para comprobar si el argumento es un objeto de nuestra clase.
  • Hacemos un cast del argumento al nuestro objeto. Ya sabemos que es una instancia de nuestro objeto, por el paso anterior.
  • Para cada campo significativo de nuestro objeto, comprobamos que se corresponda con el que se pasa como argumento. Primero comprobamos los tipos primitivos y luego los más complejos. Para los tipos Float y Double, usamos los métodos Float.Compare y Double.Compare. Para el tipo String, usamos el equals del string. Para comparar arrays usamos Arrays.equals. Tenemos que tener en cuenta que los campos pueden contener referencias a null. No debemos incluir campos que tengan que ver con el estado de un objeto, como por ejemplo tipos Lock. Tampoco tenemos que incluir campos que sean cálculos de otros campos, es redundante.
  • Cuando terminemos, tenemos que preguntarnos: ¿es reflexivo?, ¿es simétrico?, ¿es transitivo?, ¿es consistente? y ¿no nullo?
//Ejemplo de cómo sobreescribir el método equals()
public class Casa {
 private int num;
 private String direccion;
 private double precio;
 private List<Propietario> prop;
 public Casa(int num, String direccion, double precio,
            List<Propietario> prop) {
  this.num = num;
  this.direccion = direccion;
  this.precio = precio;
  this.prop = prop;
 }
 @Override
 public boolean equals(Object o) {
  if (o == null)
   return false;
  if (o == this)
   return true;
  if (!(o instanceof Casa))
   return false;
  Casa c = (Casa) o;
  if (num != c.num)
   return false;
  if (direccion == null || !direccion.equals(c.direccion))
   return false;
  if (Double.compare(precio, c.precio) != 0)
   return false;
  if (prop != c.prop && (prop == null || !prop.equals(c.prop)))
   return false;
 return true;
 }
}
public class Propietario {
 private String nombre;
 private String apellidos;
 private int num;
 public Propietario(String nombre, String apellidos, int num) {
  this.nombre = nombre;
  this.apellidos = apellidos;
  this.num = num;
 }
 @Override
 public boolean equals(Object o) {
  if (o == null)
   return false;
  if (o == this)
   return true;
  if (!(o instanceof Propietario))
   return false;
  Propietario p = (Propietario) o;
  if ((nombre == null) ? (p.nombre != null) : !nombre.equals(p.nombre))
    return false;
  if ((apellidos == null) ? (p.apellidos != null) :
     !apellidos.equals(p.apellidos))
    return false;
  if (num != p.num)
    return false;
  return true;
 }
}

Sobreescribir el método hashCode

Siempre que sobreescribamos el método equals, también tenemos que sobreescribir también el método hashCode. En el API de java para Object del método hashCode se especifica lo siguiente:

  • Cuando este método es invocado sobre el mismo objeto una o más veces durante una ejecución en una aplicación, el hashCode debe de ser consistente devolviendo siempre el mismo valor, siempre que no se modifique el objeto. Este valor no tiene que ser consistente entre ejecuciones distintas de la aplicación.
  • Si dos objetos son iguales segun el método equals, entonces el hashCode de los dos objetos tiene que ser el mismo.
  • Si dos objetos no son iguales, el hashCode no tiene que ser necesariamente distinto, pero es recomendable que lo sea.

Unos pasos para implementar un buen método hashCode son:

  • Declaramos una variable entera y le asignamos un número, por ejemplo result=17.
  • Para cada campo significativo de nuestro objeto, f:
    • Calculamos en int c el valor de:
      • Tipo boolean: hacemos (f?1 : 0)
      • Tipos byte, char, short, o int: hacemos (int) f
      • Tipo Long: hacemos (int)(f^(f>>>32))
      • Tipo Float: hacemos Float.doubleToIntBits(f)
      • Tipo Double: hacemos Double.doubleToLongBits(f) (int)(f^(f>>>32))
      • Si es una referencia a un objeto, llamamos al hashCode del objeto. Si la referencia es nula, devolvemos un 0.
      • Si es un Array, utilizamos el método Arrays.hashCode.
    • Acumulamos el valor de c en result : result = 31 * result + c
  • Devolvemos el valor de result

Podemos excluir los campos que no comprobemos en el método equals, pero no es recomendable.

//Ejemplo de cómo sobreescribir el método hashCode
@Override
public int hashCode() {
  int result = 17;
  result = 31 * result + num;
  result = 31 * result + (direccion != null ?
           direccion.hashCode() : 0);
  result = 31 * result + (int) (Double.doubleToLongBits(precio)
           ^((Double.doubleToLongBits(precio) >>> 32));
  result = 31 * result + (propietarios != null) ?
           propietarios.hashCode() : 0);
 return result;
 }

Fuente: Libro Effective Java de Joshua Bloch

]]>
http://anabuigues.com/2010/07/06/como-sobreescribir-los-metodos-equals-y-hashcode-de-java/feed/ 14
Técnicas de explotación de un Data Warehouse http://anabuigues.com/2010/06/16/tecnicas-de-explotacion-de-un-data-warehouse/ http://anabuigues.com/2010/06/16/tecnicas-de-explotacion-de-un-data-warehouse/#comments Wed, 16 Jun 2010 15:44:46 +0000 Ana Buigues http://anabuigues.com/?p=407 La construcción de un data warehouse es un medio, no un fin en sí mismo. El fin es la necesidad de realizar análisis y toma de decisiones a través del uso de esa fuente de datos.

Dependiendo de lo requisitos de análisis que planteé la explotación, podemos hablar de diferentes técnicas:

1. Query & Reporting

Consulta y reporte es el término general para referirse a una técnica de explotación de bases de datos que ofrece a las organizaciones acceso a medida a los datos (query) y capacidades de construcción de informes (reporting) para los usuarios finales. Estos informes incluyen datos de detalle, de gran volumen y con un formato que soporta imágenes, varios tipos de gráficos, tablas, etc, que pueden ser consultados por herramientas de usuario final.

Permite:

  • A los usuarios poco expertos solicitar la ejecución de informes o consultas según unos parámetros determinados.
  • A los usuarios con cierta experiencia hacer consultas más flexibles mediante una aplicación que proporcione una interfaz gráfica de ayuda.
  • A los usuarios altamente experimentados puedan escribir, total o parcialmente la consulta en un lenguaje de interrogación de datos.

2. Análisis multidimensional OLAP

Se define OLAP como la consolidación, visualización y el análisis de datos de acuerdo con múltiples dimensiones. Se puede hablar de OLAP como de una tecnología de explotación de bases de datos que facilita la visualización y el análisis multidimensional de los datos.

El análisis multidimensional consiste en analizar los datos que hacen referencia a hechos desde la perspectiva de sus componentes o dimensiones, abarcando también los diferentes niveles que puedan tener las respectivas dimensiones.

El análisis multidimensional se apoya en una visión conceptual multidimensional (cubo o hipercubo) de los datos para permitir a los sistemas OLAP:

  • Soportar requisitos complejos de análisis.
  • Analizar datos desde diferentes perspectivas (dimensiones)
  • Soportar análisis contra un volumen considerable de datos.

Representación de los datos mediante un cubo OLAP:

3. Data Mining

El término data mining o minería de datos se utiliza para hacer referencia a una técnica de análisis de datos cuyo objetio principal es el descubrimiento de conocimiento que se encuentra en los datos y que no es apreciable de manera directa. La minería de datos supone la búsqueda de similitudes, patrones generales y en general relaciones no obvias en los datos, con el objetivo de transformar la información disponible en conocimiento útil de negocio.

El data mining en vez de basarse en métricas de negocio o en información altamente agregada, explota la información detallada del almacén de datos.

No siempre es necesario disponer de un data warehouse para hacer data mining, pero aporta al data mining una fuente de datos de mayor calidad para poder trabajar.

]]>
http://anabuigues.com/2010/06/16/tecnicas-de-explotacion-de-un-data-warehouse/feed/ 1
Yo fuí al Rock in Rio Madrid 2010 http://anabuigues.com/2010/06/08/yo-fui-al-rock-in-rio-madrid-2010/ http://anabuigues.com/2010/06/08/yo-fui-al-rock-in-rio-madrid-2010/#comments Tue, 08 Jun 2010 17:17:57 +0000 Ana Buigues http://anabuigues.com/?p=949 El pasado fin de semana estuve en el Rock in Rio, un festival a lo grande que no pasa desapercibido y en el que disfruté mucho. A continuación relato un poco lo que vi, oí , me gustó, me disgustó… en definitiva una pequeña visión en primera persona de este festival.

Para comenzar diré quse el recinto es enorme, cuenta con 200.000 m2 de superficie, tres escenarios, multitud de zonas donde comprar comida y bebida, áreas comerciales y zonas de césped. También tiene dos atracciones, una tirolina que pasa por delante del escenario mundo, y una noria en la que puedes ver toda la ciudad del rock desde arriba.

El viernes pasado día 4, llegamos a la ciudad del rock temprano, teníamos muchas ganas de ver lo que nos esperaba esa noche. Después de comer algo, nos plantamos en el escenario mundo a la espera de la primera actuación. Los encargados de inaugurar la jornada fueron Macaco, el concierto fué de lo más animado, con mucha participación del público, todos bailamos al son de su exito “Moving”

http://www.youtube.com/watch?v=836r2m2kzOQ

Con un poco de retraso debido a problemas técnicos con el sonido, empezó la actuación de Pereza, por ello tocaron un tema tras otro casi sin descanso. Cantaron junto Ariel Rot y Carlos Tarque el tema “Hace calor”

http://www.youtube.com/watch?v=WP3pm54Lp1k

Y ya, el gran bombazo de la noche, la esperada actuación del grupo Bon Jovi, después de 8 años sin visitar España, se llevarón la palma. El concierto no defraudó a nadie. Se nota que es un grupo que tiene años de experiencia, lo dan todo en un concierto y transmiten sus ganas al público haciendo que la gente disfrute muchísimo. Junto con Richie Sambora ofrecieron un espectáculo muy bueno. El concierto terminó con el tema “Livin’ on a Player”

http://www.youtube.com/watch?v=ESCEmUJhyTQ

El cierre de la jornada del escenario mundo le tocó a el dj alemán Paul Van Dyk. Está en puesto 6 del top-ten de los mejores djs del mundo.

http://www.youtube.com/watch?v=vrF__xgKYVY

El sábado fué repetición de la jugada, pero esta vez con mucha más gente en el recinto que el día anterior. Los encargados de abrir el escenario mundo fueron Calle 13, con sus canciones atrevidas y ritmos variados,  hicieron que todas las voces fueran una. Terminaron con el tema “Atrevete-tete”

http://www.youtube.com/watch?v=K9EuS5zQcDw

Ya estabamos más que impacientes cuando por fin apareció Rihanna en el escenario y estalló la locura. Nos sorprendió a todos con su nuevo corte de pelo, corto, rapado por detrás y teñido de color rojo. Iba semi-vestida con un body que llevaba un sujetador de pico que recordaba a los que utilizaba Madonna en sus inicios. Tuvo muchos cambios de zapatos, desde unos taconazos excesivos hasta unas botas para moverse más fácilmente. Sin lugar a dudas, fue el mayor espectáculo, acompañada de sus bailarines ofreció una gran puesta en escena. El tema “Disturbia” fué el que más impresionó

http://www.youtube.com/watch?v=NiP01zW2kjA

Y empieza el concierto de Shakira, la gente se vuelve completamente loca al verla comenzando a golpe de caderas mientras suena con “Ojos”. Esta radiante de felicidad y la gente también. Todos aullamos el tema de “Loba”.

http://www.youtube.com/watch?v=w9VHxSxC1iQ

El encargado de cerrar la jornada en el escenario mundo fue David Guetta, que últimamente se ha puesto muy de moda en españa. Todos brincamos sus temas, al igual que hicieron un par de robots luminosos en el escenario que tiraban humo y fuego por unas pistolas. Está en el puesto 3 del top-ten de los mejores djs del mundo. Se despidió con el tema de Black Eyes Peace “I gotta feeling”

http://www.youtube.com/watch?v=FrKITDP1IhM

Bueno, hasta aquí todo lo bueno, los conciertos dieron la talla, pero la organización no tanto. El primer día los conciertos se retrasaron unos 30 minutos, pero el sábado Shakira empezó una hora y media más tarde de lo que estaba previsto, es una barbaridad, sobre todo teniendo en cuenta que llevas allí desde las 9 de la tarde de pie. También el primer día pagamos la novatada, dado que no se podía entrar comida ni bebida al recinto, no te quedaba otra que cenar allí, así que nos pedimos unos bocatas para cenar, que en principio no tendrían porque estar malos y por la pinta no lo parecía… pero lo mejor fué cuando nos dimos cuenta que dentro del bocata nos habían incluido el helado de postre!!! estaban llenos de trozos de hielo, puff.

Otra cosa que me parece increible es que sabiendo la cantidad de gente que se espera para un evento de este tipo no habria más de unas 30 papeleras en todo el recinto, así que os podeís imaginar la forma en que los desperdicios se iban acumulando, tenías que ir pisando el suelo con cuidado de no tropezar de la cantidad de basura que estaba esparcida por el suelo. Además también otro punto crítico fueron los asesos, que más que aseos, como es de esperar son las casetas de plástico, lo mejor es que esos aseos no tenían agua corriente para estirar cuando uno termina, sino que se iba amontonando… así que os podeís imaginar el mal olor que hacian en seguida, y más con el calor que hacia!!!

Bueno a pesar de todo, redactando la entrada y viendo los videos puedo decir que se me ha puesto la piel de gallina recordando los momentos, y por supuesto Yo voy al Rock in Rio 2012!!!

]]>
http://anabuigues.com/2010/06/08/yo-fui-al-rock-in-rio-madrid-2010/feed/ 3
Lie To Me: Miénteme, una serie que deberías ver http://anabuigues.com/2010/05/22/lie-to-me-mienteme-una-serie-que-deberias-ver/ http://anabuigues.com/2010/05/22/lie-to-me-mienteme-una-serie-que-deberias-ver/#comments Sat, 22 May 2010 18:04:34 +0000 Ana Buigues http://anabuigues.com/?p=930 En semana santa, una amiga me recomendó ver la serie Lie To Me, en español Miénteme y ahora yo también os la recomiendo.

En la serie, Tim Roth da vida al doctor Cal Lightman, un científico que se ha hecho experto en reconocer engaños simplemente a través de expresiones faciales, el lenguaje corporal y la voz. Él y sus compañeros detectan verdades y mentiras para ayudar en investigaciones a través de la psicología aplicada. Su proceso deductivo se basa en hacer preguntas a sospechosos y evaluar sus reacciones físicas. La serie se fundamenta en los planteamientos de Paul Ekman, un especialista en el estudio de las emociones y sus relaciones con la expresión facial, además ahora es asesor de los guionistas de la serie.

En la serie nos cuentan algunas de las expresiones que fácilmente podemos dectectar en una persona, como son la ira, el miedo, la tristeza, la sorpresa, el desprecio… pero solo algunas, ya que según la serie, tenemos 43 músculos en la cara con los que podemos formar unas 10000 expresiones!! Es lo que llaman microexpresiones, ya que pueden durar apenas una fracción de segundo, tiempo suficiente para analizar si uno miente o dice la verdad.

Una de las cosas que remarca la serie es la poca fiabilidad que tienen los polígrafos, algo comúnmente conocido por su uso como detector de mentiras. Afirman que un detector de mentiras es muy fácil que se equivoque ya que los seres humanos somos capaces de sentir varias cosas a la vez pudiendo obtener un falso positivo con el polígrafo.

Bueno, no os cuento nada más, simplemente decir que os divertireís viendo la serie y además aprenderéis un poco sobre la comunicación no verbal.

]]>
http://anabuigues.com/2010/05/22/lie-to-me-mienteme-una-serie-que-deberias-ver/feed/ 6
Data Mart y Data Warehouse http://anabuigues.com/2010/04/19/data-mart-y-data-warehouse/ http://anabuigues.com/2010/04/19/data-mart-y-data-warehouse/#comments Mon, 19 Apr 2010 21:24:03 +0000 Ana Buigues http://anabuigues.com/?p=396 Data warehouse y data martsUn Data Mart cumple los mismos principios que un Data Warehouse, construir un repositorio de datos único, consistente, fiable y de fácil acceso.

Entonces ¿Qué diferencia hay entre un data warehouse y un data mart? Su alcance. El data mart está pensado para cubrir las necesidades de un grupo de trabajo o de un determinado departamento dentro de la organización, en cambio, el ámbito de un data warehouse es la organización en su conjunto. Se caracterizan por disponer la una estructura óptima de datos para analizar la información al detalle desde todas las perspectivas que afecten a los procesos de dicho departamento.

Supone una buena opción para pequeñas y medianas empresas que no puedan afrontar el coste de poner en marcha un Data Warehouse. La escalabilidad de los data marts hacia el data warehouse puede ser una solución si el número de data marts aumenta considerablemente.

Clases de Data Marts

Existen dos tipos de data marts:

1. Data Marts Dependientes

Los datos que se utilizan para poblar el data mart provienen del data warehouse. Esta estrategia es particularmente apropiada cuando el data warehouse crece muy rápidamente y los distintos departamentos requieren sólo una pequeña porción de los datos contenidos en él.

2. Data Marts Independientes

Los datos que se utilizan para poblar el data mart provienen de los sistemas operacionales y/o fuentes externas.

Problemática:

  • El hecho de tener varios data marts independientes, sin ningún tipo de integración, puede hacer que las tareas de administración y mantenimiento se conviertan en un lastre.
  • Se puede dar el caso de que algunos data marts necesiten los mismos datos para dar respuesta a determinadas preguntas, por lo que tenemos redundancia de datos, ya que cada data mart se alimenta con sus procesos de extracción y transformación propios.

]]> http://anabuigues.com/2010/04/19/data-mart-y-data-warehouse/feed/ 17 Mi nick de Twitter en la Tele gracias a Berto Romero! http://anabuigues.com/2010/03/29/mi-nick-de-twitter-en-la-tele-gracias-a-berto-romero/ http://anabuigues.com/2010/03/29/mi-nick-de-twitter-en-la-tele-gracias-a-berto-romero/#comments Mon, 29 Mar 2010 13:45:47 +0000 Ana Buigues http://anabuigues.com/?p=521 El pasado jueves 25, Berto Romero realizó un “mierdi-concurso” a través de su twitter que consistía en adivinar de qué saldría disfrazado en el programa de Buenafuente por la noche. Aquí os dejo la convocatoria del concurso

Yo dije que iría de King África y aunque habría sido un puntazo finalmente fue de Georgi Dan… por lo que acabé ganando, seguramente por ser creadores de grandes e inolvidables canciones del verano como… no recuerdo ahora mismo ninguna así que volveré al tema del “mierdi-concurso”. Aquí podeís ver el video donde se ve mi nick en la taza de Berto

http://www.youtube.com/watch?v=NBG_VY-QZNY

Además el viernes 25 fui a ver el show de Berto Romero “La apoteosis necia” donde además de divertirme como una enana y reir como hacía tiempo que no reía, tuve la oportunidad de conocerlo brevemente… pero esto es una historia que contaré en mi próximo post xD (con la taza en mi mano espero en vez de en la de Berto).

]]>
http://anabuigues.com/2010/03/29/mi-nick-de-twitter-en-la-tele-gracias-a-berto-romero/feed/ 11