Recent posts (max 20) - Browse or Archive for more

Wordle pic for my delicious bookmarks

Via osoco I've just found out wordle.net, which allows you to generate a snapshot of the tags you used as metadata for your bookmarks.

Here's mine : http://www.wordle.net/thumb/wrdl/935988/chous%27_delicious

  • Posted: 2009-06-12 01:20 (Updated: 2009-06-12 01:23)
  • Author: chous
  • Categories: (none)
  • Comments (0)

Si eres legal comparte

Acabo de leer una entrada en el blog de Partido Pirata relativo a luchar contra la campaña del gobierno de 'si eres legal, eres legal', utilizando una web alternativa si eres legal, comparte, y tratando de desbancarla de las primeras posiciones en google mediante un google-bombing. Aunque dudo mucho que sirva para algo, aquí van mis 2 cents :).

La 'clase política' es un fraude. Por un lado, los 'representados' podemos tener cierta inclinación a pensar que ante la duda ellos serán deshonestos, o tratarán de convencernos de sus mentiras si es necesario. Por otro, hay un 'tufillo' constante en la clase dirigente de 'triunfo', lo cual va arropado por su día a día de contactos con círculos de poder. Y eso es lo que al final hace tergiversar algo tan simple como la virtud de la generosidad. Hay intereses creados que, por estar más cerca de la clase política (desayunan o comen juntos, son 'colegas', etc.), contaminan de mercantilismo hasta los valores más fundamentales.

Por hacerlo más claro. Compartir está por encima del beneficio o pérdida económico. Las patentes no funcionaron para lo que se inventaron, sólo han servido para comprometer la innovación y hacerla un bien especulativo que pocas veces repercute en algún avance para la sociedad.

  • Posted: 2008-12-24 09:25
  • Author: chous
  • Categories: (none)
  • Comments (0)

Agile Methodologies considered religion

Last years I've tried to avoid Agile. Probably those days will be soon gone, since in the company I work for there's a strong commitment to adopt agile methodologies from the near future on.

So I'll have to adapt, I guess. There's no much space for discussion, but I still think Agile success means a failure in software engineering. Sounds dramatic, but I think its popularity has grown exclusively in business-focused software, since it's good to control (not exactly manage) software projects.

The main reason why agile practices are so popular among non-technical people is because it allows the software to follow their short-term criteria. They get the control, and they are no longer required to think deeply into their requirements, since the great news is that they can adapt when they actually see they were wrong. So now we have to deal ourselves with their trial-and-error approaches. This comes with the fact that now we (software engineers) have lost power. Maybe we didn't want it, or didn't use it, but it's gone. We are expected just to follow orders, and at the same time we don't need to think if what we develop will be able to handle probable future requirements. Nobody cares about them anymore.

Summarizing the point, we've lost the most precious area of our profession: modelling the abstractness. And nobody is doing it.

So I received some workshops about Agile. Of course, everything is carefully presented: all keywords are positive, some "benefits" but no "drawbacks" slides, and the annoying fallacy 1 of trying to prove Agile is correct by exaggerating waterfall possible outcomes.

I tried to find people daring to say they don't like agility, and found one 2. However, if you read the comments, youĺl see what I perceived in the workshops: there's no discussion, Agile is good, if it doesn't work for you is your fault.

What kind of approach is that? What is Agile invented for? To exalt the reputation of the Manifesto signers? To build a business on top of that? To write useless3 books? Do we need this? I don't buy it. I don't accept becoming a "believer" of someone else's ideas. Why Agile is not applied to non-business (-focused) software development, such as free software? I was told they're completely different stuff. Sure, but they define what we should consider success, in terms of software.

Probably I'm upset because I'm about to lose what I've fought hard to achieve. Say respect, confidence, long-term results, while keeping the eye on the business. All this, thanks to think abstract, to look further what I was told to do, to care about what I do, and to avoid thinking exclusively if this is taking too long.

