Archivo

Archivo para Julio, 2010

Extrayendo datos de direcciones web (C++ sin cURL)

Jueves, 29 de Julio de 2010 Gaspar Fernández Sin comentarios

url

En ocasiones, estamos inmersos en un proyecto que requiere conexión con un servidor.

Soy consciente de que existen muchas librerías que nos garantizan el acceso, y tienen muchas opciones aunque, a veces, no necesitamos tanto, sólo un simple acceso y un intercambio sencillo de información; del mismo modo, no nos apetece engordar demasiado nuestro ejecutable, o hacer que nuestro programa dependa de alguna librería externa.

Con esa intención, hice esta clase para C++ y que utilicé para uno de mis pequeños proyectos
hace unos años. Tengo que advertir que es una clase muy simple, y por eso también es válida para los que se quieran iniciar en programación de sockets.

Se puede descargar mysocktar (3.7Kb)

Para compilar el ejemplo:

$ g++ -c MySock.cpp
$ g++ -o ej_mysock ej_mysock.cpp MySock.o

Aún quedan cosas por hacer, sin perder el objetivo de una clase ligera, muy ligera:

  • Hacer documentación compatible con Doxygen
  • Mejor soporte para cabeceras HTML
  • Extracción de tags HTML
  • Soporte para contraseñas

Foto: Diego_3336 (Flickr)

Configuración de IMAP para GMAIL

Martes, 27 de Julio de 2010 Gaspar Fernández Sin comentarios

Tal vez sea un tema un poco antiguo, aunque hasta hace dos días no tuve que configurar ninguna cuenta de gmail en un cliente de correo (yo uso la de mi dominio) y al principio fue algo desconcertante, ya que siempre recibía el mismo problema: web login required (Failure) Aunque siguiendo estos pasos no tiene pérdida:

  1. Entrar en el correo vía web
  2. Ir a Configuración
  3. Ir a Reenvío y correo POP/IMAP
  4. Activar IMAP
  5. Importante: Ir a https://www.google.com/accounts/DisplayUnlockCaptcha
    , escribir e-mail, password y el texto que se ve en pantalla. Si eres usuario de Google Apps con tu dominio propio ir a: https://www.google.com/a/tudominio.com/UnlockCaptcha

Bueno, sí, hay que configurar el cliente de correo, y por ejemplo Mozilla Thunderbird en su versión 3, configura automáticamente la cuenta, sólo sabiendo que tu correo es de gmail.

Más info:
Fix Gmail IMAP Invalid Credentials or Web Login Requires (Failure) Error - My Digital Life
GMail Help

GPGPU: Exprimiendo el potencial de tu GPU para propósito general (I)

Domingo, 25 de Julio de 2010 Gaspar Fernández Sin comentarios

Hace unas semanas estuve en el Curso Avanzado de GPU impartido por el Dr. Manuel Ujaldón en la Universidad de Málaga; y me parece interesante compartir algunas conclusiones y un poco de investigación sobre el tema con todos ustedes.

Una arquitectura diferente

Disponemos de un chip con gran capacidad de procesamiento, pero a su estilo. Aunque originalmente está diseñado para su uso en juegos, recientemente (no tan recientemente porque el primer uso de GPU (Graphics Processing Unit, o Unidad de Procesamiento Gráfico) para propósito general fue en el 1997, lo que sí es más reciente es la implicación de empresas en este tipo de sistemas) muchas personas están concienciadas en aprovechar sus capacidades, y es muy interesante ya que con poco dinero podemos compararnos en capacidad de procesamiento a algunos superordenadores, y es que en ciertas tareas de cálculo muy pesado que en procesadores CPU actuales tardan varios días, con procesamiento GPU y con un coste mucho menor podemos completarlas en pocos minutos.

Ya podríamos pensar que es el momento de prescindir de la CPU, pero ese momento aún no ha llegado, ya que la GPU puede ser muy buena en ciertas tareas relacionadas con el paralelismo, pero la CPU es buena con las sentencias de control y los saltos en el código.

Paralelismo en GPU

