Archive for December, 2007

Esperando navidad

December 15th, 2007

Hace años que no esperaba navidad con tanta ansia, casi olvidaba la sensación en el estomago, la desesperación y el ver como el tiempo pasa cada ves mas lento cuando esperas que se apresure.

¿Pero por que?

nintendo_wii_1.jpg

rayman2.jpgsmg.jpg

¿Realmente ocupo decir mas?, maldito santa, ¡apurate pinche gordo!

¿No sabes XPath? ¡Aprende!

December 11th, 2007

Otra de las herramientas de un desarrollador que se vuelven completamente imprescindibles una ves que las conoces es XPath.

XPath es un estándar del W3C para realizar querys a documentos Xml, haciendo fácil filtrar los nodos de un documento de acuerdo a la estructura y atributos de los nodos.

Si no usamos XPath, tendríamos que iterar a través de todos los nodos de un documento Xml para obtener la información que buscamos.

Para no hacérsela mas larga voy a dejar que el código hable por si mismo.

Imaginen que tienen el siguiente Xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8" ?> 
<Sucursales>
	<Sucursal name="Matriz">
		<Articulo name="Monitor" precio="1500"/>
		<Articulo name="Impresora" precio="400"/>
	</Sucursal>
	<Sucursal name="Mayoreo">
		<Articulo name="Monitor" precio="1600"/>
		<Articulo name="Impresora" precio="500"/>
	</Sucursal>
	<Sucursal name="Menudeo">
		<Articulo name="Monitor" precio="1800"/>
		<Articulo name="Impresora" precio="700"/>
	</Sucursal>
</Sucursales>

Y ustedes quieren saber tres cosas:

  1. ¿Que artículos con que precios se encuentran en la sucursal Matriz?
  2. ¿Que sucursales tienen monitores?
  3. ¿Que precio tiene una impresora en la sucursal menudeo?

Sin XPath estas tres simples preguntas se convierte en esta monstruosidad:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Xml;
using System.Collections.Generic;
 
class Program
{
    public static void Main()
    {
        XmlDocument document = new XmlDocument();
        document.Load("Test.xml");
        XmlNode sucursales = document.ChildNodes[1];
 
        //Obtener los articulos de la sucursal matriz
        XmlNodeList articulosMatriz;
        foreach (XmlNode sucursal in sucursales.ChildNodes)
            if (sucursal.Name == "Sucursal")
                if (sucursal.Attributes["name"].Value == "Menudeo")
                    articulosMatriz = sucursal.ChildNodes;
 
        //Obtener todas las sucursales que tienen monitores
        List<XmlNode> sucursalesConMonitor = new List<XmlNode>();
        foreach (XmlNode sucursal in sucursales.ChildNodes)
        {
            if (sucursal.Name == "Sucursal")
            {
                foreach (XmlNode articulo in sucursal.ChildNodes)
                {
                    if (articulo.Name == "Articulo")
                    {
                        if (articulo.Attributes["name"].Value == "Monitor")
                        {
                            sucursalesConMonitor.Add(sucursal);
                            break; //Siguiente sucursal
                        }
                    }
                }
            }
        }
 
        //Obtener el precio de una impresora en la sucursal menudeo
        XmlNode impresoraSucursalMenudeo = null;
        foreach (XmlNode sucursal in sucursales.ChildNodes)
        {
            if (sucursal.Name == "Sucursal")
            {
                if (sucursal.Attributes["name"].Value == "Menudeo")
                {
                    foreach (XmlNode articulo in sucursal.ChildNodes)
                    {
                        if (articulo.Name == "Articulo")
                        {
                            if (articulo.Attributes["name"].Value == "Impresora")
                            {
                                impresoraSucursalMenudeo = articulo;
                                break; 
                            }
                        }
                    }
 
                    if (impresoraSucursalMenudeo != null)
                        break; //Se encontro el articulo, terminamos!
                }
            }
        }
    }
}

¡HORRIBLE!

