lunes, 26 de septiembre de 2011

Boost Hash

Esta entrada va a ser muy corta, o eso espero... Boost::hash es una libreria que nos facilita el calculo del hash de cualquier entrada. Más que facilitarlo lo soluciona completamente :)

Este seria un caso muy directo:


#include "iostream"
#include "boost/functional/hash.hpp"
int main()
{
    boost::hash string_hash;
    size_t myHash = string_hash("Hola mundo");
    std::cout << "Mi hash es " << myHash << std::endl;
    return EXIT_SUCCESS;   
}

Tambien se puede lo deberiamos usar para indexar maps. Imagina que tenemos una funcion que recibe un directorio y un objeto de una clase T, y que eso lo guardamos en un std::map. Los directorios son del tipo "c:\archivos de programas\bla bla bla\jejeje\archivo". Si te fijas, cuando se empieza a comparar la función,  los 15 primeros carácteres son siempre iguales, asi que podemos perder ciclos comparando. Lo que podemos hacer es, al insertar el objeto T, calcular el hash del directorio y devolver el hash como ID. Asi nuestros accesos posteriores seran rapidisimos.

std::size_t insert( const std::string& dir, T& objeto)
{
    std::size_t hash = string_hash(dir);
    myMap[hash] = objeto;
    return hash;
}

Ahora podriamos recuperar el objeto facilmente con el ID (no controlamos los errores).
T& get(const std::size_t id)
{
   return myMap[id];
}
Nota: He incluido las cabeceras como #include "iostream" por un tema del plugin de blogger, que me formatea mal el código, pero lo puedes poner como quieras.

sábado, 24 de septiembre de 2011

Boost. Ponle el turbo a C++

Encuentro que hay mucha gente que desconoce Boost Supongo que también hay mucha gente que desconoce que C++ esta a punto de cambiar de standard, y que muchas de las funcionalidades nuevas están en Boost. De ahi que muchas de las sentencias como:
boost::Thread t1;
Pasarán a ser:
std::Thread t1;
Es decir, parte del estandar. Boost ademas ahonda en la idea de algunas tecnologias que implementa el nuevo estandar, como auto_ptr que boost completa con los scoped_ptr, shared_ptr, etc.
Por otro lado, boost llena agujeros que tradicioanlmente ha tenido C/C++. Por ejemplo, C++ no tiene una libreria unificada para tranajar con el sistema de ficheros. No hay una función que nos devuelva, por ejemplo, si un fichero existe y cuanto mide, y tenemos que recurrir a librerias de terceros. Tampoco tiene una libreria de fechas unificada.
Y eso que significa? Pues que cualquier programador de c++ deberia tener instaladas las librerias boost en su ordenador, y aprender a usarlas para no tener que reinventar la rueda constantemente.

Boost para novatos:
Pues de novato a novato te voy a decir una cosa. Boost no es dificil de instalar. De hecho es muy fácil:
Las bajamos desde esta pagina. En la sección de packaged downloads nos bajamos la última versión. Lo mejor es bajar el que esta comprimido en 7z por que es el mas pequeño en windows. En linux sirve el que quieras que sea gz. Ahora lo podemos instalar. En Window necesitamos 4 sencillos pasos:

1. Crear un destino
Creamos una carpeta en nuestro ordenador donde queramos instalar las librerias de manera definitiva. Por ejemplo en c:\dev-libs\boost. (lo mejor es que la ruta no tenga espacios en blanco, por si acaso)

2. Ir al constructor de boost
Al acabar de descomprimir tendremos una carpeta de nombre boost_version (puede ser boost_1_47_0 por ejemplo). Vamos dentro de esta carperta a .\tools\build\v2. Abrimos una consola y escribimos los siguientes comandos estando en esa ruta:

bootstrap.bat
.\b2

Esperamos a que acabe todo y entonces tendremos una herramienta llamada bjam. Ahora vamos a la raiz de boost (c:\dev-libs\boost en nuestro caso) y escribimos .\tools\build\v2\bjam y entonces empieza la construccion de boost de verdad.


3. Esperar
Ir a por un café. Si estas en el curro ves a hablar con esa de marketing tan guapa... esa que tu y yo sabemos. La compilación se puede alargar un ratito dependiendo de la máquina que tengas.