Las GPU actuales pueden tener 128, 256 ó 512 núcleos (frente a los 4 ó 6 núcleos de los actuales procesadores más avanzados). Es decir, podemos tener 512 hilos corriendo concurrentemente en GPU. Si estamos acostumbrados a utilizar pthreads, vemos cómo tenemos que programar el hilo y crearlos, y si tenemos 512 núcleos deberíamos crear los 512 hilos; el problema y la solución vienen, en la programación GPU, en que todos los núcleos ejecutarán el mismo código, y cada hilo tendrá una serie de identificadores que nos indicarán qué procesador está funcionando. Por tanto podemos lanzar 512 tareas simultáneas y cada una será lanzada por un núcleo diferente. Si, por ejemplo queremos sumar un vector de 512 elementos con otro, en CPU, realizamos una operación cada vez (hasta 512 operaciones), en GPU lanzaremos las 512 a la vez, y terminarán en el tiempo de una operación (más o menos y a grosso modo)

Velocidad de acceso

Las tarjetas gráficas, por lo general, tienen una memorial RAM, unas cuántas generaciones por delante (mientras en CPU vamos por DDR3, las gráficas ya usan DDR5). La principal razón es que esta memoria está soldada en la plata y precisamente, muy cerca de la GPU, y además, el controlador de memoria está integrado en GPU, lo que facilita las transacciones. Por esto y mucho más, una lectura o escritura en la memoria de la tarjeta gráfica consumirá pocos ciclos en GPU, mientras que los accesos a memoria en CPU consumen muchos ciclos de reloj.
Con esto, tenemos una lectura/escritura en memoria mucho más rápida, y además, tenemos una memoria compartida, mucho más pequeña (de varios Kilobytes) que es mucho más rápida, y que nos permitirá una interacción más rápida. Es algo así como la caché de la CPU, pero en este caso es una memoria que sí podemos controlar (leer y escribir en esa memoria lo que queremos y cuando queremos, mientras que la caché de la CPU es automática).

Metodología de programación

El código que podemos utilizar se ejecuta en CPU, por tanto tenemos que programar la tarea que queremos que realice la GPU aparte (en una función, por ejemplo), ese será nuestro kernel. Justo antes de ejecutar nuestro kernel en GPU, debemos copiar los datos necesarios desde la RAM de nuestro sistema (host) a la memoria de nuestro sistema gráfico (device), tras ello ejecutar el kernel, y luego volver a copiar los datos obtenidos desde el device al host.
Sólo podemos ejecutar un kernel a la vez; éste se ejecutará en todos los núcleos a la vez, y es nuestro trabajo hacer que merezca la pena, si dejaos núcleos sin usar, es potencia que no estamos aprovechando.
Por otra parte, tenemos que conseguir que la realización de las tareas en GPU merezca la pena, ya que:

T_copia_H2D + Procesamiento GPU + T_copia_D2H < Procesamiento CPU

Es decir, el tiempo que tardamos en copiar los datos, primero desde el host al device y luego desde el device al host, más el tiempo que tarde el procesamiento en GPU tiene que ser menor que el tiempo que tarde el procesamiento en CPU, si no, todo esto no merecería la pena.

Dada la naturaleza de los kernels, y que todos los procesadores tienen que ir sincronizados, ejecutando la tarea encomendada, lo óptimo es que estos sean lo más pequeños posible y que tengan el menor número de decisiones posible (un if … else, implica que si la condición se cumple en un conjunto de núcleos, al ir todos los procesadores a la par, mientras unos núcleos procesan, otros pierden tiempo).

¿Cómo empezamos?

Aunque tenemos varias posibilidades, siempre podemos programar en ensamblador, específico a cada modelo de Chip, pero tal y como ocurre en CPU, van surgiendo lenguajes y sistemas que nos permiten generalizar nuestro código y poder ejecutarlo en una amplia gama de Chips (sí, se pierde un poco de rendimiento, pero perderíamos mucho tiempo haciéndolo así, por tanto es un coste que podemos permitirnos). Actualmente hay dos sistemas que podemos utilizar: CUDA (sólo para tarjetas nVidia, a partir de la serie 8) y OpenCL desarrollado por Apple y propuesto al grupo Khronos para ser un estándar de programación GPU libre del control de una empresa y compatible con una amplia gama de chips gráficos y que tanto nVidia, como ATI, y otros muchos fabricantes de chips gráficos.

