Just a little bit freak

miércoles 25 de enero de 2012

El mecanismo de conexiones, señales y slots en Qt

Este post asume que el lector tiene ciertos conocimientos en programación C++ y en la librería Qt. Si no sabes de que te estoy hablando, es mejor que dediques tu tiempo a leer otro sitio, porque te vas a aburrir de lo lindo. Avisado quedas.



=== La base teórica ===

El mecanismo de señales y slots es una de las características mas importantes de la librería Qt, probablemente la que le diferencia de otros framework para desarrollar interfaces de usuario.

Las señales y los slots se usan para las comunicaciones entre los objetos del interfaz. En general, la señal (signal) parte de un objeto "emisor" y llega a un objeto "receptor". El objeto receptor decide si ejecuta un slot y finaliza el proceso, o emite una nueva señal que propaga el evento hacia otro objeto receptor. El proceso se puede repetir.

Como ejemplo sencillo, imagina un botón de "Apagar". Cuando el usuario lo pulsa, el boton genera la señal clicked(). Y en respuesta a esa señal, el sistema ejecuta un slot que hace un apagado ordenado de todo el sistema.

Para establecer una conexión entre la señal emitida por un objeto "emisor" y un slot que ejecuta el objeto "receptor", se usa el metodo connect() y las macros SIGNAL() y SLOT(). La sintaxis es esta:

    connect(emisor, SIGNAL(signal_emitida()), receptor, SLOT(slot_doaction()));


Cuando el widget "emisor" genera la señal "signal_emitida", el widget "receptor" ejecuta el código del slot "slot_doaction". La llamada connect, y las macros SIGNAL() y SLOT() forman parte de la sintaxis de Qt, y no son parte del estandar C++. Para compilarlas, se usa un meta-object compiler (moc) que traduce estas macros en C++ estándar. Esta parte escapa del propósito de este post , aunque si sientes interés, no dudes en preguntarme.

Algunas consideraciones a tener en cuenta:

* Una misma señal puede conectarse a distintos slots
* Distintas señales pueden conectarse a un mismo slot
* Una señal puede conectarse a otra señal, lo que emite una segunda signal en el widget receptor inmediatamente después de recibir la primera.

La lista de parámetros de la señal signal_emitida(signature) debe coincidir con la lista de parámetros del slot_doaction(signature). Pero el slot slot_doaction(signature) puede tener menos parámetros que los que tiene la señal signal_emitida(signature), en cuyo caso los parámetros adicionales son simplemente ignorados. Aunque parezca un poco extraño, fíjate que tiene sentido, ya que Qt es capaz de ignorar argumentos sobrantes, pero en ningún caso puede inventar argumentos de la nada. Algunos ejemplos para aclarar este punto:

                   Signals      Slots                   ¿isOK?
rangeChanged(int, int) setRange(int, int) OK
valueChanged(int) setValue() OK
clicked() setValue(int) NOK


Todas las clases que heredan de QObject (o alguna de sus subclases como QWidget), pueden contener señales, slots y conexiones. Pero para que sea posible definirlas, es necesario que la clase mencione la macro Q_OBJECT al comienzo de su declaración.


=== Sintaxis en la práctica ===

Veamos un ejemplo de como se realiza una conexión. Para ello, necesitamos dos clases ("Emisor" y "Receptor") que sean agregaciones de una clase contenedora W (dos partes componentes, o si lo prefieres, dos variables de W). Para enviar un mensaje desde "Emisor" hasta "Receptor" haríamos la siguiente conexión en W (pongo pseudocódigo para que te quedes con la idea):

    class W: public QObject
{
Q_OBJECT
...
Emisor e;
Receptor r;
connect(e, SIGNAL(signalChangePos()), r, SLOT(slotChangePosition()));
};

class Emisor: public QObject
{
Q_OBJECT
...
signal signalChangePos();
...
emit signalChangePos();
};

class Receptor: public QObject
{
Q_OBJECT
...
slot slotChangePosition();
};


Veamos ahora la declaración de una clase MiWidget que maneja señales y slots. MiWidget hereda de QWidget, y a su vez QWidget hereda de QObject:

    class MiWidget : public QWidget
{
Q_OBJECT // Macro es necesaria cuando la clase define sus propias señales o slots

public:
MiWidget(QWidget *parent = 0);
void foo(QString &text);

signals: // señales emitidas por esta clase
void findnext(const QString &str);
void findprev(const QString &str);

private slots: // slots de esta clase
void enableFindButton(const QString &text);
};


Supongamos que el metodo foo emite una signal, veamos como se realiza la implementación:

    void MiWidget::foo(QString &text)
{
emit findprev(text); // se emite la señal findprev con el texto "text"
}



=== Un ejemplo práctico ===

Un escenario común ocurre cuando quieres pasar valores constantes en la sentencia connect. Esto ocurre por ejemplo cuando quieres implementar un teclado QWERTY usando QPushButtons como teclas. Podrías pensar que lo lógico es implementar algo como esto:

    connect(key_q, SIGNAL(pressed()), panelTexto, SLOT(keyPressed('q')));
connect(key_w, SIGNAL(pressed()), panelTexto, SLOT(keyPressed('w')));
connect(key_e, SIGNAL(pressed()), panelTexto, SLOT(keyPressed('e')));
connect(key_r, SIGNAL(pressed()), panelTexto, SLOT(keyPressed('r')));
connect(key_t, SIGNAL(pressed()), panelTexto, SLOT(keyPressed('t')));
...


Pero esto no es valido en Qt, y no te funcionaría. Para implementar un teclado, la opción fácil sería usar un montón de QPushButton, y asignar a cada uno un slot diferente. La implementación sería como esto:

    connect(key_q, SIGNAL(pressed()), panelTexto, SLOT(press_q()));
connect(key_w, SIGNAL(pressed()), panelTexto, SLOT(press_w()));
connect(key_e, SIGNAL(pressed()), panelTexto, SLOT(press_e()));
connect(key_r, SIGNAL(pressed()), panelTexto, SLOT(press_r()));
connect(key_t, SIGNAL(pressed()), panelTexto, SLOT(press_t()));
...


Y la lista de slots:

    private slots:
void press_q();
void press_w();
void press_e();
void press_r();
void press_t();
...


Parece una exageración tener 102 slots, todos prácticamente con el mismo código. Pero, ¿a caso se te ocurre alguna alternativa mejor? Para hacer esto de una forma mas eficiente y sencilla de mantener, con un único slot, se usa la clase QSignalMapper. Con su ayuda, podríamos hacer esto:

    signalMapper = new QSignalMapper;

signalMapper->setMapping(key_q, QChar('q'));
signalMapper->setMapping(key_w, QChar('w'));
signalMapper->setMapping(key_e, QChar('e'));
signalMapper->setMapping(key_r, QChar('r'));
signalMapper->setMapping(key_t, QChar('t'));
...