From my point of view, we are asked to get rid of the engineering stuff and do only what we're told to do. In practice, this is a list of business-visible features. It's not only that the rest is not important, but the lack of flexibility to non-feature-oriented tasks means they won't be supported in practice. In other words: nobody but us wass doing engineering. Now we have to copy that if we want to be "good enough".


  1. 1. http://en.wikipedia.org/wiki/Argumentum_ad_baculum Argumentum ad baculum
  2. 2. http://antiagile.indigenious.ro/ Agile Development in Outsourcing Considered Harmful
  3. 3. I have only regretted of purchasing two books: One from Robert C. Martin and one of Martin Fowler

chous, ecamino, wiily

This blog is used by a group of individuals who don't share some of their interests, but we're friends. We use this blog to say whatever we want, to get feedback from others, and to hear critics from whoever dares! :D.

The participants' interests range from software engineering, politics, free-software, and anything they eventually think worth publishing.

  • Posted: 2008-09-21 07:51 (Updated: 2008-09-22 17:59)
  • Author: chous
  • Categories: about
  • Comments (0)

Smart ps

Just a minor Linux hack. You can override ps command to get rid of the usual | grep -v grep.

Define your own ps version in /usr/local/bin:

#!/bin/bash
/bin/ps $@ | grep -v -e "^.* \+.\+ $$ \+.*" | grep -v grep

Don't forget to make it executable, but make sure you have complete control of the basic commands you execute, since overriding commands such as ps is the first thing to do when implementing rootkits.

QueryJ screencast

I recorded a screencast that describes the methodology we use at Ventura24 regarding designing, modelling and accessing persistence layers from an application.

I'd have wished to spend more time explaining QueryJ in particular, but it was only part of what we wanted to describe. Anyway, you can enjoy the QueryJ experience without installing it :).

The screencast is 50-minute long, and take into account I'm not as fluent in english as I'd like.

There're two versions, the original (1280x1024), in both ogg format, and one adapted for ipod.

In any case, I'd be glad to hear about your comments.

QueryJ meta-language

As you may already know, the main development of QueryJ is right now being pushed by Ventura24 requirements.

We are including more features as soon as we find nice-to-haves. First, the query validation, the customization of templates to make Spring be aware of heterogeneous transactions (Connection/DataSource), some performance improvements, and so on.

Lately I made QueryJ support a dsl to support logical statements as part of the comments of the physical table model. So far, the following statements are interpreted:

  • static column-name

Used to improve performance by avoiding the need to access the database to operate on certain static tables, such as typecodes. This keyword makes QueryJ generate constants in the Java side with the contents of the table, at development time. The column-name is used to build the constant name.

  • @isa parent-table

Identifies the table as a child of given one. This means it inherits parent's attributes and relationships, besides its own.

  • @isatype type-table

For a parent table in an ISA relationship, it indicates which additional table is used to specify all possible children. That is generally not needed in practice, but makes the ISA more clear and self-explanatory.

  • @decorator

Indicates all DAO operations will use a decorator instead of a plain ValueObject. This is useful in refactorings, in which you had a ValueObject with a number of attributes (since its associated table was pretty wide), and you change it to use a metadata table(s) for the optional ones, so you can add more in the future without DDL changes. In such case, the API for the ValueObject changes, but you can make it appear as if it were the same, by using decorators. Since this kind of refactoring changes the API significantly, you'd end up with a lot of compile errors throughout all client code. Using @decorator allows you to reduce such errors by changing ValueObject to ValueObjectDecorator, and writing (and caching) logic for retrieving the missing attributes via DAO calls.

  • @relationship (foreign-key1),(foreign-key2)

This indicates to QueryJ that the table is an implementation of a many-to-many relationship, and that it makes no sense to build DAO or ValueObject for it.

  • @readonly

It's used to indicate that the column is managed completely at the database side, and that it cannot be modified from the application. This is usually the case of last-modified or creation-date helper attributes: you don't want/need them to be parameters in Java by any means. With this keyword, you can access them, but you're never supposed to specify them.

  • @bool trueValue,falseValue[,nullValue]

Denotes a column is a boolean value, regardless of its declared type. QueryJ declares it as boolean in the Java side, and transforms its value to given constants when accessing the database. In case the column is not nullable, and you want to be able to work with null values in the application, you'd then specify also the value to represent nulls.

  • @isarefs (value1, child-table1) ... (valueN, child-tableN)