Lectura recomendada

Giz Explains: GPGPU Computing
Wikipedia: Unidad de Procesamiento Gráfico

Keepnote : Organización de notas personales

Viernes, 23 de Julio de 2010 Gaspar Fernández Sin comentarios

screenshot-17-07-2010-140744Hace unos días que estoy probando Keepnote, y me está convenciendo. Es un gestor de notas personales multiplataforma (Linux, Mac, Windows), escrito en Python.
Hasta ahora estaba trabajando con Kjots (sobre KDE3); aunque este tiene bastantes opciones como la organización de Libros, búsquedas en todas las páginas de un libro, copia de seguridad, permite adjuntar archivos y capturas de pantalla, así como insertar estilos a las notas.
Por otra parte, nos permite organizar los libros en pestañas y tiene una papelera donde insertamos los elementos eliminados y además… extensiones (aunque no hay muchas todavía, pero el sistema lo permite, esperemos que en poco tiempo haya más).

Si estás buscando un software para gestionar tus notas, prueba Keepnote.

Más info: KeepNote : Note Taking and Organization

Categories: General Tags: , ,

Mi tweet 1024

Miércoles, 21 de Julio de 2010 Gaspar Fernández Sin comentarios

¡ Hace unas horas publiqué mi tweet 1024 ! Aprovecho este momento para poner mi dirección de Twitter por aquí: blakeyed. Quise poner alguna frase de alguien especial, relacionado con el mundo de la informática, y escogí una frase de Alan Turing:

Sólo podemos ver poco del futuro, pero lo suficiente para darnos cuenta de que hay mucho que hacer.

Aunque seguro que ha sido pronunciada por muchas personalidades a lo largo de la historia.

Hacer que konqueror conecte por FTP con los datos de .netrc ; Usar nombres de usuario que contienen arrobas

Martes, 20 de Julio de 2010 Gaspar Fernández Sin comentarios

Si usamos frecuentemente un archivo .netrc para almacenar nombres de usuario y contraseñas para servidores FTP, tal vez queramos utilizar esas mismas contraseñas para Konqueror sin necesidad de volver a escribirlas, ni almacenarlas en Kwallet (ya están en un sitio, ¿para qué meterlas en más lugares?). O tal vez se nos presente el siguiente problema, tenemos que conectar con un servidor FTP que permite conexiones anónimas, y al mismo tiempo el nombre de usuario (o la contraseña) que tenemos contiene el carácter arroba (@), tendríamos que meterlo en la barra de direcciones y al menos en KDE3.5.10 no nos deja hacerlo (no lo he probado en kde4), y la única forma rápida que se me ocurrió fue a través de .netrc.

Bien, si vamos a crear un archivo .netrc de primeras, leer esto, es un post de un proyecto que utilizaba .netrc para conectar donde se explica qué tiene que contener el archivo.

Luego editamos el archivo $HOME/.kde/share/config/kio_ftprc (si no existe lo creamos), por ejemplo con nano:

$ nano ~/.kde/share/config/kio_ftprc

e introducimos la siguiente línea:

EnableAutoLogin=true

Lo más fácil ahora es reiniciar KDE, pero yo opté por ejecutar lo siguiente:

$ dcopserver_shutdown
$ dcopserver

Como véis estoy utilizando dcop, esta solución es para KDE3, aunque supongo que para KDE4 habrá alguna solución sin usar dbus. Por otra parte, en mi sistema no uso KDE como gestor de ventanas, sólo utilizo algunas aplicaciones de KDE, por lo que no garantizo que se reinicie el gestor de ventanas.

Con esta solución, desde Konqueror pude abrir un FTP cuyo nombre de usuario contenía una arroba

Sustituyendo texto con expresiones regulares en EMACS

Domingo, 18 de Julio de 2010 Gaspar Fernández Sin comentarios

regular_expression

Una de las herramientas más utilizadas (por mí al menos) es la de reemplazar texto. En EMACS la podemos encontrar con:

M-x replace-string

