¿Si eres legal, eres legal?

Dejando de lado la falta de originalidad del eslogan de la nueva campaña antipiratería del Ministerio de Cultura (sí, que les devuelvan el dinero) y cómo aprovechan para difundir mentiras sobre el p2p,

Las redes p2p son seguras.
¡Falso! La seguridad es uno de los mayores problemas que plantean estas redes, ya que damos entrada a nuestro ordenador a todos aquellos que estén conectados a ella. Cualquiera puede circular libremente y acceder a nuestros datos: IP, tipo de descargas que estamos haciendo, número de teléfono y otra información de seguridad que figure en el ordenador.

me entero por Barrapunto de que se ha presentado en el Parlamento una proposición no de Ley que insta al Gobierno a liderar, en el marco de la Comisión Intersectorial contra la Piratería, una estrategia consensuada y eficaz que permita ordenar la circulación de contenidos en Internet”.

Ante esta situación, creo que la única salida es decir: que les den. Que se queden en su jaula con sus obras protegidas. Apoyemos las iniciativas de difusión de cultura libre, que no criminalizan al que comparte, que se salen del “lo mío es mío y sólo mío”, “mi tesooooro” 95 años después de muerto, las dosis de moralina y el “¿de qué van a vivir entonces los copistas?”.

Jamendo, el libro de Los piratas son los padres, o la librería, distribuidora y editorial Traficantes de Sueños son sólo tres pruebas de que otra forma de entender la cultura, fuera de la industria del entretenimiento, es posible.

¡Que les den!

Velocidad del centro de masas de una estrella binaria

Este fin de semana toca, una vez más, práctica numérica de Fundamentos de Astrofísica. Una de las tareas que hay que hacer es, a partir de la curva de velocidad radial de una estrella binaria espectroscópica, hallar la velocidad del centro de masas.

Según el método de Lehmann-Filhes, lo que hay que hacer es trazar una linea horizontal en la gráfica de velocidad radial, de modo que las áreas encerradas por la curva por encima y por debajo de esta linea horizontal sean iguales. Parece trivial, pero en una licenciatura como la nuestra (CC. Físicas en la UCM) no nos enseñan a manejar programas de cálculo numérico lo suficiente como para resolver este tipo de problemas.

Yo he seguido un proceso iterativo. En primer lugar, he puesto los datos de la curva en una tabla, los he representado, y he usado la función de integración de Qtiplot (un programa clon de Origin) para realizar la integral de la curva por el método del trapecio.

Como se puede ver, el valle de la curva de velocidad radial es mucho más extenso que la cresta, y es por lo que al final las áreas suman negativo. La estrategia consiste en desplazar la curva hacia arriba hasta que la integral de cero, y la distancia que lo hayamos desplazado, cambiada de signo, equivaldrá a la velocidad del centro de masas en km/s. Es decir, si para que la integral se anule tenemos que desplazar la gráfica 8 km/s hacia arriba, la velocidad del centro de masas será -8 km/s.

En este caso, el desplazamiento adecuado fue de -13.3 km/s.

Son bienvenidos comentarios y sugerencias sobre otras formas de hacer el cálculo.

Pequeña introducción al Test Driven Development en C++

Normalmente, cuando uno desarrolla un programa, lo que hace para ver si funciona es probar el programa con unos datos de entrada y ver si la salida es correcta.Existe una técnica de programación que consiste en escribir pruebas automáticas para programas que aún no han sido escritos, de forma que al principio las pruebas evidentemente fallan (y si no fallan, es que no valen para nada) y, cuando el programa esté completo, funcionan.Esto puede parecer una carga de trabajo excesiva pero, siempre que se use con sentido común, tiene varias ventajas:

  • Se define el prototipo de entrada y salida de datos desde el principio.
  • Se descubren errores prematuros que podrían pasar desapercibidos y hacernos dar mil vueltas por el código tratando de averiguar dónde está el problema.
  • Constituyen una prueba de que tu programa funciona, diga lo que diga el profesor.
  • Como son automáticos (los hace el ordenador, no tú), puedes ejecutarlos siempre que escribas algún trozo de código nuevo, o cambies algo, para asegurarte que no has roto nada. Esto aumenta la confianza entre miembros de equipos de desarrollo.