4. Añadir la ruta al PATH
Ahora solo te queda añadir lo que iba en prefix + bin, en mi caso c:\dev-libs\boost\1.47\bin al path. Aunque tambien podemos instalarlo directamente en Visual Studio para no enredar con el PATH. Para ello vamos a Herramientas -> Opciones -> Proyectos y soluciones -> Directorios de VC++
Alli añadimos "c:\dev-libs\boost\1.47\" en "Archivos de inclusion" y "c:\dev-libs\boost\1.47\stage\lib" en "Archivos de biblioteca". Asi boost estará disponible para cualquier proyecto.
Y con eso quedaria instalado. Ahora, sin ninguna confuguracion adicional del proyecto deberiamos poder compilar algo como esto:
#include 
#include 
#include 

int main()
{
    std::string line;
    boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" );

    while (std::cin)
    {
        std::getline(std::cin, line);
        boost::smatch matches;
        if (boost::regex_match(line, matches, pat))
            std::cout << matches[2] << std::endl;
    }
}
Y con eso ya tendriamos boost instalado. En general ni es tan largo ni complicado como mucha gente piensa. Espero que esto te anime a empezar. En los proximos dias escribire algunas entradas sobre librerias de boost que me parecen especialmente utiles.

Pasitos con Unity

Hace unos días me baje Unity3D para trastear un poco y la verdad es que parece un producto muy bien hecho. Lo primero que sorprende es su sencillez de ideas. Tenemos la ventana de diseño, donde vemos la escena que hemos montado, la jerarquia, que es donde montamos la escena a base de interrelacionar assets, el panel de proyecto, que es donde nuestros assets disponibles estan listos para usarse y el panel de inspeccion.

Casi todo pasa con sencillez. Queremos una luz? Buscamos en el panel de proyecto por los tipos de luces disponibles, elegimos una, la arrastramos al panel de jerarquia y en el inspector podemos cambiarle las propiedades. Casi todos los elementos estan pensados asi, con lo que ganamos en sencillez.

Unitiy no sorprende por herrmamientas 3D, o de retoque de imagen o de sonido, sino que se limitan a aconsejarte que busques alguna herramienta de verdad como Maya o Photoshop. Pero Unity3D provee metodos para recoger los productos de estas herramientas y cargarlos como assets. Tambien viene con el editor mono, para javascript o c#. Y de momento eso es lo que he visto hasta ahora. Ya ire poniendo mas entradas donde explique como me va con Unity3D

jueves, 22 de septiembre de 2011

Probando tu codigo en C++ con gtest (II)


El porque de las pruebas unitarias


En la entrada anterior planteaba la necesidad de hacer test unitarios, ademas de explicar como montar la librería  compilarla y usarla. Pero quizás hay una pregunta que no respondo y es: para que? Para que una librería cuando podemos hacer programas de ejemplo?
En esta segunda entrada quiero hablar desde un punto de vista diferente y explicar que se busca con las pruebas unitarias y que estrategia tomar para sacarle partido a estas:

Imagina que estas programando y usas las STL. Al ejecutar, aparece un error muy raro. Al debugar, la excepción salta en medio del código de una de las clases que implementan std::vector. Le echaras la culpa a las STL? Las mirarás en profundidad? No. Seguro que no. Tendrás la seguridad de que lo que falla es tu código, por que sabes que las STL han sido probadas una y otra vez (y aun y así todavía tienen errores, aunque son difíciles de encontrar). Esa tranquilidad agiliza el desarrollo puesto que en caso de error siempre miramos el último código. Esa es una de las fortalezas de la reutilización de código.

Cuando pruebas su código, muchas veces haces algunas funciones de prueba pero, lo haces de una manera estructurada? Por ejemplo, esta función:

int dividir(const int a, const int b)
{
   return (a/b);
}

Como la probarías?
En principio no haríamos nada raro: un par de llamadas y ver el resultado. Con google test seria así

TEST(funcionDividirTest, dividir)
{
    EXPECT_EQ(dividir(5,2),7);
    EXPECT_EQ(dividir(5,-5),0);
}

No hay nada que hacer. Al final siempre hay bugs. En este caso, por ejemplo, no se contempla la division por cero. Si has hecho bien tu trabajo de pruebas, arreglarás el bug, y añadiras una prueba más a tu set de pruebas, y te asegurarás de que en cada compilación se ejecuten todas las pruebas. La ganancia principal aquí con las pruebas unitarias es que podemos probar nuestro código cada vez que compilamos una nueva version. En codigo más complejo, cuando probamos funciones de más alto nivel, nos permitirá descubrir cuando alguien ha metido la pata.


La vista puesta en la calidad