Con esta orden podemos cambiar un texto por otro dentro de un buffer o una selección. Hasta aquí bien. Pero alguna vez nos podemos encontrar con un texto que debemos reemplazar por otro, y aunque no es exactamente igual en todos los reemplazos que tenemos que hacer sigue una cierta lógica.

Imaginemos que tenemos este código en PHP (Gracias Antonio):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
switch ($pregunta) {
    case 0: $preg="<br><br>¿Qué significa PHP?<br>";
            $resp="<a href=".$_SERVER['PHP_SELF']."?respuesta=1>a. Power H Processor</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=2>b. PHP: Hypertext Preprocessor</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=3>c. Para Hacer Poco</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=4>d. PHP: Harvard Preprocessor</a><br>";
            break;

    case 1: $preg="<br><br>¿Dónde se ejecuta PHP?<br>";
            $resp="<a href=".$_SERVER['PHP_SELF']."?respuesta=1>a. En el Cliente</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=2>b. En algún lugar de la Mancha...</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=3>c. En el Servidor</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=4>d. Ninguna de las anteriores</a><br>";
            break;

    case 2: $preg="<br><br>¿Cuál de las siguientes variables NO existe como predefinida en PHP?<br>";
            $resp="<a href=".$_SERVER['PHP_SELF']."?respuesta=1>a. PTTS_BOOK</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=2>b. PHPSESSID</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=3>c. REQUEST_METHOD</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=4>d. REMOTE_ADDR</a><br>";
            break;

    case 3: $preg="<br><br>¿Quién creó PHP?<br>";
            $resp="<a href=".$_SERVER['PHP_SELF']."?respuesta=1>a. Rasmus Lerdorf</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=2>b. Obi One Kenobi</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=3>c. Bill Gates</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=4>d. Andrew S. Tanenbaum</a><br>";
            break;

    case 4: $preg="<br><br>¿Con qué <i>marca</i> habrá un salto de línea en el código fuente?<br>";
            $resp="<a href=".$_SERVER['PHP_SELF']."?respuesta=1>a. \\t</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=2>b. \\n</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=3>c. &lt;br&gt;</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=4>d. \\g</a><br>";
            break;

    case 5: $preg="<br><br>¿Cuál de las siguientes funciones NO se puede acceder al servidor de datos MySQL?<br>";
            $resp="<a href=".$_SERVER['PHP_SELF']."?respuesta=1>a. mysql_query</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=2>b. mysql_connect</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=3>c. mssql_connect</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=4>d. mysql_pconnect</a><br>";
            break;

    case 6: $preg="<br><br>¿Cuál es la frase correcta?<br>";
            $resp="<a href=".$_SERVER['PHP_SELF']."?respuesta=1>a. setcookie() puede ser llamada desde cualquier parte del documento HTML</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=2>b. Las cookies sólo se pueden mandar antes de mandar cualquier otra cabecera</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=3>c. Las cookies no son parte de la cabecera HTTP</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=4>d. El perro de San Roque no tiene rabo, porque el Chiquito se lo ha robado</a><br>";
            break;

    case 7: $preg="<br><br>¿La función ftp_get?<br>";
            $resp="<a href=".$_SERVER['PHP_SELF']."?respuesta=1>a. Sube un fichero al servidor FTP</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=2>b. Establece una conexión FTP</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=3>c. Descarga un fichero del servidor FTP</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=4>d. Devuelve el nombre del directorio actual</a><br>";
            break;
}