Querría matizar que hay que usarlos con sentido común. Si no somos capaces de descubrir si el problema está en nuestra función de prueba automática o en el código de la aplicación que hemos escrito, no valen para nada. No obstante, coger práctica en la escritura de pruebas conlleva un tiempo de aprendizaje.

Un ejemplo sencillo

Para que todo este rollo deje de sonar a chino, vayamos con un ejemplo facilito:

char pasar_caracter_a_mayusculas(char caracter) {
        int const SEPARACION_MINUS_MAYUS = 'A'-'a';
        caracter += SEPARACION_MINUS_MAYUS;
        return caracter;
        }

string pasar_texto_a_mayusculas(string texto) {
        // leer cada caracter y pasarlo a mayúsculas
        for (int i=0; i<texto.length(); i++) {
                texto[i] = pasar_caracter_a_mayusculas(texto[i]);
                }
        return texto;
        }

¿Ves el error? Porque hay uno… Está claro que es difícil cazarlo a simple vista, pero si probamos la función con un texto al azar nos daremos cuenta enseguida del problema:

int main(int argc, char* argv[]) {
        string text = "Los programadores.";
        cout << pasar_texto_a_mayusculas(text);
        return 1;
        }

Lo ejecutamos y aparece:

,OSPROGRAMADORES

Vale, tenemos un error en el código: se intentan pasar a mayúsculas tanto los caracteres que no son letras como los que ya son mayúsculas. En vez de empezar a retocar el código directamente, vamos a escribir una función que demuestra que nuestra función “pasar_texto_a_mayusculas” tiene un fallo:

bool prueba_pasar_texto_a_mayusculas(string texto_entrada, string texto_salida) {
        if (pasar_texto_a_mayusculas(texto_entrada) == texto_salida)
                return true;  // Test OK!
        else
                return false;  // Test Failed!
        }

int main(int argc, char* argv[]) {
        if (prueba_pasar_texto_a_mayusculas("Los programadores.", "LOS PROGRAMADORES."))
                cout << "pasar_texto_a_mayusculas funciona!n";
        else
                cout << "pasar_texto_a_mayusculas falla!n";
        return 1;
        }

Lo ejecutamos y aparece por la pantalla:

pasar_texto_a_mayusculas falla!

Ahora que hemos demostrado que hay un problema, vamos a escribir el código para arreglarlo. Cuando lo arreglemos, la prueba lo demostrará:

char pasar_caracter_a_mayusculas(char caracter) {
    int const SEPARACION_MINUS_MAYUS = 'A'-'a';
    if (caracter >= 'a' && caracter <= 'z')  // caracter es una letra minúscula
        caracter += SEPARACION_MINUS_MAYUS;
    return caracter;
    }

Si ejecutamos de nuevo nuestro programa veremos:

pasar_texto_a_mayusculas funciona!

¡Genial!

Observaciones

En este ejemplo, el error no estaba en la función que hemos comprobado, sino en otra a la que la primera llamaba. Idealmente, se debería escribir una función de prueba por cada función “real” que se implementa, para que sepamos inmediatamente en qué función está el fallo.

No basta con probar la función con un caso general: es muy importante probarla con casos límite, como textos vacíos, todo mayúsculas, todo minúsculas, etc. La mayoría de las veces, los problemas aparecen en esos casos límite.

De nuevo, hay que usar el sentido común: si no te sientes cómodo escribiendo funciones de prueba y tardas horas en hacerlo, olvídalo. Es sólo una técnica que puede ser tanto una ayuda maravillosa como una lacra absurda. Lo importante es saber que existe, por si algún día nos interesase usarla.

Las funciones de prueba son todas muy parecidas: consisten en pasar una serie de argumentos de entrada a una función y comprobar que la salida es la esperada. Usa el clásico copiar & pegar siempre que puedas. También existen frameworks (programas que sirven para escribir programas basados en ellos) que facilitan la tarea, aunque yo no he usado ninguno de C++ todavía.