Claro que si hicieron la tarea y saben XPath, ¡las cosas cambian dramáticamente!:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Xml;
 
class Program
{
    public static void Main()
    {
        string xPathQuery;
        XmlDocument document = new XmlDocument();
        document.Load("Test.xml");
 
        //Obtener los articulos de la sucursal matriz
        xPathQuery = @"/Sucursales/Sucursal[@name='Matriz']/Articulo";
        XmlNodeList nodes = document.SelectNodes(xPathQuery);
 
        //Obtener todas las sucursales que tienen monitores
        xPathQuery = @"/Sucursales/Sucursal[./Articulo[@name='Monitor']]";
        nodes = document.SelectNodes(xPathQuery);
 
        //Obtener el precio de una impresora en la sucursal menudeo
        xPathQuery = @"/Sucursales/Sucursal[@name='Menudeo']/Articulo[@name='Impresora']";
        XmlNode node = document.SelectSingleNode(xPathQuery);
    }
}

SIMPLE, SENCILLO Y HERMOSO

Si no saben nada al respecto lean por lo menos este tutorial de w3schools, no se arrepentirán.

P.S XPath es un estándar, por lo que no depende de .NET, puedes usarlo en Java, Python o lo que te de tu gana

La belleza del formato de fecha yyyymmdd

December 10th, 2007

Siempre que pongo una fecha trato de hacerlo en el formato yyyymmdd en ves del mas tradicional (en México) de ddmmyyy.

¿Por que?

Resulta ser que ese formato es mal útil al momento de ver una lista de archivos y saber cual es el mas actual, si usamos yyyymmdd lo único que ocupamos es ordenar la lista alfabéticamente y tendremos en el mismo momento un orden cronológico.

Cuando un programa ordena una lista, compara los caracteres uno por uno según su ubicación, si los nombres están en formato ddmmyyyy, comparara primeramente los dias, por lo que el primero de diciembre (0112) aparecerá antes que el 31 de enero (3112). En cambio si usamos yyyymmdd, siempre se compararan primero el año, que es el valor que tiene mas peso, seguido del mes y por ultimo el día.

No cuesta mucho acostumbrarse a un nuevo formato de fecha y las ventajas si usas mucho la compu son bastantes, por lo que no hace daño y puede ser muy útil :)

Ahora, antes de que alguien salga diciendo que es antinatural, les recuerdo que el mundo no gira alrededor de ustedes, distintas culturas usan distintos formatos de fecha, numero, moneda, etc. Y lo que a ustedes les parece poco común en otros lugares del mundo es de uso diario, por ejemplo, en gran parte Europa se usa el punto (.) como separador de miles y la coma (,) como separador decimal, por lo que nuestro 123,456.78 se convierte en 123.456,78. Sin mencionar que los gringos usas mmddyyyy como formato de fecha común.

Igual si no me hacen caso me vale.

P.S Si van a hacer esto, es importante que los meses y los días siempre tengan dos dígitos, por ejemplo, para enero usar 01 en ves de 1.

Hannibal Rising

December 10th, 2007

Ayer, domingo (2007-12-09) fui al cine, no tenia ninguna pelicula en mente y esperaba elegir una random en cartelera.

Fue el destino

La primera película que vi en el anuncio rotatorio de la taquilla fue:

Hannibal Rising

Tras consultarlo rapidamente con mi mujer (con todo y mirada amenazadora twisted) rápidamente compre los boletos.

La película trata de como nuestro querido Hanibbal Lecter llego a ser la criatura tierna, dulce y amorosa que todos conocemos, mostrándonos su trágica infancia en Alemania durante la segunda guerra mundial y, el como obtuvo su famosisimo buen gusto en el arte culinario.

La película, obviamente es sangrienta (no puedo creer que haya tenido que decir eso), por lo que recomiendo llevar a sus hijos a verla con mentiras, asegurando que es Bee Movie o algo por el estilo, para brindarles una excelente infancia traumática, ¿quien sabe?, a lo mejor los convierte en los próximos genios maléficos acomplejados.