Y queremos sustituirlo por este otro:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
addPregunta($pregresp, "¿Qué significa PHP?", "a. Power H Processor", "b. PHP: Hypertext Preprocessor", "c. Para Hacer Poco", "d. PHP: Harvard Preprocessor");

    addPregunta($pregresp, "¿Dónde se ejecuta PHP?", "a. En el Cliente", "b. En algún lugar de la Mancha...", "c. En el Servidor", "d. Ninguna de las anteriores");

    addPregunta($pregresp, "¿Cuál de las siguientes variables NO existe como predefinida en PHP?", "a. PTTS_BOOK", "b. PHPSESSID", "c. REQUEST_METHOD", "d. REMOTE_ADDR");

    addPregunta($pregresp, "¿Quién creó PHP?", "a. Rasmus Lerdorf", "b. Obi One Kenobi", "c. Bill Gates", "d. Andrew S. Tanenbaum");

    addPregunta($pregresp, "¿Con qué <i>marca</i> habrá un salto de línea en el código fuente?", "a. \\t", "b. \\n", "c. &lt;br&gt;", "d. \\g");

    addPregunta($pregresp, "¿Cuál de las siguientes funciones NO se puede acceder al servidor de datos MySQL?", "a. mysql_query", "b. mysql_connect", "c. mssql_connect", "d. mysql_pconnect");

    addPregunta($pregresp, "¿Cuál es la frase correcta?", "a. setcookie() puede ser llamada desde cualquier parte del documento HTML", "b. Las cookies sólo se pueden mandar antes de mandar cualquier otra cabecera", "c. Las cookies no son parte de la cabecera HTTP", "d. El perro de San Roque no tiene rabo, porque el Chiquito se lo ha robado");

    addPregunta($pregresp, "¿La función ftp_get?", "a. Sube un fichero al servidor FTP", "b. Establece una conexión FTP", "c. Descarga un fichero del servidor FTP", "d. Devuelve el nombre del directorio actual");

    addPregunta($pregresp, "¿Con qué función se puede eliminar una variable de sesión?", "a. session_unregister", "b. session_destroy", "c. session_register", "d. jam_session");

    addPregunta($pregresp, "¿Con que harías un buen bocadillo...?", "a. Con pavo de ese que tiene trozos de colores", "b. Con un milagro", "c. Con habichuelas", "d. Con las manos");

El switch podemos quitarlo a mano, y en este ejemplo, tal vez para 7 preguntas, podríamos hacerlo a mano, aunque si fuera alguna más, nos pensaríamos este nuevo método.

Bien, en EMACS, tenemos la siguiente herramienta:

M-x regexp-builder

Que nos seleccionará el texto que corresponde con la expresión regular que estemos construyendo, y nos ayudará a generar una expresión más compleja, en definitiva queremos que la expresión cubra todos los cases, para continuar la lectura del post, nos fijamos en el primero:

1
2
3
4
5
6
case 0: $preg="<br><br>¿Qué significa PHP?<br>";
            $resp="<a href=".$_SERVER['PHP_SELF']."?respuesta=1>a. Power H Processor</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=2>b. PHP: Hypertext Preprocessor</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=3>c. Para Hacer Poco</a><br>".
                  "<a href=".$_SERVER['PHP_SELF']."?respuesta=4>d. PHP: Harvard Preprocessor</a><br>";
            break;

Para construir la expresión, hay mucho copy-paste, además, desde Linux podemos seleccionar texto y pegarlo con el botón central del ratón, lo que nos facilita mucho la vida. Por otra parte, hay que tener en cuenta que tenemos que escapar muchos caracteres (como “, [, (, ), ], ?), de todas formas, nos vamos dando cuenta de eso al construir la expresión, si EMACS no selecciona un carácter como correspondiente a la expresión, lo más normal es que tengamos que escaparlo, también, tenemos que tener en cuenta que un espacio en blanco se representa aquí como [:space:]. Con todo esto, construimos la siguiente expresión:

“case [0-9]: $preg=\”

[a-zA-Z_.\<\>\/\¿\?áéíóú[:space:]]*
\”;
[[:space:]]*$resp=\”[\\_()a-zA-Z,\:áéíóú&;[:space:]\.]+
\”.
[[:space:]]*\”[\\_()a-zA-Z,&áéíóú\:;[:space:]\.]+
\”.
[[:space:]]*\”[\\_()a-zA-Z,&áéíóú\:;[:space:]\.]+
\”.
[[:space:]]*\”[\\_()a-zA-Z,&áéíóú\:;[:space:]\.]+
\”.
[[:space:]]*break;

Se seleccionarán todos los case, ahora copiamos la expresión para luego pegarla para reemplazarla. Aunque antes, tenemos que fijarnos en una cosa, en cada línea que queremos sustituir hay fragmentos de texto que queremos que figuren en la cadena sustituida, queremos hacerlo también automáticamente, eso lo conseguimos poniendo entre paréntesis en la expresión anterior las cadenas que vamos a aprovechar del texto que vamos a sustituir. La dejamos así:

case [0-9]: $preg=\”

\([a-zA-Z_.\<\>\/\¿\?áéíóú[:space:]]*\)
\”;
[[:space:]]*$resp=\”\([\\_()a-zA-Z,\:áéíóú&;[:space:]\.]+\)
\”.
[[:space:]]*\”\([\\_()a-zA-Z,&áéíóú\:;[:space:]\.]+\)
\”.
[[:space:]]*\”\([\\_()a-zA-Z,&áéíóú\:;[:space:]\.]+\)
\”.
[[:space:]]*\”\([\\_()a-zA-Z,&áéíóú\:;[:space:]\.]+\)
\”.
[[:space:]]*break;

Ahora llamamos a la siguiente orden:

M-x replace-regexp

Introducimos como expresión la última que hemos hecho (la de los paréntesis, marqué en negrita los textos que queremos conservar). Y la sustituimos por lo siguiente:

addPregunta($pregresp, “\1″, “\2″, “\3″, “\4″, “\5″);

Vemos que es una función a la que le pasamos una variable y después cinco textos, el primer texto (\1), coincidirá con la pregunta (en el código de los cases), y desde el segundo (\2) hasta el quinto (\5) coincidirá con cada una de las cuatro posibles respuestas.

Una vez hecho esto se sustituirán todo el código de los cases, por el de la función addPregunta() con los textos correspondientes.

Tal vez este ejemplo haya sido un poco grande, pero las expresiones regulares son muy útiles, seguro que casi a diario encontráis la necesidad de hacer algo parecido a esto en vuestro editor de texto.

Referencias:
Text Pattern Matching in EMACS
Regexp Replace - GNU Emacs

Foto: fdecomite (Flickr)

Nos ponemos serios con PHP: Empezamos con un CRUD (la esencia no es exclusiva de PHP)

Viernes, 16 de Julio de 2010 Gaspar Fernández Sin comentarios

crudHace años tuve entre manos un gran proyecto web, en el que invertí 8 meses de mi vida y funcionó bastante bien durante un tiempo. En su desarrollo recuerdo que tuve que desarrollar cerca 50 formularios diferentes, comprobar los valores de cada uno de los campos, hacer lecturas y escrituras en base de datos con los datos obtenidos, y opcionalmente realizar alguna tarea extra una vez enviado y validado el formulario. Además, tenía que ser capaz de listar la información, modificarla y eliminarla. Por aquel entonces, aunque había partes en común y aproveché para realizar código, no lo hice de la forma más efectiva; podría haber ahorrado muchísimo trabajo.
En los últimos años, para mis proyectos web decidí fabricarme una biblioteca para hacer este tipo de tareas de forma más rápida (con menos esfuerzo, y al fin y al cabo de forma más depurada y segura). Para eso me fabriqué una biblioteca CRUD.

Es cierto que perdemos eficiencia, es más rápida por lo general una herramienta específica, que haga justo lo que se le pide en un momento dado, que una herramienta configurable y flexible (tendremos muchas más sentencias de control y a veces se ejecutarán procesos innecesarios), pero por otro lado hay que tener en cuenta que no podemos echar un mes en un proyecto que generalmente requiere unos días, y por otra parte, seguro seguro que tenemos que hacer modificaciones antes de entregarlo, y éstas no deben llevarnos otro mes más. En definitiva, nos compensa perder algo de eficiencia en favor de un tiempo de desarrollo más corto y generar un código más fácilmente mantenible.

Lo importante de un CRUD, es la posibilidad de Crear, Ver, Actualizar, Borrar (y listar información), si lo pensamos es simple, lo ideal sería tener una clase (o una función) que simplemente llamándola nos hiciera esta complicada tarea; aunque también es verdad, si lo pensamos un poco más, que podemos complicar todo esto de mil formas, y todo lo que queramos. Además, tenemos que crear una herramienta que sea lo más flexible posible para todo tipo de bases de datos y tablas, y además, sería interesante manejar los errores que puedan surgir en el proceso, para poder generar una salida acorde.