Agradecimientos

Gracias a la comunidad de Python y Zope/Plone por hacer que me llegue a gustar tanto el Test-Driven Development como para que me anime a escribir sobre ello, y a la gente que ha confiado en mí para que pueda publicar esto en el foro de MareMonstrum. :-)

Escribir código iterativamente

Muchas veces al programar nos enfrascamos demasiado en la inicialización de variables, uso de estructuras, etc. y perdemos la noción de lo que estamos haciendo realmente, llegando incluso a programar funciones que no hacen lo que queremos ni de lejos.

Una buena idea es escribir en varias fases, de forma iterativa, escribiendo primero el flujo general del programa, y a partir de ahí ir perfilándolo por partes, progresivamente, en vez de intentar hacerlo todo de una vez. Si es necesario, se puede empezar con comentarios.

Supongamos que queremos pasar un texto a mayúsculas. ¿Qué datos de entrada y salida queremos? Básicamente, queremos pasar un texto como entrada y que nos salga convertido todo a mayúsculas, lo que se traduce como:

string pasar_a_mayusculas(string texto);

Vale, ya tenemos lista la interfaz de la función. Lo siguiente es preguntarnos cómo se pasa un texto entero de mayúsculas a minúsculas: pasando a mayúsculas cada uno de sus caracteres:

string pasar_a_mayusculas(string texto) {
    // leer cada letra y pasarla a mayúsculas
    }

Vamos avanzando. Ahora describamos la última tarea:

string pasar_a_mayusculas(string texto) {
    // leer cada letra y pasarla a mayúsculas
    for (i=0; i<n_letras; i++) {
        texto[i] = pasar_letra_a_mayusculas(texto[i]);
        }
    return texto;
    }

char pasar_letra_a_mayusculas(char letra) {
    letra += SEPARACION_MINUS_MAYUS;
    return letra;
    }

La distancia entre mayúsculas y minúsculas es simplemente (A-a), o (Z-z), etc.:

char pasar_letra_a_mayusculas(char letra) {
    int const SEPARACION_MINUS_MAYUS = 'A'-'a';
    letra += SEPARACION_MINUS_MAYUS;
    return letra;
    }

Si lo probamos con el texto “Los programadores.”, obtenemos “,OS PROGRAMADORES(corcheas)”. Vaya, nos hemos equivocado en algo, pero no pasa nada. Tenemos que convertir a mayúsculas sólo lo que sean letras minúsculas y dejar intacto el resto de caracteres.:

char pasar_letra_a_mayusculas(char letra) {
    int const SEPARACION_MINUS_MAYUS = 'A'-'a';
    if // letra es una letra minúscula
        letra += SEPARACION_MINUS_MAYUS;
    return letra;
    }

Vale, tenemos montado un lío de nombres, vamos a renombrar nuestras funciones para hacerlo todo más claro:

char pasar_caracter_a_mayusculas(char caracter) {
    int const SEPARACION_MINUS_MAYUS = 'A'-'a';
    if // caracter es una letra minúscula
        caracter += SEPARACION_MINUS_MAYUS;
    return caracter;
    }

string pasar_texto_a_mayusculas(string texto) {
    // leer cada caracter y pasarlo a mayúsculas
    for (int i=0; i<texto.length(); i++) {
        texto[i] = pasar_caracter_a_mayusculas(texto[i]);
        }
    return texto;
    }

Vale, ahora se entiende mejor. Nuestro siguiente objetivo consiste en averiguar si el caracter es una letra minúscula. Eso quiere decir que está entre ‘a’ y ‘z’:

char pasar_caracter_a_mayusculas(char caracter) {
    int const SEPARACION_MINUS_MAYUS = 'A'-'a';
    if (caracter >= 'a' && caracter <= 'z')  // caracter es una letra minúscula
        caracter += SEPARACION_MINUS_MAYUS;
    return caracter;
    }