For static tables used as helpers of ISA relationships, this keyword can be used in the actual attribute that enumerates all possible ISA children. That will be used in the future to improve ISA support by omitting redundant information from the child tables. This only makes sense in tables referred by ISA parents via @isatype keyword.

  • @oraseq sequence

This keyword attaches an Oracle sequence to a concrete attribute.

For more information, please take a look at the ANTLR grammar.

Enjoy!

Blog/podcast thoughts

I read somewhere the average lifetime of a blog is 6 months.

Despite I write less often lately, and that my posts are brief explanations of simple scripts or news, I plan not to stop writing.

Now I'm not sure whether using Trac as blogging system fulfills my needs. I don't really care about formatting too much, so wiki-like format support is enough for me. The important thing is RSS. I'll go on with current deployment, since anyway I don't think I have enough hardware resources to install a separate blogging system.

The reason why I wanted to start blogging has not changed: I still like to share some opinions, thoughts, or pieces of work. At first it can be a little embarassing, but it also pays back.

So I'll try to retake some unfinished topics. But during last year, I've become a podcast addict1, even though all I listen is in english and I don't understand everything since it's not my mother language.

However, yesterday I downloaded a podcast entry from Adam Curry's Daily Source Code, that I did enjoy very much, up to the point to consider the possibility to do some amateur, home-made, podcasting myself.

The problem is that it takes time, it's much more embarrassing than plain blogging, and nobody I asked to is interested in co-authoring it.

Let's see if I have real guts at last...


  1. 1. This is my opml

  • Posted: 2007-07-22 08:05 (Updated: 2007-07-22 08:08)
  • Author: chous
  • Categories: chous
  • Comments (0)

Server moved to Atlanta

The websites for www.acm-sl.org, svn.acm-sl.org, and www.acm-sl.com have now moved to a remote UML-based hosting.

The server is not full of resources, but now that I can compare I think the bottleneck was my home ADSL connection. Let's hope hosting provider offers vserver-patched uml-compatible kernels someday soon...

  • Posted: 2007-07-21 09:08 (Updated: 2007-07-21 09:09)
  • Author: chous
  • Categories: chous
  • Comments (0)

Script to display inline descriptions of USE flags from emerge -uv output

When updating a gentoo system, knowing what are each USE flag for is important. USE flags affect how each package is built, whether it includes support for optional features, and so on.

For that reason, I pay attention to each flag. It makes me constantly grepping /usr/portage/profiles/use.* to know what is the meaning of each flag.

I've created a script to parse emerge -uv output and display the description of each affected flag, so that you can setup your /etc/portage/package.use/ file accordingly.

If you're interested, you can find it here.

Script to sort USE flags

When updating my system, mplayer got affected, and I found out that I already had a number of USE flags defined in my /etc/portage/package.use/mplayer.

I like to maintain the USE flags sorted alphabetically, so I decided to write a simple script to do it for me.

If you're interested, you can find it here.

Unhiding custom entries in /proc in vservers

I use vservers very often. They are easy to maintain and to deploy, and allow clean environments for servers with different purposes, avoiding the need to invest money on hardware resources.

I recently installed Oracle on a vserver, and got some errors from the Enterprise Manager application saying:

java.lang.Exception: Cannot read /proc/partitions

I noticed that such file was not unhidden by vprocunhide script. Such script uses two configuration files (in given order):

  1. /etc/vservers/.defaults/apps/vprocunhide/files
  2. /usr/lib/util-vserver/defaults/vprocunhide-files

The format is simple: each line points to a file in /proc to unhide. You can actually hide them, prepending a - character. Refer to the actual source code for /usr/lib/util-vserver/vprocunhide to get the full options and syntax.

In our context, we just need to

mkdir -p /etc/vservers/.defaults/apps/vprocunhide/
echo "+/proc/partitions" >> /etc/vservers/.defaults/apps/vprocunhide/files

The Oracle problem, however, persists. It now says java.lang.Exception: Unknown format in /proc/partitions, but it seems to be independent of hosting it inside a vserver. Probably some of the reasons why Oracle is selective regarding Linux kernels and distributions are issues like this.

Firefox Add-ons