// Conexiones de los button con el signal mapper
connect(key_q, SIGNAL(pressed()), signalMapper, SLOT(map());
connect(key_w, SIGNAL(pressed()), signalMapper, SLOT(map());
connect(key_e, SIGNAL(pressed()), signalMapper, SLOT(map());
connect(key_r, SIGNAL(pressed()), signalMapper, SLOT(map());
connect(key_t, SIGNAL(pressed()), signalMapper, SLOT(map());

// Y conexion del signal mapper con el slot genérico
connect(signalMapper, SIGNAL(mapped(QChar)), panelTexto, SLOT(setText(QChar)));


Y en el slot setText() irias pintando los distintos caracteres en el objeto "panelTexto", según la tecla pulsada por el usuario.

viernes 25 de marzo de 2011

Mens sana in corpore sano

El deporte ha formado parte de mi vida desde que tengo uso de razón, y probablemente así siga siendo hasta el día que me falle la salud. Empecé a practicarlo con 11 años, y desde entonces hasta hoy, 23 años después, ahí seguimos, a tope. Para mi ya forma parte de una filosofía de vida. Vivir sin el deporte sería como vivir sin dormir, o vivir sin comer.



Nunca destaqué por tener unas cualidades atléticas sobresalientes. No obstante, el esfuerzo y las ganas continuas de mejorar me han llevado a labrar un historial deportivo del que hoy en día me siento, por que no decirlo, orgulloso. Y precisamente se trata de este historial deportivo del que hoy os voy a hablar en este post:



== Futbol ==

[1987-1988]
Escuela infantil de futbol Selma Junior (Castellón)



== Baloncesto ==

Recuerdo mis años como jugador de baloncesto con muchísima nostalgia. Con los años he perdido contacto con demasiada gente, decenas de compañeros de equipo, entrenadores, fisioterapeutas... De todos vosotros guardo muy buenos recuerdos. Me acuerdo de aquella remontada ganando "in extremis" contra el equipo valenciano de "La Salle", uno de los mejores de toda la Comunidad Valenciana, después de perder la primera parte por mas de 25 puntos, y el pabellón de Grapa repleto de gente rugiendo y aplaudiendo... Todavía se me pone la piel de gallina. Me acuerdo muchas veces de todos vosotros.

[1987-1988]
Escuela infantil de baloncesto Taugres Castellón

[1988-1989]
Escuela infantil de baloncesto Taugres Castellón
Seleccionado como cantera del club en la "Operación Altura '89"

[1989-1990]
Temporada completa en el Cadete B club de baloncesto Taugres Castellón

[1990-1991]
Temporada completa en el Cadete A club de baloncesto Taugres Castellón

[1991-1992]
Temporada completa en el Juvenil A club de baloncesto Atletic Basquet Castelló (ABC)
Parte de la temporada doblo entrenamientos con el juvenil B del mismo club

[1992-1993]
Temporada completa en el Juvenil A club de baloncesto Ceramicas Gaya

[1993-1994]
Pretemporada e inicio de temporada con el Junior/Senior club de baloncesto Ceramicas Gaya



== Rutas en bicicleta ==

La fecha indica la primera vez que realicé la ruta, aunque algunas son rutas habituales de entrenamiento. Como por ejemplo la subida al Desert de les Palmes, con un desnivel de mas de 700 metros de altura, la he realizado decenas de veces. Precisamente en el descenso de esa carretera tuve mi primer (y único) accidente con la bicicleta. Me rompí dos dedos de la mano contra un coche en un accidente que me podría haber costado la vida.

[1991]
Castellon - San Juan de Moro - Castellon (36Km)
Castellon - Onda - Castellon (48Km)

[1992]
Castellon - San Juan de Moro - Villafames - Borriol - Castellon (56Km)
Castellon - Borriol - Cabanes - Castellon (56Km)
Castellon - Magdalena - Desert de les Palmes - Castellon (30Km)

[1993]
Castellon - San Juan de Moro - Alcora - Castellon (42Km)
Grao de Castellon - Oropesa - Grao de Castellon (36Km)
Castellon - Borriol - Atzaneta - Benafigos (58km)

[1994]
Grao de Castellon - Magdalena - Desert de les Palmes - Grao de Castellón (25Km)
Grao de Castellon - Pico del Bartolo - Grao de Castellon (29Km)
Castellon - Villafames - Costur - Castellon (60km)
Grao de Castellon - Oropesa (por la costa) - Grao de Castellon (36Km)



== Gimnasios fitness ==

El fitness forma parte del deporte que practico habitualmente 3 o 4 días por semana. Algún día os hablaré sobre mis rutinas de entrenamiento, de las que hay para hablar largo y tendido.

[01/1995 - 01/2004]
Gimnasio en mi casa

[02/2004 - 07/2004]
Gimnasio Amstelpark, Amsterdam (Holanda)

[08/2004 - 11/2004]
Gimnasio en mi casa

[12/2004 - 02/2005]
Gimnasio Club Estudio Praga, Madrid

[02/2005 - 06/2006]
[Gimnasio Muscle Gracia, Bilbao (Vizcaya)

[07/2006 - Actualmente]
Gimnasio Balla Shen Dragon, Terrassa (Barcelona)



== Montañismo ==

Mi pasión por la naturaleza no queda bien reflejada en esta lista de montañas tan corta. Espero y deseo poder ampliar esta lista en los próximos años:

[8/1994]
Pico del Bartolo (724m)
Parque natural del Desert de les Palmes (Castellón)
Ruta en bicicleta partiendo desde Castellón de la Plana.

[5/2009]
Pico de San Jerónimo (1224m)
Parque natural de la muntanya de Montserrat (Barcelona)
Ruta corriendo partiendo desde Monistrol de Montserrat.

[7/2009]
Pico La Mola (1104m)
Parque Natural Sant Llorenç del Munt (Barcelona)
Ruta de trekking partiendo desde Sant Feliu del Raco.

[4/2011]
Pico del Collbaix (547m)
Parque natural Sant Llorenç del Munt (Manresa, Barcelona)
Ruta de trekking partiendo desde San Joan de Vilatorrada.

[4/2011]
Pico del Penyagolosa (1814m)
Parque natural del Penyagolosa (Castellón)
Ruta de trekking partiendo desde la Hermita de San Juan de Penyagolosa.

[07/2011]
Pico del Montcau (1066m)
Parque Natural Sant Llorenç del Munt (Barcelona)
Ruta de trekking partiendo desde el Coll d'Estenalles y pasando por la Mola.

[07/2011]
Pico superior del Pedraforca (2497m)
Parque Natural del Cadí-Moixeró (Barcelona)
Ruta de trekking partiendo desde el parking del mirador de gresolet.

[08/2011]
Ruta circular desde Benafigos por el Rio Montlleo (945m)
Parque natural del Penyagolosa (Castellón)
http://es.wikiloc.com/wikiloc/view.do?id=995398
Video 1/2 y 2/2 en YouTube.

[08/2011]
Ronda Vallesana Terrassa
Parque natural de Sant Llorenç del Munt i l'Obac
http://es.wikiloc.com/wikiloc/view.do?id=1261016



== Carreras populares ==

Soy corredor habitual desde que dejé el baloncesto con 18 años. A 15km de entrenamiento semanales, distancia que supero holgadamente todas las semanas, calculo que mis piernas deben haber corrido mas de 10.000km. Desde hace unos 6 años, me aficioné a participar en carreras populares. Estas son algunas de las carreras en las que he participado:



09/2007
I travessa Circutor - Monasterio Montserrat (23km: 4h 30m)

10/2007
II gran premio 42 y pico Castellón (10km: 49m 47s)

10/2008
Cursa de fons a Sant Muç, Rubi (10Km: 48m 56s)

09/2008
Cursa festa major Matadepera (10km: 51m 49s)

04/2008
Mullat i Corre circuit de Montmelo (10km: 47m 27s)

09/2008
II travessa Circutor - Monasterio Montserrat (23km: 4h 05m)

01/2009
IX mitja marató de Terrassa (21Km: 2h 0m 45s)

07/2009
XXX Cursa Festa Major Terrassa (8km: 37m 35s)

07/2009
XXVII Cursa atlètica popular Ca n'Anglada (6km: 25m 02s)

09/2009
Cursa festa major Matadepera (10km: 52m 44s)

10/2009
III travessa Viladecavalls - Monasterio Montserrat (23km: 3h 52m)

07/2010
XXXI Cursa Festa Major Terrassa (8km: 39m 53s)

09/2010
Cursa festa major Matadepera (10km: 49m 44s)

09/2010
Cursa Mercè en Barcelona (10km: 44m 44s)

01/2011
Cursa Santi Centelles de Terrassa (5Km: 22m 35s)

04/2011
IV Carrera a pie costa Azahar (10km: 45m 59s)

05/2011
XI Cursa de Muntanya de Rubí (11km: 1h 10m 16s)

06/2011
XXVII Cursa atlètica popular Pla de Bonaire (7km: 32m 22s)

06/2011
XXIX Cursa atlètica popular Sant Llorenç (5.5km: 22m 30s)

06/2011
I Cursa popular Grao de Castellò (5km: 21m 31s)

07/2011
XXXII Cursa Festa Major Terrassa (7.5km: 37m 59s)

07/2011
XXIX Cursa atlètica popular Ca n'Anglada (6km: 23m 24s)

09/2011
Cursa festa major Matadepera (10km: 46m 39s)

09/2011
Cursa Mercè en Barcelona (10km: 44m 41s)

10/2011
V travessa Viladecavalls - Monasterio Montserrat (23km: 3h 54m)

01/2012
XIII mitja marató de Terrassa (21km: 1h 56m 17s)




== Entrenamiento running ==

Zonas donde realizo (o he realizado en el pasado) entrenamientos habitualmente. En muchas de ellas me podéis encontrar entrenando hoy en día.

Camino de la Fileta (Castellón)
Camino del rio seco (Castellón)
Avd. Ferrandis Salvador (Castellón)
Camino de la Plana (Castellón)
Camino Serradal (Castellón)
Avd. del Mar (Castellón)
Amstelpark, Amstelveen (Holanda)
Paseo del Museo Guggenheim (Bilbao)
Carretera del Desert de les Palmes (Castellón)
Avenida del Valles, Terrassa (Barcelona)
Parc Vallparadis, Terrassa (Barcelona)



== Planes para el futuro ==

Por supuesto, seguir corriendo todas las carreras populares que me queden cerca. Mi próxima carrera será el día 16 de Abril en mi querida ciudad natal. Participaré en la IV carrera a pié, costa de Azahar.

Aunque desde hace un par de años ronda por mi cabeza la palabra "Triatlon", me atrae mucho la idea de juntar la bicicleta, piscina y running en una sola prueba. Pronto espero poder comprar una buena bicicleta para entrenar la prueba en condiciones. También necesitaré una piscina para entrenar la natación. Aunque mi presupuesto de momento no está para muchas alegrías.

También me gustaría comprar un GPS para aventurarme mas a menudo por la montaña haciendo trekkings de muchos kilómetros y varios días. El Camino de Santiago empezando en los Pirineos encajaría muy bien en este apartado.

Esperemos que las lesiones nos respeten durante muchos años para seguir disfrutar de todos estos proyectos durante mucho tiempo... ¿Alguien se anima con alguno de ellos? :-)

sábado 5 de febrero de 2011

Contraseñas seguras y faciles de recordar

Es el momento de elegir una contraseña para un nuevo servicio online que estamos dando de alta. Dicha decisión, aunque todavía hay gente que no se lo plantea, es trascendental para proteger la privacidad de los datos confidenciales de carácter personal que vamos a proporcionar al proveedor de dicho servicio: cuentas bancarias, tarjetas de crédito. CV, ofertas de trabajo, y un largo sin fin de datos personales privados.

Finalizado el proceso de alta, la única barrera que protege a nuestros datos confidenciales de la curiosidad ajena es dicha contraseña. Por ello, dicha contraseña debería ser elegida con toda la cautela y el máximo recelo posible, puesto que todos conocemos las consecuencias de exponer información sensible y los peligros que eso conlleva.



Para elegir una contraseña segura, hay que tener en cuenta algunas recomendaciones de lo mas básicas:

- Debe ser fácil de recordar pero difícil de adivinar
- Es obligatorio usar un mínimo de 8 caracteres
- Debe combinar letras con dígitos numéricos
- No debe utilizarse la misma contraseña para acceder a distintos servicios online
- No deben utilizarse palabras que aparezcan en un diccionario

La gente acumula cuentas de usuario en distintos servicios online. Con el paso del tiempo tienden a olvidar las contraseñas elegidas. Para evitar ese olvido, muchos optan por elegir contraseñas fáciles de adivinar, basadas en su propio nombre, edad, fecha de nacimiento, dni, matricula de tu coche, profesión, comida favorita, el nombre de tu perro o de tu gato, etc. Y muchas veces esa misma contraseña fácil de recordar, se utiliza en todos y cada uno de los servicios online registrados. Podéis imaginaros la dimensión del problema.

En este post se propone un método para resolver este problema.

La solución propuesta se basa en dos inputs que combinados adecuadamente mediante un algoritmo que definiremos nosotros mismos, generan como output la contraseña segura.

    f_algoritmo_secreto(servicio_online, semilla) = contraseña


Como inputs tendremos el nombre identificativo del servicio online donde estamos registrando la cuenta, y una semilla secreta única para todas nuestras contraseñas. El algoritmo combina los dos inputs para obtener como output la contraseña segura.

Vamos a explicar todo esto con un ejemplo sencillo para que se entienda mejor. Sea f_algoritmo_secreto una función que concatena las cadenas semilla y servicio_online, aplicando la función de hash md5 sobre el resultado de su concatenación, y del md5 resultante extrae los 10 primeros caracteres como contraseña de salida. Sea "supersecreto" la cadena semilla. Veamos algunos ejemplos de aplicación con distintos servicios online:

    Portal gmail --> md5sum[ "gmailsupersecreto" ] = 6037becb2f
Portal facebook --> md5sum[ "facebooksupersecreto" ] = ca713f6ce3
Maquina amd64 --> md5sum[ "amd64supersecreto" ] = ea816a9399


Por tanto, el password para la cuenta de gmail sería "6037becb2f", para la cuenta de facebook sería "ca713f6ce3" y para la cuenta en la maquina amd64 sería "ea816a9399". Como veis se trata de passwords dificiles de memorizar incluso para aquellos que estuvieran mirando vuestro teclado mientras pulsais las teclas.

Aqui teneis un sencillo bash shell script que os resuelve el problema sin mayor complicación:

  #! /bin/bash

echo -ne "Online service: "
read READ

stty -echo
read -p "Supersecret seed: " SEED
echo -ne "\n"
stty echo

echo -ne "$READ$SEED" | md5sum | cut -b 1-10


El secreto del método reside tanto en el algoritmo_secreto como en la cadena semilla.

Aunque el algoritmo_secreto cayera en manos ajenas, el método continúa protegido por la semilla. Esta semilla deberíais interiorizarla como si fuera vuestro propio nombre, tendrían que torturaros para obtenerla (aunque ojito por donde viajais :-) Pero obviamente es mas fácil recordar esa semilla que todas y cada una de las distintas contraseñas de los distintos servicios online en los que tenemos alguna cuenta registrada.

Este método (y cualquier variante basada en el mismo principio) cumple todas y cada una de las recomendaciones básicas que se han enumerado al comienzo de este post para garantizar la elección de una contraseña segura.

Quede claro que se trata de una propuesta concreta para explicar el método con un ejemplo. No os recomiendo en absoluto que uséis este mismo método tal y como esta publicado. Así que ¡aya vosotros! que este mismo método ya lo conocen todos los lectores de este blog! ;) Aunque con pequeñas modificaciones debería ser sencillo adaptarlo a vuestras propias necesidades personales.

sábado 15 de enero de 2011

Cuestionario open source

Hoy me apetece plantearos una serie de preguntitas relacionadas con sistemas Linux para que mantengáis vuestras mentes en forma. Veamos quien es el primero en contestar todas las preguntas correctamente. Los recursos de los que dispongo para premiar al ganador son mas bien escasos, así que el ganador tendrá que conformarse con la satisfacción de ser el primero en lograrlo. ¡Que no es poco! Cualquier día os llaman desde alguna empresa internacional cañera planteando preguntas de este estilo y entonces, ..., ¡entonces tendréis vuestro merecido premio! :-)




Redes

¿Como contacta un cliente DHCP con el servidor DHCP para pedirle una IP cuando el cliente DHCP todavía no tiene ninguna dirección IP asignada?

¿Que comando se usa para cambiar el ESSID de un interfaz wifi? ¿Y para habilitar/deshabilitar el modo promiscuo del interfaz?

¿Que protocolo de red utiliza el mecanismo de ventana deslizante? ¿Podríais explicarme brevemente en qué consiste?

¿De cuantas direcciones de host efectivas dispones en una subred con una mascara de red con 27 bits habilitados a 1?

¿Cuantos enteros necesitas en una plataforma x86 para almacenar una dirección IPv4?


Sistema:

¿Cual es el uso de los runlevels en un sistema Linux?

¿Cual es la diferencia entre los ficheros fstab y mtab situados en el directorio /etc?

¿Para que se usa el comando modprobe y en qué se diferencia del comando insmod?

Dime el comando opuesto a 'cat'.

¿Cual es la diferencia entre los números "major" y "minor" de todos los ficheros dispositivo situados en /dev?. ¿Que llamada al sistema se usa para generar dichos ficheros dispositivo?


Desarrollo:

¿Cual es la llamada al sistema usada para crear un proceso? Explícame también el significado de los posibles valores de retorno de esta llamada.

¿Cual es el uso del modificador 'friend' en un método de C++?. Los métodos friend, deben ser, ¿public, protected, o private?

¿Cual es el significado del Set User ID SUID bit cuando se aplica sobre binarios? ¿Tiene alguna utilidad aplicado sobre directorios?

¿Para que se usa el comando built-in 'export' del bash shell script?

¿Que comando se usa para eliminar la información de debug de un binario compilado con gcc/g++?

sábado 20 de noviembre de 2010

Retos para desarrolladores

Entre crisis, abogados, hipotecas, y tareas del hogar (aunque éstas últimas no terminen nunca para mi frustración), últimamente he tenido poco tiempo libre para disfrutar de mi afición como programador, que aunque también sea mi profesión, no deja de ser un hobbie con el disfruto de mi tiempo libre.

"Busca un trabajo que te guste y no tendrás que trabajar un sólo día de tu vida". 
Cita sabia del filosofo chino Confucio.


Cansado ya de dedicar mi tiempo libre a resolver problemas de mi vida cotidiana que me divierten mas bien poco, me aportan mas bien nada, y me limitan mi capacidad de aprendizaje y mejora continua de mis aptitudes profesionales, hoy por fin encontré el día perfecto para pasar un buen rato con mi buen amigo 'Dellone' (así es como bauticé este verano a mi primer portátil Dell)

Era una tarde de Sábado gris, lluviosa y fría. Otro de esos días perfectos en los que no se me ocurría nada mejor que sentarte delante del portátil y disfrutar junto al calor de sus ventiladores resolviendo alguna de las muchas tareas que tenia pendientes en mi lista de TODOs personales.



La tarea elegida hoy fue resolver el reto para desarrolladores publicados en el portal The Greplin Programming Challenge. Conocí estos retos gracias a un compañero de trabajo, a quien desde aquí le agradezco la información porque he pasado una tarde muy entretenida. Gracias Dani! ;)

Sobre el nivel del reto, comentar que son tres problemas que exigen unos conocimientos en algorítmica de lo mas básicos. En todo caso, es el tercer reto el que exige un poquito de imaginación para dar con la solución. Pero poco mas. Todo aquel con experiencia 'picando código' debería poder resolverlos sin mayores problemas.

Las soluciones que publico han sido desarrolladas en C, que a mi es el lenguaje que más me gusta. Pero el lenguaje usado para resolverlos es indiferente, podéis usar el que mas os guste (o el que mas os disguste, hay mucho masoca suelto por ahí...)

El primer reto se introduce con esta explicación:
 The Greplin Programming Challenge

Level 1

----------------------------------------

Embedded in this block of text is the password for level 2.
The password is the longest substring that is the same in reverse.

As an example, if the input was "I like racecars that go fast"
the password would be "racecar".


La solución que propongo al primer reto es esta:

#include stdio.h
#include string.h

const char g_cad[] =
"Fourscoreandsevenyearsagoourfaathersbroughtforthonthiscontainentanewnationconceivedinz"
"LibertyanddedicatedtothepropositionthatallmenarecreatedequalNowweareengagedinagreahtci"
"vilwartestingwhetherthatnaptionoranynartionsoconceivedandsodedicatedcanlongendureWeare"
"qmetonagreatbattlefiemldoftzhatwarWehavecometodedicpateaportionofthatfieldasafinalrest"
"ingplaceforthosewhoheregavetheirlivesthatthatnationmightliveItisaltogetherfangandprope"
"rthatweshoulddothisButinalargersensewecannotdedicatewecannotconsecratewecannothallowth"
"isgroundThebravelmenlivinganddeadwhostruggledherehaveconsecrateditfaraboveourpoorponwe"
"rtoaddordetractTgheworldadswfilllittlenotlenorlongrememberwhatwesayherebutitcanneverfo"
"rgetwhattheydidhereItisforusthelivingrathertobededicatedheretotheulnfinishedworkwhicht"
"heywhofoughtherehavethusfarsonoblyadvancedItisratherforustobeherededicatedtothegreattd"
"afskremainingbeforeusthatfromthesehonoreddeadwetakeincreaseddevotiontothatcauseforwhic"
"htheygavethelastpfullmeasureofdevotionthatweherehighlyresolvethatthesedeadshallnothave"
"diedinvainthatthisnationunsderGodshallhaveanewbirthoffreedomandthatgovernmentofthepeop"
"lebythepeopleforthepeopleshallnotperishfromtheearth";

int is_str_palindrome(const char * init, const char * end)
{
while ((*init == *end) && (init <= end)) {
init++;
end--;
}

return (init >= end);
}

int main(void)
{
int l = strlen(g_cad);
int i, j, ibest, lbest;

ibest = lbest = 0;

for (j = l - 1; j > 0; j--) {
for (i = 0; i < j; i++) {
if (is_str_palindrome(g_cad+i, g_cad+j))
if (j-i > lbest) {
ibest = i;
lbest = j-i+1;
}
}
}

printf("Solution to challenge 1 is '%.*s'\n", lbest, g_cad+ibest);
}


El segundo reto se introduce con esta explicación:
 The Greplin Programming Challenge

Level 2

----------------------------------------

Congratulations. You have reached level 2.

To get the password for level 3, write code to find the first prime
fibonacci number larger than a given minimum. For example, the first
prime fibonacci number larger than 10 is 13.

When you are ready, go here or call this automated
number (415) 799-9454.

You will receive additional instructions at that time. For the second portion
of this task, note that for the number 12 we consider the sum of the prime divisors
to be 2 + 3 = 5. We do not include 2 twice even though it divides 12 twice.


La solución que propongo al segundo reto es esta:

#include stdio.h

unsigned long next_fibonacci()
{
static unsigned long a = 0;
static unsigned long b = 1;
unsigned long nf = a + b;

a = b;
b = nf;

return nf;
}

unsigned long next_prime()
{
static unsigned long prime = 0;
unsigned long tested = prime + 1;

while (1) {
if (is_prime(tested)) {
prime = tested;
return prime;
} else {
tested++;
}
}
}

int is_prime(unsigned long tested)
{
unsigned long divisor;

for (divisor = (tested / 2); divisor > 1; divisor--)
if ((tested % divisor) == 0)
return 0;

return 1;
}

int main(void)
{
unsigned long given_minimum = 227000;
unsigned long X;

while ((X = next_fibonacci()) < given_minimum)
;

while (!is_prime(X))
X = next_fibonacci();

X += 1;

int np = next_prime(); // 1

int challenge2 = 0;

while (X != 1) {
np = next_prime();

if ((X % np) == 0) {
while ((X % np) == 0)
X = X / np;
challenge2 += np;
}
}

printf("Solution to challenge 2 is %d\n", challenge2);
}


Y por ultimo, el tercer reto se introduce con esta explicación:
 The Greplin Programming Challenge

Level 3

----------------------------------------

Congratulations. You have reached the final level.

For the final task, you must find all subsets of an array
where the largest number is the sum of the remaining numbers.
For example, for an input of:

(1, 2, 3, 4, 6)

the subsets would be

1 + 2 = 3
1 + 3 = 4
2 + 4 = 6
1 + 2 + 3 = 6

Here is the list of numbers you should run your code on.
The password is the number of subsets. In the above case the
answer would be 4.


Y la solución que propongo al tercer reto, es esta:

#include stdio.h
#include math.h

/* Input param */
int g_set[] = { 3, 4, 9, 14, 15, 19, 28, 37, 47, 50, 54, 56, 59, 61, 70, 73, 78, 81, 92, 95, 97, 99 };

int g_setlen = sizeof(g_set) / sizeof(int);

int is_membership(int v)
{
int i;

for (i = 0; i < g_setlen; i++)
if (g_set[i] == v) {
return 1;
}

return 0;
}

int is_onebit(int v)
{
int i;
for (i = 0; i < g_setlen; i++)
if (v == (pow(2, i)))
return 1;
return 0;
}

int main(void)
{
int mask;
int m;
int aux;
int pos;
unsigned int N = pow(2, g_setlen);
int challenge3 = 0;

for (mask = 1; mask < N; mask++)
{
if (is_onebit(mask))
continue;

aux = mask;
pos = 0;
m = 0;
while (aux != 0) {
if (aux & 0x01)
m += g_set[pos];
aux = aux >> 1;
pos++;
}

if (is_membership(m))
challenge3++;
}

printf("Solution to challenge 3 is %d\n", challenge3);
}


Todos los desarrolladores que estáis leyendo esto conocéis la sensación de satisfacción inmensa que produce dar con la solución al problema y "avanzar al siguiente nivel". Pienso que esa es la droga que nos metemos los que trabajamos en esto y nos mantiene tan enganchados a esta entretenida profesión (si, somos unos jonkies!! :) Y este es el premio que obtendréis al terminar el reto:
 The Greplin Programming Challenge

The End

----------------------------------------

Congratulations. You completed the challenge. Your completion code is 118-170-234969.

We'd love to talk to you - send your completion code, the code you wrote
during the challenge, and your resume to

USER at SUBDOMAIN dot DOMAIN

Even if you're not looking for a job, we'd love to hear what you thought
about the challenge.


La dirección de correo la protejo para evitar spam innecesario a los organizadores. Eso si, si alguno de los lectores esta en paro, y tiene en mente trabajar en Estados Unidos, igual es ésta vuestra oportunidad. !Al menos intentadlo! :)

Para los que sigáis con el gusanillo de resolver mas problemas de este estilo, os dejo aqui otro enlace a un reto para desarrolladores bastante famosillo, The Euler Project, con mas de 300 problemas que resolver, un gran número de participantes registrados repartidos por los cinco continentes, y un ranking en el que estareis compitiendo contra todos ellos. Si alguien se aburre con este reto, que hable conmigo que está contratado! :P



Como veis en la imagen adjunta, solo he podido terminar los 7 primeros. La falta de tiempo libre me obliga a mantener abandonadas algunas tareas que me gustaría continuar a medida que recupere el control de mi tiempo libre. Animo a todos los lectores que compartan mi afición a que lo intenten, pregunten dudas, compartan las soluciones, y así poder comentarlas y buscar entre todos la solución óptima en cuanto a coste computacional, etc. Espero que lo disfrutéis. Y ya sobran mas explicaciones. ¡A programar se ha dicho!

sábado 23 de octubre de 2010

Hiputecado

Compré un piso en Abril de 2007 en plena burbuja inmobiliaria por un precio bastante razonable para lo que se movía en aquellos momentos, ante la alocada escalada de precios que me hizo creer que era de las últimas oportunidades que tendría en mi vida para tener algo mio en propiedad. Y es que los precios de venta ya rozaban lo prohibitivo...



5 meses después de firmar el contrato de arras para comprar un piso sobre plano, la burbuja me estalló en las manos. A mi, como a muchos otros amigos, conocidos y familiares. Mucha gente de mi edad, rondando los 30 años. Jóvenes ilusionados con tener su propia vivienda, habían puesto todos sus ahorros en manos de unos promotores que poco tiempo después se declararon insolventes, en quiebra. El desconocimiento del sector, de los riesgos de una operación tan arriesgada, de la legislación que regula este mercado, la confianza de que "todo iba bien" y que "nada malo podía pasar", hizo que mucha gente entregara cantidades de dinero a cuenta sin ser avaladas por el banco. Muchísima gente sigue hoy en día en los juzgados gastando su dinero en abogados para intentar recuperar parte de aquel dinero, muchos otros lo han perdido ya todo. Historias realmente lamentables.

Es de recordar que el Articulo 47 de la Constitución Española, dice textualmente:

    "Todos los españoles tienen derecho a disfrutar de una vivienda digna
y adecuada. Los poderes públicos promoverán las condiciones necesarias
y establecerán las normas pertinentes para hacer efectivo este derecho,
regulando la utilización del suelo de acuerdo con el interés general
para impedir la especulación"


Se trata de un derecho fundamental de todos los ciudadanos españoles. A estas alturas, ya no creo que haya ningún poder público de este país que se preocupe realmente por atender las verdaderas necesidades de los ciudadanos. Ellos siguen sonrientes, contando chistes delante de los suyos sobre las habilidades o las carencias de sus opositores. Es indignante, frustrante, vergonzoso y un largo sin fin de adjetivos que podrían seguir describiendo la situación política lamentable que vivimos en este país.

Gracias a todos ellos, muchos otros al igual que yo seremos la generación de los pringados de este país. Los pringados que pagaremos los excesos cometidos por algunos a los que hoy en día les importa un pimiento que estemos en crisis. Mientras ellos disfrutarán de lo ganado en tiempos de bonanza, otros lo estaremos pagando el resto de nuestras vidas. Y muy caro.

De los pocos que después de un largo calvario de abogados de mas de 4 años, hemos tenido la "suerte" (muy entre comillas) de que terminen la construcción de nuestra vivienda, debemos hacer frente ahora a la hipoteca, por un importe hoy por hoy muy por encima de su valor real de tasación en el mercado. A sabiendas de que los precios seguirán cayendo en los próximos meses y, probablemente, años. O eso o perder el 100% de las cantidades anticipadas. Pagar el resto de mi vida por un bien que no tiene la mitad de su valor. Viva las leyes de este país.

Para intentar reducir el coste de dicha vivienda al máximo, he tenido que aprender en muy pocos días muchos términos nuevos relacionados con el mundillo de los economistas: indices de referencias, hipotecas a tipo fijo o variable, diferenciales sobre el euribor, comisiones de apertura, amortización, cancelación, productos vinculados, suelos o techos de interés, y un largo etcétera. Y hacer números por mi cuenta para sacar mis propias conclusiones.

Mucha gente me dice... ¡es que hay que saber un poco de todo! No lo veo justo. Daría lo que fuera por ver a todos los economistas, abogados, jueces, etc. que manejan ordenadores para su trabajo a diario, se vieran en la obligación de aprender a manejarse con conceptos informáticos como ensambladores, juegos de instrucciones, compiladores, linkers, librerías, herencia, polimorfismo, estructuras de datos, clases, objetos, constructores, variables, punteros, estructuras, uniones, debuggers, ... stack overflow.

Como ingeniero tengo conocimientos matemáticos mas que suficientes para sacar a flote la triste realidad de los datos económicos que se ocultan detrás de las hipotecas. En lo que sigue intentaré explicaros como funciona esto de las hipotecas, como se realiza el cálculo de la cuota mensual y como funciona el tema de los intereses. Veremos también algunos datos que conviene tener en cuenta para ahorraros bastantes euros durante todo el pago de vuestra hipoteca.

Calculo de la cuota mensual

Veamos primero como se calcula la cuota que se paga cada mes de una hipoteca. Este dato se obtiene aplicando una formula que depende de estas 3 variables:

- Capital solicitad (€): es la cantidad de dinero que le pides al banco.
- Plazo de amortización (meses): es el tiempo que vas a tardar en devolverle el capital solicitado al banco
- Interes anual o TAE (%): es el interés aplicado cada año sobre el capital que le seguimos debiendo al banco (capital no amortizado).

Con estos tres datos tenemos todo lo necesario. Veamos un ejemplo práctico para entenderlo mejor. Pediremos al banco un crédito de 12.000€ a devolver en 2 años y a un tipo de interés TAE del 6% anual.

    Capital solicitado = C = 12000€
Plazo de amortización = n = 24 meses
TAE = 6%


A partir de estos 3 datos, se extrae el índice "i" de interés, como:

    TAE mensual = 6% / 12 meses = 0.5%
Indice del interés = i = TAE mensual / 100 = 0.5 / 100 = 0.005


A partir de las variables anteriores, calculamos la cuota mensual de una hipoteca aplicando esta ecuación:

    Cuota Mensual Hipoteca = C * i / [ 1 - (1 + i)**-n ]


donde 2**3 = 2*2*2 = 8 (es la operación "elevado a"). En nuestro caso concreto

    C = 12000€
i = 0.005
n = 24 meses


Sustituyendo las variables calculadas en la ecuación, y haciendo el cálculo, tenemos el resultado de la cuota mensual:

    Cuota Mensual = 12000 * 0.005 / [ 1 - (1 + 0.005)**(-24) ] = 531.85€ / mes


No fue fácil encontrar esta formula. Pero me hizo gracia leer en el sitio donde la encontré que muchos de los banqueros que gestionan este tipo de productos financieros ni siquiera saben de donde se obtiene esta cantidad. Será por las primas anuales que cobran, demostrando que hay nivel...

La siguiente tabla demuestra como se amortiza el capital pendiente a lo largo de los 24 meses del plazo de amortización

    Año Mes     Cuota       Interés     Amortización        Capital pendiente
=========================================================================
0 0 12.000,00 €
1 1 531,85 € 60,00 € 471,85 € 11.528,15 €
1 2 531,85 € 57,64 € 474,21 € 11.053,95 €
1 3 531,85 € 55,27 € 476,58 € 10.577,37 €
1 4 531,85 € 52,89 € 478,96 € 10.098,41 €
1 5 531,85 € 50,49 € 481,36 € 9.617,05 €
1 6 531,85 € 48,09 € 483,76 € 9.133,29 €
1 7 531,85 € 45,67 € 486,18 € 8.647,11 €
1 8 531,85 € 43,24 € 488,61 € 8.158,50 €
1 9 531,85 € 40,79 € 491,05 € 7.667,44 €
1 10 531,85 € 38,34 € 493,51 € 7.173,93 €
1 11 531,85 € 35,87 € 495,98 € 6.677,96 €
1 12 531,85 € 33,39 € 498,46 € 6.179,50 €
2 13 531,85 € 30,90 € 500,95 € 5.678,55 €
2 14 531,85 € 28,39 € 503,45 € 5.175,09 €
2 15 531,85 € 25,88 € 505,97 € 4.669,12 €
2 16 531,85 € 23,35 € 508,50 € 4.160,62 €
2 17 531,85 € 20,80 € 511,04 € 3.649,58 €
2 18 531,85 € 18,25 € 513,60 € 3.135,98 €
2 19 531,85 € 15,68 € 516,17 € 2.619,81 €
2 20 531,85 € 13,10 € 518,75 € 2.101,06 €
2 21 531,85 € 10,51 € 521,34 € 1.579,72 €
2 22 531,85 € 7,90 € 523,95 € 1.055,77 €
2 23 531,85 € 5,28 € 526,57 € 529,20 €
2 24 531,85 € 2,65 € 529,20 € 0,00 €

=====================================

IMPORTE TOTAL = 12764,33€
Intereses = 764,33€


Como vemos, a medida que se amortiza capital (se reduce la deuda contraída con el banco) se van reduciendo los intereses, puesto que los interese solo se aplican sobre el capital pendiente de ser amortizado.

Carencia de capital

Algunos bancos ofrecen unas hipotecas con un periodo de carencia inicial en el que el hipotecado pasa un tiempo (de 1 a 5 años) durante el cual solo paga intereses, sin amortizar capital. Para entender esto, vamos a aplicar una carencia de capital de 6 meses al ejemplo anterior. Por tanto, durante los 6 primeros meses pagaremos intereses pero no amortizaremos capital.


    Año Mes     Cuota       Interés     Amortización        Capital Pendiente
=========================================================================
0 0 12.000,00 €
1 1 60,00 € 60,00 € - € 12.000,00 €
1 2 60,00 € 60,00 € - € 12.000,00 €
1 3 60,00 € 60,00 € - € 12.000,00 €
1 4 60,00 € 60,00 € - € 12.000,00 €
1 5 60,00 € 60,00 € - € 12.000,00 €
1 6 60,00 € 60,00 € - € 12.000,00 €
1 7 698,78 € 60,00 € 638,78 € 11.361,22 €
1 8 698,78 € 56,81 € 641,97 € 10.719,24 €
1 9 698,78 € 53,60 € 645,18 € 10.074,06 €
1 10 698,78 € 50,37 € 648,41 € 9.425,65 €
1 11 698,78 € 47,13 € 651,65 € 8.774,00 €
1 12 698,78 € 43,87 € 654,91 € 8.119,09 €
2 13 698,78 € 40,60 € 658,19 € 7.460,90 €
2 14 698,78 € 37,30 € 661,48 € 6.799,42 €
2 15 698,78 € 34,00 € 664,78 € 6.134,64 €
2 16 698,78 € 30,67 € 668,11 € 5.466,53 €
2 17 698,78 € 27,33 € 671,45 € 4.795,09 €
2 18 698,78 € 23,98 € 674,81 € 4.120,28 €
2 19 698,78 € 20,60 € 678,18 € 3.442,10 €
2 20 698,78 € 17,21 € 681,57 € 2.760,53 €
2 21 698,78 € 13,80 € 684,98 € 2.075,55 €
2 22 698,78 € 10,38 € 688,40 € 1.387,15 €
2 23 698,78 € 6,94 € 691,85 € 695,30 €
2 24 698,78 € 3,48 € 695,30 € 0,00 €

======================

IMPORTE TOTAL = 12938,05€
Intereses = 938,05€


Indudablemente puede ser una buena idea contar con un periodo de carencia cuando por distintas razones no podemos hacer frente a las primeras mensualidades de nuestra hipoteca. No obstante, conviene hacer hincapié en los aspectos negativos. Una vez transcurrido el periodo de carencia, vemos como las cuotas aumentan de manera considerable, puesto que tenemos que devolver el mismo capital prestado (no hemos amortizado todavía capital) en menos tiempo. Otro inconveniente es el aumento del importe total por intereses, ya que durante el periodo de carencia, estamos pagando el máximo de intereses al banco, al no estar amortizando capital.

Cosas obvias que conviene recordar

Para finalizar, quisiera mostraros algunos datos extras que os deberían resultar muy útiles para entender como se puede ahorrar dinero al pagar una hipoteca.

Primero, anticipar las amortizaciones parciales de capital para reducir el coste total de la operación. Supongamos una hipoteca de 100.000€ a un 3% TAE a devolver durante 10 años. Vamos a amortizar 20.000€ en distintos momentos desde que se solicita el préstamo:

    Año de amortización parcial     Interes total
==================================================
1 12725€
2 13053€
3 13379€
4 13701€
5 14020€
6 14339€
7 14649€
8 14960€
9 15267€
nunca 15872€


De la tabla anterior se deduce que cuanto antes amorticemos capital, mas barata nos resultará la hipoteca, puesto que nos beneficiaremos durante mas tiempo de la reducción de capital pendiente de devolución, y por tanto de la reducción de intereses pagados por ese capital pendiente que le debemos al banco.

Obviamente, para poder amortizar hay que tener una alta capacidad de ahorro. Dicha capacidad de ahorro queda mermada por las distintas vinculaciones que nos exigen las entidades bancarias para poder ofrecer un buen diferencial con el índice de referencia (generalmente el euribor): planes de pensiones, fondos de inversión, seguros de hogar y de vida, etc. No soy un experto en la materia, pero según estos cálculos, yo aconsejaría huir de dichas vinculaciones como de la peste.

Segundo, devolver al banco lo antes posible el dinero que nos ha prestado, para lo cual interesa que el plazo de amortización (n) sea lo menor posible. La siguiente tabla muestra el interés total pagado por una cantidad de 100.000€ solicitada al banco a un interés TAE dado, y devuelto durante los años indicados.

    TAE(%)          (10 años)       (20 años)       (30 años)       (40 años)
===========================================================================
0.0% 0€ 0€ 0€ 0€
1.0% 5124€ 10374€ 15790€ 21365€
2.0% 10416€ 21412€ 33063€ 45342€
3.0% 15852€ 33103€ 51777€ 71807€
4.0% 21494€ 45435€ 71869€ 100571€
5.0% 27278€ 58389€ 93255€ 131398€
6.0% 33224€ 71943€ 115838€ 164026€


En la tabla anterior se observa como, a un misma tasa de interés anual TAE, cuanto menos tiempo tardemos en devolver el dinero prestado, menos nos costará el total de la operación. Dicho de otro modo, cuanto mas años tardamos en devolver el dinero, mas pagamos. Que nadie se equivoque. No se trata de picos despreciables de pocos euros. Fijaros en la barbaridad de intereses que se le pagan al banco por 100.000€ a un 6% durante 40 años: 164026€, ¡¡solo en concepto de intereses!!

Conclusiones

La conclusión de todo esto: si os lo podéis permitir, no os hipotequéis. Cualquier otra opción es mejor: plantearos la opción de vivir de alquiler. No se está nada mal y disfrutareis mucho mas de vuestras vidas. Esperar que os toque alguna herencia o incluso comprar lotería y a ver si hay suerte.

Mientras tanto, ahorrar todo el dinero que podáis, y si algún día decidís comprar, pagad el piso en metálico. Esa es la única opción que mínimamente garantiza el cumplimiento del Articulo 47 de la Constitución Española. Lo demás, es un error imperdonable. Un robo de guante blanco al amparo de la Ley.

sábado 25 de septiembre de 2010

Documentación técnica en el idioma de Cervantes

Los documentos técnicos cumplen el propósito de informar de lo que se ha hecho en una actividad determinada en términos técnicos y de forma que sea legible y comprensible dentro de su contexto. En la documentación técnica existen unos criterios determinados para su elaboración. En este articulo intentaremos mencionar los principales a tener en cuenta.


Lenguaje

Un documento técnico se escribe en lenguaje técnico. El lenguaje técnico evita la utilización de palabras con significados ambiguos. El lenguaje técnico es preciso en los significados, abunda en la aplicación de los términos técnicos propios del dominio sobre el que se habla, y estructura el contenido a base de frases cortas y directas. Esto último significa que el lenguaje técnico no utiliza recursos como tropos, metáforas ni otros elementos propios del lenguaje literario.

El documento técnico debe mantener la corrección técnica del contenido y de la estructura con respecto a los objetivos y naturaleza del proyecto. La utilización de términos fuera del dominio técnico, de metodologías o técnicas no contrastadas, de resultados incoherentes, de afirmaciones o conclusiones no fundamentadas, etc., es síntoma inequívoco de incorrección técnica.

Gramática

Las frases deben aplicar construcciones gramaticales regulares: en primer lugar, el sintagma nominal (sujeto y complementos). En segundo lugar, el sintagma verbal (verbo y complementos). También se suelen utilizar frases relativas que extienden el significado (-frase principal- que -frase relativa-).

Sujeto

El lenguaje técnico utiliza el sujeto impersonal o reflexivo, tal y como se está aplicando en el presente documento:
    "se puede ver"
"se describe"

A veces, también se usa la primera persona del plural cuando el autor pretende implicarse con el lector en una actividad determinada que se está realizando en el momento presente
    "vamos a poner el dispositivo en marcha"
"veamos el resultado"

Debemos huir de la aplicación de la primera persona del singular
    "yo incluyo el informe"
"yo conecto el módulo"

Cuando se quiere enfatizar o recalcar información relativa al autor, se puede utilizar términos estereotipados como
    "el autor"
"el que suscribe"

Y cuando se quiere mencionar la participación activa del lector, usaremos
    "el usuario"
"el lector"

Tiempos verbales

Hay que ser cuidadoso en el uso de los tiempos verbales de las frases y párrafos. No es correcto mezclar pretéritos, presentes y futuros en un mismo documento o sección del documento. En un documento o parte del mismo donde se describe una actividad o un conjunto de actividades ya realizadas y concluidas, se suele aplicar el pretérito perfecto:
    "se ha procedido al cálculo del promedio"
"se han establecido los requisitos fundamentales"

A veces, también se puede combinar con el pretérito imperfecto cuando se refiere a acciones puntuales
    "el programa dio un error"
"saltó la alarma en el momento en que"

Cuando se describe un procedimiento a realizar, normalmente se utiliza el presente de indicativo
    "se abre el menú de edición"
"se selecciona la opción"

Cuando se describe el contenido que se incluye a continuación en una sección, subsección o apartado del documento, se puede utilizar el futuro imperfecto así,
    "se mostrará el resultado del proyecto"
"se va a mostrar el resultado del proyecto"

Finalmente, para indicar acciones que el lector debe realizar, se aplica el imperativo
    "véase la Figura"

o las siguientes construcciones
    "hay que"
"se debe"

Narración

La narración o descripción debe ser fluida y fácil de leer, cuidando especialmente la corrección ortográfica y terminológica. Deben evitarse las frases rebuscadas, el uso del lenguaje coloquial, o la inserción no justificada de citas, tablas, figuras, etc. que no aporten nada al texto. El texto debe componerse a base de frases cortas separadas por puntos y seguidos. Su extensión debe adecuarse a los objetivos establecidos al comienzo del documento. Todos los elementos técnicos que deban ser citados o presentados exhaustivamente se deben poner en anexos al cuerpo del documento. Incluso se puede incluir una relación de abreviaturas, términos comunes o un glosario de términos técnicos para evitar confusiones semánticas.

Inserciones de figuras y tablas

Debe adecuarse la cantidad de tablas y figuras al contenido del documento, evitando incluir demasiadas tablas y figuras que no aporten casi nada al texto. Es mejor alternar descripciones textuales con tablas y figuras. Salvo necesidades concretas, no es necesario explicar profusamente una figura o una tabla con texto suplementario.

La inserción de referencias a figuras y tablas puede hacerse de dos formas distintas: conexa e inconexa. La forma de inserción inconexa consiste en utilizar la construcción
    "(Véase la Figura 27)"

como una frase independiente entre paréntesis. La forma de inserción conexa consiste en utilizar un párrafo introductorio que establece una relación con el contenido y/o descripción de la figura o tabla:
    "En la Figura 27 se puede apreciar que...",
"existe un indicador, tal como se muestra en la Figura 27..."

Por otra parte, los términos "Figura" y "Tabla" deben aparecer en el texto con la inicial en mayúscula.

Bibliografía y referencias

En muchos documentos técnicos habitualmente se incluye información que proviene de otro u otros documentos distintos. Es costumbre y por supuesto, ético, citar las fuentes externas que proporcionan dicha información.

Internet provee de algunas herramientas como esta que permiten descubrir si el contenido de un documento ha sido plagiado. Por tanto, debemos referenciar a nuestras fuentes para evitar incurrir en el delito de plagio.

Respecto a la bibliografía, en un documento técnico hay que distinguir por un lado la inserción de las referencias a las fuentes, y por otro lado, la relación detallada de dichas fuentes.

Inserción de las referencias a las fuentes

La inserción de referencias a una fuente de información externa, sea libro, articulo de investigación u otro tipo de obra, se hace mediante paréntesis siguiendo estas normas:

Cuando la referencia tiene un solo autor, se incluye el primer apellido de éste y el año de publicación con todas las cifras:
    (Tanembaum, 2001)

Cuando la referencia tiene más de un autor, la estructura es la misma salvo que, en lugar de poner todos los apellidos, se añade al apellido del primer autor la terminación "et al.":
    (Harmelen et al., 2004)

Relación de referencias

La relación de referencias se hace en un capitulo o sección independiente del documento. Se recopilan todos los datos relativos a cada una de las fuentes, ordenadas alfabéticamente de menor a mayor por el apellido del primer autor.

El formato con el que deben citarse las referencias bibliográficas depende de si la fuente es un libro, un capitulo de un libro, un articulo de revista, una obra no publicada, una dirección web, etc.. Se muestran algunos ejemplos a nivel orientativo:

Referencia a un libro:
    [Alonso, 2009]: Alonso J.A. Redes privadas virtuales. 1ª ed. Ra-ma,
Madrid, 2009.

Referencia a un artículo de investigación:
    [Siebes, 2005]: Siebes R. pNear: combining content clustering and
distributed hash tables. Vrije Universiteit Amsterdam. The netherland,
2005.

Referencia a una URL:
    [Castell, 2010]: Castell A.I. Documentación
técnica en el idioma de Cervantes.
http://aicastell.blogspot.com/2010/09/documentacion-tecnica-en-el-idioma-de.html.
Acceso el 25/09/2010.

Estructura del documento

El documento se divide en secciones, subsecciones y apartados. Salvo en contadas excepciones, no se recomienda llegar a un mayor nivel de división. En todos ellos, la unidad de redacción y de estilo es el párrafo, compuesto por un conjunto de frases. Al párrafo se le aplican una serie de características de formato y aspecto como son la separación de párrafos, interlineado, justificación entre margenes, tipo y tamaño de letra, etc.

De forma muy genérica, podemos organizar la estructura de un documento técnico con los siguientes apartados:
    Portada
Información visible sobre el titulo del documento y nombre del autor.

Resumen
Objetivos, descripción, resultados y conclusiones del trabajo resumidos
en no mas de 500 y no menos de 300 palabras.

Palabras clave
5 términos alusivos al contenido y propósitos del documento para poder
aplicar una indexación del mismo.

Indice
Relación de secciones y subsecciones, sin llegar a los apartados.

Introducción
Objetivos del documento, descripción del contexto general, planteamiento
del problema, descripción resumida del contenido del resto del documento.

Descripción
Descripción detallada de todo el trabajo realizado.

Resultados
Descripción de los resultados obtenidos en el trabajo realizado.

Conclusiones
Redacción de las conclusiones obtenidas, interpretación de los
resultados, de las afirmaciones fundamentadas y de las posibles
ampliaciones en sucesivos trabajos.

Bibliografía
Relación de referencias utilizadas durante la redacción del documento

Anexos
Inclusión de anexos con información complementaria sobre la que se
aporta en el cuerpo del documento. Esta sección es opcional.

Indice de tablas
Relación de las tablas contenidas en el documento.

Indice de figuras
Relación de las figuras contenidas en el documento.

Terminología
Relación de términos y abreviaciones utilizados en el documento con una
breve explicación de su significado para evitar confusiones al lector.

Herramientas

Por último, en la elaboración de toda la documentación se debe contar por supuesto con el apoyo de herramientas informáticas del estilo de Open Office o LaTeX. La persona encargada de llevar a cabo la documentación técnica debe tener los conocimientos suficientes de estos programas para obtener el debido provecho.

Seguidores