Resolver bugs es aburrido y una perdida de tiempo. Lo mejor es no fallar al programar. Como es casi imposible, las pruebas unitarias hacen que una vez escritas las pruebas por alli ya no fallará el programa (y si falla sera algo muy localizado). No harías ningun sacrificio por esa buena causa? Pues intenta que el código sea probable. Para hacerlo, intenta que tus funciones y métodos devuelvan algo. Si la función no debería devolver nada, pues que devuelva 0 en caso de éxito y algún valor de error en caso contrario (debidamente documentado). Evidentemente, cambiar el diseño para que sea fácilmente probable puede ser costoso pero creo que se sale ganando con creces.

Se consistente en el manejo de errores. Devuelve un código de error o haz saltar una excepción, pero no mezcles estrategias en el código.

Lleva un control de lo que has probado, pero también de lo que no has probado. Es casi más importante saber que código esta en el aire.

Desacopla tu código, por que si no las inicializaciones son pesadas y penosas. Cada subsistema debería poderse compilar por separado (siempre que sea posible). Desacoplar el código significa que cada subsistema habla con los otros subsistema a través de unas interfaces muy determinadas. Hay que evitar situaciones donde cada clases de un subsistema tiene que conocer muchas cosas de otro subsistema



Test driven development

Pero se puede hacer algo más?
Pués si. Imagina que un jefe de proyecto, manager o lo que sea te da esto:

int factorial(const int n)
{
    return 0;
}

Y además esto:
TEST(funcFactorial, aceptacion)
{
    EXPECT_EQ(factorial(0), 0);
    EXPECT_EQ(factorial(1), 1);
    EXPECT_EQ(factorial(2), 2);
    EXPECT_EQ(factorial(5), 120);
    int n = 20;
    EXPECT_EQ(factorial(n), factorial(n -1)*n);
}

Digamos que con la interface de la función yo puedo compilar, aunque siempre me devolverá 0, pero yo puedo ir haciendo otro trabajo. Tu trabajo seria programar la funcion de manera que pase el test unitario. Programala como quieras mientras no cambies la signatura de la funcion y siempre que el resultado del test sea verde.

Esta estrategia, de crear lo test antes de el codigo que bajo test, se llama test driven development. Este tipo de estrategia, aunque parezca lenta, puede llegar a reducir el tiempo de desarrollo y aumenta la calidad del codigo final, ademas de reducir el tiempo de desarrollo al haber menos fallos.

lunes, 20 de septiembre de 2010

Probando tu codigo en C++ con gtest

La necesitadad de probar las cosas
En las ultimas semanas me ha entrado un ataque de creatividad y he escrito bastante código para mi motor gráfico en eterna creación. La verdad es que los casos directos funcionan pero van apareciendo errores y eso te paraliza bastante porque tienes que pararte y analizar lo que has hecho y alguna que otra vez rediseñar y cambiar un monton de cosas.
Para evitar esto, ultimamente he estado buscando algunas herramientas de test unitarios para C++ y he encontrado una que me ha gustado bastante. Multiplataforma, simple y rapida, sin muchas florituras pero parece que bastante madura. Y con el sello de google. Sí, es google test. En este articulo voy a describir como preparar tu entorno Visual Studio con google test para empezar a probar tu código.
Compilando gtest desde las fuentes
Lo primero que vamos a hacer es bajar una copia del código fuente. Podemos obtener el código aqui. Yo bajo la 1.5.0. Ahora solo hay que descomprimir en un directorio de windows. Una vez descomprimido podemos ver que hay un subdirectorio llamado msvc. Aqui se guardan los proyectos para compilar las librerias de gtest. Veras que hay dos soluciones de proyecto (lo que antes eran los workspace de VC++): gtest.sln y gtest_md.sln. La diferencia entre uno y otro la explicaré más adelante. Nos quedaremos con el primero. Si tenemos Visual Studio 2005 la solución se abrirá directamente. Si tenemos Visual Studio 2008/2010 entonces se abrirá el convertidor de soluciones.

Una vez abierto, veremos que tenemos 4 proyectos incluidos en la solución.

No nos preocuparemos demasiado por que solo queremos generar las librerias. Hacemos click derecho en la solución y seleccionamos generar solución.
En principio, y si no pasa nada raro, deberia acabar sin errores ni advertencias, habiendo compilado los 4 proyectos. Si te fijas, dentro del directorio msvc, ahora existe una carpeta llamada gtest. Dentro de gtest, se ha creado otra llamada Debug. Y dentro, se han creado las librerias y ejecutables resultantes de la compilación. Veras que tienes un archivo llamado gtest_maind.lib y otro llamado gtestd.lib. Estos son las librerias estaticas que necesitamos para nuestros tests.