Parece que ya está. Lo probamos de nuevo y sale “LOS PROGRAMADORES.” ¡Bingo!

Con este ejemplo se pretende (de)mostrar cómo seguir un proceso iterativo y separar las tareas grandes en otras más pequeñas ayuda a no perder la visión general de qué es lo que se está haciendo y dejar un código más limpio, elegante y legible.

Es importante señalar que, a lo largo del desarrollo del programa nos hemos equivocado (se ha equivocado el autor). No pasa nada: como lo hemos desarrollado por partes, hemos descubierto rápidamente dónde estaba el error, que hemos corregido con una simple linea.

The way to opensource microblogging

I’ve recently started using Twitter, discarding (almost) all my prejuices. I’d ever thought microblogging was only about broadcasting you’re walking your dog or that you’re sooo bored, but I was wrong: it’s also an great environment to share short ideas and web pages you like without clobbering mailing lists and post thoughts and info about events and hot topics.

However, microblogging is sadly failing at the same point current social networks are: isolation. If you signup into Twitter, you won’t be able to share your micro-posts with Jaiku or Pownce users, among others. This makes users choose the biggest microblogging network to reach as more contacts as possible, which makes everybody more and more dependant of a central service/company, affecting the neutrality of the web and slowing down innovation.

Nobody would currently accept such lack of openness and neutrality in blogging, so why are we ok with it in microblogging? We need opensource microblogging platforms and reading clients, supporting interconnectivity between services and servers, freedom to migrate from one server to another keeping all your data and a flexible standard and documented API.

I’ve just read that in a README:

Laconica supports an open standard called OpenMicroBlogging
(http://openmicroblogging.org/) that lets users on different Web
sites or in different companies subscribe to each others’ notices.
It enables a distributed social network spread all across the Web.

:-) Could be Laconica the way to go?

Change We Need – a note for ourselves

Why are we afraid of change? Why can’t we say “wait, this is completely wrong” and start again from scratch? Is there any special reason to do everything the way we’re doing it nowadays?

World is full of misunderstandings, wrong decisions and lot of slackness. Move your ass now and start changing your little world. Yes, we can!

How I fell in love with Plone

Today is the World Plone Day and JoAnna suggested us to post about why do we love Plone, so here I go.

I became interested in Zope when I spotted a printed copy of The Zope Book in the Students’ Council premises of my faculty. I learned the basics of acquisition, object hierarcy and… DTML! Yes, that version of The Zope Book was so old it didn’t cover ZPT, and I build the whole website of my student’s association, Hypatia, using DTML and the ZMI.

Some months later I started contributing to the Alqua project, whose founders (Álvaro Tejero and Pablo Ruiz) were big fans of Zope and Plone and I helped migrating an plain-html site to a Plone one a year ago. That summer Álvaro attended to The Plone Conference 2007 at Naples, Italy and recommended two books to me: “Proffessional Plone Development”, by Martin Aspeli, and “Web Component Development with Zope 3″, by Philipp von Weiterhausen.

At first, these two books were too hard for me, specially PPD, and I left them in my shelves more than once thinking I would never understand the “extreme” complexity of Plone. I started learning Django and built my first real-world application: mini-litmus, a web-based QA tool for Mozilla-related products.

On July 2008 I started working for Zassh.com, a startup company, developing a sports-oriented social networking site built on Plone. There I realized that I weren’t a Plone newbie at all! Reading PPD and Philipp’s book turned out to be really helpful, and I hard-learned how to face real world Plone development issues, which were very different from what I expected. Plone is hard to tame!

Now I’ve become a documentation editor and I’m working to improve this well-known weak point of Plone. I’m e-meeting a lot of people from the community and looking forward to meet some of them personally at a sprint or conference.

Plone is a strong and mature CMS with features others have only dreamed with yet. New eggified products and modules are published every day in PyPI, exploring new concepts and design patterns. Paraphrasing Phillip J. Eby, “those who doesn’t study Plone are condemned to reinvent it”.

Happy ploning, community!