I've just created a page with Firefox Add-ons, their links and brief descriptions, so that I can evaluate them and have an homogeneous toolset in all computers.

Take a look if you're interested: firefox-addons.

Script to generate bibtex entries from filenames

I've written a small bash script to generate BibTeX entries from the information found in the filename passed as argument.

Since the pdf files I have respect a format like this: publisher - book name[ - year]?.pdf I've been able to write a script to generate the following:

@book{filename_translated,
  title="book name",
  publisher="publisher",
  note="complete filepath"
}

The complete source is in Subversion (misc/trunk/bin/importbookcd.sh).

Blog posts migrated

I've just finished re-publishing posts from old Roller system.

I did it by directly performing SQL queries against the MySQL database, retrieving the text, fixing all invalid characters (due to some encoding problems which arose after a MySQL version upgrade), and republishing them directly using the Trac web interface.

The only problem with this approach has to do with the publishing timestamp. Blog plugin uses now no matter the timestamp you want it to use (which it's probably good). Since by default the plugin takes the timestamp of when the post was started to be written, and uses it as the name of the associated wiki page, by respecting the original timestamp in the post names I was able to do some SQL logic to fix the pubtime timestamp in Trac database (SQLite).

So I did the following:

  1. Start emacs
  2. M-x sql-sqlite -> database: trac.db
  3. select name,time from wiki where name like '200%';
  4. Record a macro to translate each one of the entries into update wiki set time=(select strftime("%s", datetime(t)) from (select substr(aux, 0, 10) || " " || substr(aux, 12, 6) as t from (select replace(replace(name, ".", ":"), "/", "-") as aux from wiki where name="XXX"))) where name="XXX"; and write them in a brand new buffer called *rows*.
  5. Execute the macro for each one of the retrieved rows.
  6. M-x switch-to-buffer *rows*
  7. C-x h
  8. M-w
  9. M-x switch-to-buffer *SQL*
  10. C-y [enter]
  11. commit

Voilá :) The problem is dealing with the date format YYYY/mm/DD/HH.MM used in the blog plugin, which has to be translated to a date. There's some lack of support for date formats in SQLite, so I had to translate such format to YYYY/mm/DD/HH:MM, then to YYYY-mm-DD-HH:MM, and finally split it into YYYY-mm-DD and HH:MM, so that I can concatenate them with a blank space in between.

  • Posted: 2007-05-23 18:24 (Updated: 2007-05-25 18:47)
  • Author: chous
  • Categories: chous
  • Comments (0)

Linking to SourceForge

Some of the projects now hosted here were initially signed up in SourceForge.

I decided to update them again, pointing them to this server, and start defining a release mechanism so that they can be downloaded from the SF mirrors.

  • Posted: 2007-05-17 06:03 (Updated: 2008-09-21 07:37)
  • Author: chous
  • Categories: (none)
  • Comments (0)

Milestone names

From now on I'll use a different naming scheme for milestones: famous algorithms.

The purpose is to learn something or at least invite to a brief reading about the concrete algorithm.

The list I'll use is provided by Wikipedia of course:

http://en.wikipedia.org/wiki/List_of_algorithms

  • Posted: 2007-05-02 21:19
  • Author: chous
  • Categories: (none)
  • Comments (0)

Trac-hosted blog

I decided not to restore the previous server at blog.acm-sl.net, which was using JRoller software. Once I migrated the servers, I found Trac useful to manage not only source-code views, but also as a full-featured wiki. The blog plugin lacks some features comparing to previous server, but fulfills my requirements.

Now it's time to migrate previous posts.

Keep tuned :).

  • Posted: 2007-05-02 19:02
  • Author: chous
  • Categories: (none)
  • Comments (0)

Cambiar TAGS de un fichero por información

Esto que voy a contar de forma breve tiene relación con el escrito titulado "¿tres capas?"1 en el cual expongo una forma de realizar interfaces de usuario de forma sencilla mediante la utilización de html y cgi.

En un momento dado relato que el cgi escrito en C/C++ deberá pasear el documento html que se quiere presentar al usuario y que se cambiarán ciertos TAGS presentes en dicha página por datos que decide la capa de negocio o parte inteligente de la aplicación.