La película en si es buena, no tanto como las anteriores según mi refinado gusto, pero como cualquiera que haga cazo de una critica es un imbecil, corre al cine mas próximo o al puesto de periódicos mas cercano (pa’ comprarla pirata wink) y ponte a verla.

Di no a los passWORDS, si a passPHRASE

December 7th, 2007

Leyendo Coding Horror, me encontré con un post acerca de no usar palabras como contraseñas, si no frases.

El beneficio es obvio, una frase es fácil de recordar, mas aun si es algún tipo de cita de un libro o una canción, y es mas larga que cualquier palabra que puedas elegir.

Por lo tanto una frase usada como contraseña es mucho mas segura que una palabra.

Los críticos dicen que esto no es así, debido a que las frases contienes palabras de diccionario, pero no necesariamente. Yo desde hace bastantes años llevo usando como contraseña principal una pequeña frase de unas cuantas palabras, la frase esta ingles y para evitar ataques de diccionarios esta mexicanizado.

¿Mexicanizado?

Así es, basicamente lo que hago es poner algunas palabras tal y como suenan en español, ejemplos:

  • Lucky star: Luqui Estar
  • What if god was one of us: Güat if god uas uan of os
  • When the night, has come: Güen de naigt, jas com

Hasta el momento me ha funcionado, y no veo por que a ustedes no ;)

¿No sabes Regex? ¡Aprende!

December 7th, 2007

Algo de lo que me e dado cuenta cuando e dado platicas/talleres/cursos es que la gran mayoría de los desarrolladores, al menos de la región, no tienen ni puta idea acerca de que demonios son las expresiones regulares (Regex para los amigos).

Muchos recuerdan haber escuchado algo al respecto en su clase de autómatas en la universidad, pero como a todos, les paso de noche :P .

Es difícil de entender como la gente puede pasarse sentado en su vida profesional sin saber Regex, escribiendo cientos de lineas de código resolviendo problemas que con unos cuantos caracteres de Regex queda solucionado.

Si aun no sabes Regex, ¡deja de leer esto inmediatamente y ponte a buscar información al respecto!

Para los escépticos, un pequeño ejemplo:

Imagina que quieres validar que un teléfono siga el formato (900) 9-00-00-00, la forma común de hacerlo seria algo cómo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    bool isValidPhoneNumber(string input)
    {
        //Validate (900) 9-00-00-00
        if (input.Length != 16)
            return false;
        if (!input.StartsWith("("))
            return false;
        if (input[4] != ')')
            return false;
        int number;
        if (!int.TryParse(input.Substring(1, 3), out number))
            return false;
        if (input[1] == '0' || !char.IsNumber(input[1]))
            return false;
        if (input[5] != ' ')
            return false;
        string[] numbers = input.Substring(6, 10).Split ('-');
        if (numbers.Length != 4)
            return false;
        foreach (string subpart in numbers)
            if (!int.TryParse(subpart, out number))
                return false;
        if (numbers[0][0] == '0')
            return false;
        return true;
    }

Es tedioso de hacer, resulta fácil dejar errores en el, sin mencionar que es completamente horrible y resulta difícil de entender, y precisamente este es uno de los momentos en que Regex es útil:

1
2
3
4
5
6
7
8
   bool isValidPhoneNumber(string input)
    {
        //Validate (900) 9-00-00-00
        string expression = @"^\([1-9]\d{2}\)\ [1-9](\-\d{2}){3}$";
        System.Text.RegularExpressions.Regex regex = 
            new System.Text.RegularExpressions.Regex(expression);
        return regex.IsMatch(input);
    }

Si bien la sintaxis puede resultar confusa al inicio, basta un poco de practica para acostumbrarse a ella y puede llegar a ahorrarte toneladas de trabajo, especialmente si la usas para buscar patrones de texto en ves de solamente validación.

Confíen en mi, si no las conocen, ¡Aprendan!.

P.S: No me hago responsable de cualquier mal uso que puedan hacer de ellas ;)