Ahora vamos a compilarlas en modo Release. Vamos a Visual Studio y arriba, en la barra de herramientas estandar, cambiamos la configuración de Debug a Release. Ahora, como antes, hacemos click derecho en la solución y generamos la solución. Como antes vamos a msvc->gtest, pero ahora veremos dos directorios. Uno de ellos se llama Release. Tambien contiene dos ficheros .lib.

Instalar gtest en nuestra máquina

Dentro del directorio de gtest, existe un directorio llamado include. Ademas, ya hemos explicado donde quedan los .lib tanto de degub como de release. Ahora podemos hacer dos cosas. O le explicamos al IDE donde encontrar estos dos directorios o le decimos a cada proyecto donde estan. En general soy partidario de lo segundo, pero en este caso lo voy a instalar de manera global puesto que esta es una libreria de uso muy general y usable en casi cualquier proyecto, como boost, por ejemplo.

Asi que en Visual Studio voy a Herramientas, opciones... y alli voy a proyectos y soluciones y selecciono Directorios VC++. Alli añado el directorio Debug y Release resultante de la compilación anterior en el apartado de archivos de biblioteca, y añado el directorio include dentro de archivos de inclusion:
Le doy a aceptar y ya tenemos "instalado" gtest en nuestro IDE

El primer proyecto de tests de unidad

Lo unico que necesitamos hacer para crear un test minimo de gtest es lo siguiente. Creamos un nuevo proyecto, en general dentro de la solución donde estemos creando nuestro proyecto principal y le ponemos un nombre que parezca importante (por nuestro ego y todo eso...), como unit_Tests. El proyecto, lo haremos vacio y de win32 console.

Ahora hacemos click derecho en el proyecto y vamos vinculador --> entrada -->dependencias adicionales y alli añadimos, gtestd.lib y gtest_maind.lib si estamos en Debug, y lo mismo pero sin la 'd' si estamos en release.

Nota!!
Si no hubieramos configurado nuestro IDE para saber donde estan estos archivos necesitariamos decirselo añadiendo los directorios de los .lib en vinculador-->general-->directorios de bibliotecas adicionales.

Ademas deberiamos instruir al proyecto sobre donde se encuentran los directorios de include, poniendoles su situacion en C/C++ --> directorios de inclusion adicionales.

Y ahora ya tenemos preparado nuestro proyecto para ejecutar test. Vamos a crear un archivo unit_tests.cpp (por ejemplo), con el siguiente código:


#include <gtest/gtest.h>

TEST(UnitTestSample,TestOne){
EXPECT_EQ(1,1);
}

Te recomiendo que ejecutes con CTRL-F5 para que la ejecución se pare antes de cerrar la ventana. Deberias ver esto:
Y eso es todo!! Con esto ya puedes probar de manera automatica que 1 es igual a 1, y muchas otras cosas más. Ahora importa tu código y demuestra que es robusto como una roca!!!

A continuación algunas explicaciones que he dejado para el final para no desviarme del tema principal.

Nota1: Te habrás dado cuenta de que el codigo no tiene función main. Esto es por que al añadir gtest_main(d).lib, ya añadimos un main que ejecuta todos nuestros test. Puedes consultar en la documentación del proyecto como generar tu propio main. Pero te recomiendo que lo uses asi, puesto que el código más seguro es el que no se escribe.


Nota2: Antes he explicado que hay que elegir la solución gtest y no la gtest_md. Bueno, en realidad lo importante es que si eliges gtest_md, entonces en la configuración de tu proyecto debes elegir en C/C++ --> generacion de código --> biblioteca en tiempo de ejecucion la opcion depuracion multiproceso si es en Debug y mutiproceso si estamos en Release. Si por el contrario elegimos gtest, entonces seleccionaremos DLL multiproceso.

miércoles, 1 de septiembre de 2010

Comprobar "Endianess"

Pequeño truquito para comprobar como se ordenan los bytes en la memoria de la maquina:

int i = 1;
char c = *(char *) &i;

if (c) {
cout << "Little endian" << endl;
} else {
cout << "Big endian" << endl;
}


Encontrado via:

De std::wstring a std::string

Una manera practica para pasar de std::wstring a std::string y viceversa:


#include <string>
#include <algorithm>

// Prototype for conversion functions
std::wstring StringToWString(const std::string& s);
std::string WStringToString(const std::wstring& s);

std::wstring StringToWString(const std::string& s)
{
std::wstring temp(s.length(),L' ');
std::copy(s.begin(), s.end(), temp.begin());
return temp;
}


std::string WStringToString(const std::wstring& s)
{
std::string temp(s.length(), ' ');
std::copy(s.begin(), s.end(), temp.begin());
return temp;
}


Encontrado via: http://www.codeguru.com/forum/showthread.php?t=193852