Esto, en general, se hace parseando el documento de la forma en que se describió en el ártículo anterior, pero hay una forma mucho más rápida y sencilla la cual paso a describir ahora.

Sencillamente en el documento que será presentado se añade un %s en cada punto donde se quiera añadir algo de forma dinámica. Para que quede claro, se escribe el documento html a mano o como queramos y donde nos interese añadir algo se introduce un %s.

Supongo que cualquiera que sepa algo de C/C++ ya ve por donde me estoy encaminando. Efectivamente, cuando se va a presentar el documento y ya lo hemos leido del disco duro y lo tenemos en forma de string, sin parsear ni hacer nada complicado se puede sustituir el %s por lo que queramos con un sencillo "sprintf()" y lo mejor es que podemos poner tantos %s como queramos.

Os recomiendo man sprintf, pero en general se utiliza mucho y seguro que lo conocéis. En cualquier caso y por encima, el sprintf es exactamente igual que un printf() pero en vez de utilizar la salida estándar, lo que hace es copiar el string en la memoria que se haya reservado a tal efecto, sustitiyendo, en este caso, todos los %s por lo que se ponga a partir del tercer parámetro.

Ejemplo clarificador:

sprintf(ptr_memoria,"HOLA %s ADIOS","PEPE");

Como resultado, tendríamos un string llamado ptr_memoria con la información "HOLA PEPE ADIOS"

Si queremos sustituir un valor numérico podríamos poner %d y un número directamente. Sigo recomendando un man sprintf a quien no lo conozca adecuadamente.

Bueno, lo contado es algo muy sencillo y desde luego es muy probable que este método lo utilice mucha gente, pero puede ser que no a todo el mundo se le ocurra que poner un %s directamente en los documentos nos facilite el trabajo tanto.

Voy a poner una clase de C++ que hace exactamente esto, por si alguien quiere utilizarla o le da una idea. No está muy comentada, pero es bastante autoexplicativa.

Las funciones open_file, read_file, close_file son una encapsulación de funciones de C para el manejo de ficheros y realizán exactamente lo que su nombre indica.

La función CambiarTag puede cambiar hasta 6 %s que se pasan en un array de strings, con eso me vale a mi de sobra y el que quiera más parámetros o que se realice de forma iterativa que lo piense un poco.

Recordar que hay que liberar la memoria que se devuelve en esta función en donde se llame.

#include "GeneradorHtml.h"
#include "../comunes/file_control.h"
#include <string.h>
#include <stdio.h>
#define MAX_ELEMENTOS 6
GeneradorHtml::GeneradorHtml(char *lruta)
{
  char *ptr_ayuda;
  open_file(lruta,"r");
  read_file(&ptr_ayuda);
  texto_html = new char[strlen(ptr_ayuda)] ;
  strcpy(texto_html,ptr_ayuda);
  close_file();
}
GeneradorHtml::~GeneradorHtml()
{
  delete texto_html;
}
//Hay que liberar en donde se utilice la memoria que se devuelve.
char* GeneradorHtml::CambiarTag(char lnuevo_elemento[][100])
{
  int llen_elementos = 0;
  int llen_html =  strlen(texto_html);
  int llen_total = 0;
  char *lnuevo_html = 0;
  int i;//iterador
  for(i = 0; i<MAX_ELEMENTOS; i++)
  {
    if(lnuevo_elemento[i] == 0)
      break;
    llen_elementos = llen_elementos + strlen(lnuevo_elemento[i]);
  }
  //espacio necesario para albergar todo el texto html cambiando las partes necesarias.
  llen_total = llen_elementos + llen_html;
  lnuevo_html = new char[llen_total+100];
  switch(i)
  {
    case 0:
      strcpy(lnuevo_html,texto_html);
    break;
    case 1:
      sprintf(lnuevo_html,texto_html,lnuevo_elemento[0]);
      //sprintf(lnuevo_html,texto_html,"HOLA");
    break;
    case 2:
      sprintf(lnuevo_html,texto_html,lnuevo_elemento[0],lnuevo_elemento[1]);
    break;
    case 3:
      sprintf(lnuevo_html,texto_html,lnuevo_elemento[0],lnuevo_elemento[1],lnuevo_elemento[2]);
    break;
    case 4:
      sprintf(lnuevo_html,texto_html,lnuevo_elemento[0],lnuevo_elemento[1],lnuevo_elemento[2],lnuevo_elemento[3]);
    break;
   case 5:
      sprintf(lnuevo_html,texto_html,lnuevo_elemento[0],lnuevo_elemento[1],lnuevo_elemento[2],lnuevo_elemento[3],lnuevo_elemento[4]);
    break;
    case MAX_ELEMENTOS:
      sprintf(lnuevo_html,texto_html,lnuevo_elemento[0],lnuevo_elemento[1],lnuevo_elemento[2],lnuevo_elemento[3],lnuevo_elemento[4],lnuevo_e
    break;
  }
  return lnuevo_html;
}

Analogías entre gestión de software y de música

Desde hace poco tengo a mi disposición una iPod. No es que esté orgulloso, máxime cuando por el momento me resulta muy poco asequible cambiarle el firmware por uno libre.

Aunque no todo está perdido: afortunadamente mi iPod nunca conocerá iTunes :).