Aunque podemos encontrar bibliotecas por Internet que hacen esta tarea, yo siempre prefiero una solución DIY (Do it yourself) (Hazlo tú mismo), de esta forma, el código será 100% mío y yo controlaré el proceso por completo, además de que como materia de aprendizaje es bastante efectivo. Dejo por aquí algunas instrucciones para empezar a fabricarnos un CRUD un tanto sencillo (y que a medida que vayamos haciendo proyectos podemos ir completándolo con las necesidades que nos vayan surgiendo):

  • Listar información de base de datos: Debemos tener la posibilidad de elegir los campos a listar
  • Crear entrada: Debemos tener la posibilidad de introducir campos que concuerden con entradas en una base de datos, y también la posibilidad de generar datos automáticamente (fecha de introducción, identificadores únicos, etc):
    • Necesitaremos un generador de formularios y la posibilidad de elegir el mejor tipo de campo para cada campo de la tabla que vamos a modificar
    • Debemos tener la posibilidad de verificar, vía servidor (PHP) o cliente (Javascript), mejor hacerlo de las dos formas, que los datos estén bien formados (números máximos de caracteres, formato de introducción (por ejemplo, de una fecha, un teléfono, una dirección e-mail…)
    • Inserción en tabla, y muestra de la salida, para que el usuario vea si todo ha ido bien o mal. Sería conveniente también, que esto fuera una redirección, para que, si se refresca la página, no se reenvíen los formularios.
  • Modificar entrada:
    • Podemos aprovechar mucho código de la creación de entrada (muestra de formulario, verificación…)
    • Debemos modificar la tabla de datos, a lo mejor actualizar fechas de modificación, logs, etc
  • Eliminar entrada:
    • Idealmente, debemos presentar un diálogo tipo: “¿Está seguro?” para confirmar que no se hace por accidente, tal vez los datos no siempre interese eliminarlos, sólo hacer una marca de que no se visualicen.
  • Ver información:
    • Necesitamos hacer un sistema de visualización flexible, automático y tener la posibilidad de seleccionar los campos a mostrar (los identificadores únicos, fechas internas, IDs, no le suelen interesar al usuario), por otra parte, a veces para visualizar un dato es necesario hacer varias consultas a base de datos y tenemos que estar preparados.

Pero como dije antes, esto lo podemos complicar hasta la saciedad, aumentando el número de campos que podemos introducir (por ejemplo inserción de ficheros, Javascripts para introducir la fecha de forma fácil, o inclusión de áreas de texto HTML (como TinyMCE).

En cuanto al listado podemos implementar paginación automática (para el caso de que haya muchos elementos a listar) y ordenación de los elementos por columna (tal vez por nombre, por fecha, etc)

Por otra parte, tenemos que tener muy en cuenta el diseño, éste suele ser diferente para cada página (quitando esas páginas que parece que están hechas todas con el mismo molde), así que tenemos que hacer que nuestra salida en (x)HTML sea lo más flexible posible, que nos deje introducir código adicional, cambiar las imágenes utilizadas (iconos de insertar, eliminar…)

Y como colofón, podemos implementar soporte para relaciones, puede que echemos unos días desarrollando nuestro CRUD, pero  nos va a ahorrar mucho tiempo de desarrollo si lo utilizamos en nuestros proyectos.

Curioso e interesante III: Licencias libres, sistemas de productividad, diseño web, Linux 5%

Jueves, 15 de Julio de 2010 Gaspar Fernández Sin comentarios

En los últimos días me he encontrado con información interesante, ¡echadle un vistazo!

Categories: General Tags: , , , , , ,

Pequeña reflexión sobre el uso de Linux

Jueves, 15 de Julio de 2010 Gaspar Fernández Sin comentarios

Esto está basado en una conversación real. Hace un tiempo, encontré a una de esas personas, que yo llamo cariñosamente, un gafe informático, tras comprarse el primer ordenador, tuvo mala suerte instalando Windows (Millenium, sé que todos tenemos un amigo de un amigo al que le ha funcionado bien esta versión, pero no fue el caso de esta persona), cada poco tiempo le fallaba casi sin hacer nada, de estas veces que instalas cuatro programas locos que has instalado varias veces en varios ordenadores y en el ordenador de esa persona no entran. El problema no era fácilmente reproducible, ya que sólo pasaba a veces; pero aún así, con muchos problemas, aguantó un año con el ordenador.

Al año siguiente compró otro, y al instalar Windows XP, tuvo varios problemas, y hubo que devolver a la tienda el ordenador por errores de hardware (hasta que al final se lo dieron instalado y todo), y en cuestión de un par de meses, Windows empezó a dar pantallazos azules, al reinstalar, seguía dando pantallazos, esta vez por culpa de la actualización de un driver de la placa base. Sin él, el ordenador funcionaba, aunque el USB2.0 no funcionaba, y el disco duro iba un poco más lento, siguió con el mismo Windows XP que reinstalaba manualmente cada 3 meses (no hacía un uso intensivo del ordenador, no instalaba muchos programas, aunque sí usaba Internet Explorer).

Compró también un portátil, tenía un problema en la RAM, que más tarde verifiqué personalmente; aunque mientras duraba la garantía, los del servicio técnico, en los numerosos partes de reparación (y los numerosos viajes que se pegó el portátil antes de funcionar), decían que le habían cambiado la CPU, el teclado, la placa base (este no me lo creí), la batería un par de veces… (esta historia acabó en denuncia e indemnización)

Fue el momento en que conocí a esta persona, y le propuse una forma de reinstalar Windows más rápida que a la antigua usanza, haciendo imágenes de la partición de sistema (algún día hablaré de esto), el tema es que verifiqué con un live CD de linux, que el USB 2.0 de su ordenador iba perfectamente, la transferencia de datos también, y tras usarlo mi amigo durante un rato, me dijo que su ordenador nunca había ido tan rápido. En este momento, le propuse probar Linux durante un mes y la cosa fue así:
- Es muy difícil - A.
- Sólo cambian los nombres de algunos programas y el botón de Inicio, que no pone Inicio - Yo (le enseñé un sistema KDE)
- Sí, pero la consola es de escribir mucho - A.
- Bueno, pero no hay por qué utilizarla - Yo
- Pero si la tiene, será para algo - A.
- Sí, es como la de Windows, pero ésta hace más cosas - Yo
- Claro, pero hay que aprender más cosas para saber aprovechar todas sus características - A.
- Bueno, pero tienes el registro de Windows, las políticas de acceso, los servicios de sistema, etc; que seguro que ni los has tocado - Yo.
- Cierto, pero al no estar a la vista, no tengo por qué conocerlo - A.

(Por cierto, la A. es de Amigo)

En fin, una conversación que se alargó un poco más de forma improductiva, después de que Linux se ahorrara unas 4 horas al mes en reinstalaciones de disco duro (con lo de la imagen de sistema y partimage), rescatara una partición de Windows cuando XP dejó de detectarla (no lo sé, de un arranque a otro la partición desapareció, pero Testdisk la rescató cuando ningún programa para Windows fue capaz), y sobre todo cuando con Linux, estuve trabajando unas horas con su primer ordenador sin ningún problema.

Me he encontrado a varias personas que no quieren probar Linux, ni algo que no sea Windows, a pesar de las malas experiencias. Aunque los que somos usuarios o conocemos bien este sistema, veamos que para un uso más o menos normal (navegación, ofimática, grabación de discos y alguna cosa más), no se necesita ningún conocimiento especial, ni siquiera hay que mirar la consola. Es más algunas distribuciones nos detectan e instalan el hardware que enchufamos automáticamente, pero aún así, y después de mostrar estas características, muchos se muestran rehacios al cambio; muchos aún son cautivos de la frase: “Más vale malo conocido que bueno por conocer”, sin ninguna razón sólida; aunque cada vez encuentro más personas que se sienten incómodas con el Windows de toda la vida, con el mantenimiento que requiere, y con que se pierde tiempo y energía, y en el que muchas cosas que en cualquier otro sitio se solucionan con un pequeño script, en Windows requieren un programa y varios Megabytes.

Visita otras webs de la red