En cualquier caso, dejando a un lado el dispositivo de moda, el haber dedicado algo de tiempo a organizar la música, conocer qué son los Podcast, etc. me ha hecho pensar sobre un concepto sencillo que nunca he aprovechado demasiado: las playlist.

Aunque suene trivial, los dispositivos de almacenamiento que usaba hasta la fecha (fundamentalmente cds o mp3 de pequeña capacidad) permitían no esforzarme mucho en cómo organizar los archivos: un directorio por autor, otro por disco y poco más. Fue cuando perdí la organización presente en mis cds cuando me di cuenta de que en realidad, las playlist no son más que lo que se denominan tags en sistemas de control de versiones como CVS o Subversion.

En el ámbito de desarrollo de software (que es dónde mayor acogida tienen estos sistemas, a pesar de que es provechoso para cualquier documento que vaya evolucionando) se utilizan tags y branches para referenciar colectivamente un conjunto de archivos (en el primer caso) y poder bifurcar el progreso de los mismos (en el segundo). Es decir, a partir de un nombre común, se puede obtener la foto de los archivos en el instante en el que se creó el tag.

Las playlist, por otro lado, pueden llevar asociadas connotaciones semánticas muy diversas en función de la intención del usuario o de quien las cree, pero en el fondo son lo mismo: una etiqueta única que permite obtener un conjunto concreto de ficheros.

Si algunos habéis descubierto ya el placer de usar Amarok, seguramente conozcáis ya sus playlists dinámicas, definidas en función de lo que más te guste o más frecuentemente escuches. Este tipo de playlists son análogas a los branches, con una salvedad: los archivos de mp3 son fijos, con lo cual el concepto de branch se ve reducido a la evolución temporal de archivos cuyos únicos cambios son ser añadidos o borrados del branch.

Y para terminar las analogías, el calvario de actualizar los tags Id3 (que por otro lado se ve aliviado con EasyTag) no se da tanto en el software, ya que los metadatos asociados a cada archivo son escasos.

Aun así, algo parecido se da cuando uno se enfrenta a conflictos derivados de los ^M y atributos como el "eol-style" (en Subversion). Una diferencia fundamental es que, en el caso de los archivos ogg o mp3, el nombre del fichero es un metadato más (con EasyTag se puede generar a partir de los demás), mientras que en los sistemas de gestión de versiones lo habitual es que se use como clave primaria (tal como lo hace el sistema de archivos).

Lo bueno de los Id3 es que definen un conjunto de atributos fijo. Lo malo es que los valores por lo general estarán desnormalizados.

Uno puede normalizar su colección, con esfuerzo, pero es dudoso que si la comparara con la de otra persona el criterio coincidiera sin problemas, y el encoding no hace sino empeorarlo.

Ojalá se llegara a un punto en el que, aparte de modificar el continente, fuéramos capaces de actualizar el contenido con la misma facilidad, tal como se hace en el software libre.

Obstáculos: DRM y creatividad musical. Y es que ya se puede vivir sin software propietario, pero el porcentaje de música libre es irrisorio.