Archivo

Archivo para Mayo, 2010

Una balanza que no funciona

Lunes, 31 de Mayo de 2010 Gaspar Fernández Sin comentarios

450px-balanzaLlega el día en que nos dedicamos al desarrollo, ya sea por libre, en una empresa, para investigación o en cualquier otra circunstancia; tenemos que poner en práctica lo aprendido durante tanto tiempo y no estamos haciendo simples ejercicios ni programas de un máximo de 200 líneas (con muchos espacios en blanco, comentarios multi-línea y esas cosas).
Es decir, nos enfrentamos a un proyecto real y tenemos que dar lo mejor de nosotros mismos en su realización.
Como tampoco es un proyecto excesivamente grande decidimos pasar de hacer una planificación previa del proyecto, y decidimos que es más rápido pasar a la acción y ponernos a picar código.
Comprendo que si no se tiene mucha experiencia, es una tarea intelectualmente más ligera ponernos a escribir de forma estructurada nuestros algoritmos, excepcionalmente haciendo alguna función; no tenemos tiempo para separar estructuras, ni para idear algún algoritmo extra que nos simplifique un poco el código, pero no le damos importancia… simplemente nos damos el batacazo cuando el cliente nos pide un pequeño cambio en el código; de repente se nos viene a la cabeza la famosa teoría del caos. Y es que nuestro código es un caos. Y no comprendemos que el cliente (a no ser que seamos nosotros mismos), usuario, jefe, o persona que necesita el programa pero no tiene ni idea de cómo se desarrolla tiende a pensar que todos los cambios son pequeños y que cualquier modificación se hace en 10 minutos; por tanto, la primera versión de nuestro código no va a servir, y tenemos que distinguir entre: pijadas, o modificaciones en la interfaz, cosas que harían el programa más bonito; entrada/salida, tal vez campos de una base de datos que se suponía que teníamos que introducir y que no están (será porque nadie nos había informado de que la posición en que una persona jugaba al fútbol de pequeño era un dato personal básico e importantísimo); o que está visualizando más datos de los que quiere; cambios estructurales, esos ya son más peliagudos, pero bueno.
Lo que quiero decir, es que la versión preliminar que hagamos casi nunca va a ser la buena y tendremos que revisarlo, incluso al cabo de un tiempo, se necesitará añadir una característica más, y la hemos liao si seguimos por este camino.

Tenemos que hacer de nuestro código un arte:

  • Podemos comentar en nuestro idioma hasta la saciedad, aunque sin pasarnos.
  • Podemos dividir nuestro código, e incluso cuando hacemos cosas muy parecidas podemos unificarlas en una función/clase/proceso diferente. El lema divide y vencerás es muy útil, y a la larga hace nuestra aplicación más facilmente mantenible.
  • Podemos separar la lógica del programa, con lo relativo a datos y lo relativo a la visualización (MVC)… programar a pegotón no ayuda.
  • A veces, con alguna operación matemática, nos podemos ahorrar una secuencia iterativa
  • No por mucho que tarde nuestro programa en hacer una tarea determinada, lo hace más profesional, aunque hay empresas que esto no lo tienen muy claro.

Si bien es cierto que cuando llamamos a funciones estamos haciendo la ejecución de nuestro código más lenta (con operaciones recursivas ya ni hablamos), tenemos que tener en cuenta si podemos sacrificar unos cuantos milisegundos en la ejecución en favor de unas cuantas horas de desarrollo, y es que muchas veces, crear una función, incluso para hacer nuestro código más legible (por ejemplo, si estamos presentando los resultados de una búsqueda, y necesitamos ordenarlos, no tenemos por qué implementar el método de ordenación en el mismo sitio, nos lo podemos llevar fuera; incluso si tenemos que presentarlo de forma bonita para el usuario, podemos hacer una función aparte que presente esos datos), puede ahorrarnos mucho tiempo de mantenimiento; cuando al cabo de dos semanas nos enfrentemos de nuevo a nuestro código, seguro que preferimos ver las cosas más claras.

Dando ejemplos (no todo se hace en los lenguajes mencionados, esto lo podemos extender a muchos lenguajes más):

  • Vale, estamos diseñando un sistema de tiempo real y tiene que funcionar rápido, como ejecutamos las órdenes muchas veces, no podemos queremos hacer funciones ni hacer nada complicado, para no ralentizar mucho la ejecución… en C/C++, por ejemplo, podemos crear macros.
  • Nuestras necesidades pueden ser más complicadas, tenemos que tener en cuenta que un lenguaje de programación, nos da herramientas básicas, y las podemos extender. Imaginad el uso de mysql_query() [PHP], puede que necesitemos contar cuántas veces se ha llamado esta función. Esto implicaría ver dónde se ha llamado la función e incrementar una variable, aunque tal vez en el futuro tengamos más necesidades.
  • Ya no hablamos de la abstracción con objetos, al principio nos choca esa forma nueva de pensar, pero a la hora de embarcarnos en un proyecto, de primeras no la tenemos muy en cuenta. Por ejemplo, en C++ o en PHP es muy cómodo trabajar con una clase que se entienda con las bases de datos, nosotros símplemente tenemos que llamarla siempre que necesitemos algo.
  • A la hora de hacer una web dinámica se piensa poco en un posible re-diseño, y cuando este llega nos echamos las manos a la cabeza ya que hemos puesto multitud de código PHP entre el (x)html… podremos crear una biblioteca de funciones dedicada a la exportación web y desde nuestro php llamarlas… haría fáciles los re-diseños.

Todo esto viene unido a un post anterior: Enseñando a programar, sobre todo porque en muchos lugares se enseña programación (me refiero a carreras universitarias que no tienen que ver con informática; algunos ciclos formativos, etc) pero uno de los grandes objetivos es que nos sirva para el futuro; y de poco sirve si no se sientan unas bases. Es importante el reciclaje, la claridad y la sostenibilidad.

Foto: Feliciano

Enviando posts a twitter

Viernes, 28 de Mayo de 2010 Gaspar Fernández Sin comentarios

twitter-bird-6

Hace mucho tiempo leí en anieto2k una función muy interesante para twittear sin necesidad de incluir APIs tremendas. Es decir, si en mi aplicación, sólo quiero enviar twits, ¿para qué incluir algo demasiado grande? Con una pequeña función estaría todo resuelto.

El tema es que hace poco inicié un proyecto que periódicamente envía twits y necesité echar mano de esa función. Descubrí que Twitter había cambiado un poco su forma de interactuar.

Antes, podíamos enviar por GET (en la URL) el parámetro del mensaje que íbamos a postear, aunque ahora devuelve un error extraño: 413 Request Entity Too Large, más o menos es cuando la consulta que enviamos al servidor es muy grande; aunque el error nos lo da porque no encuentra el post que queremos publicar.

Para solucionarlo, tenemos que enviarlo con el método post, de la siguiente forma:

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
function postToTwitter($username,$password,$message)
{
// Esta línea está modificada
    $host = "http://twitter.com/statuses/update.xml";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $host);
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_POST, 1);
// Esta línea es nueva
   curl_setopt($ch, CURLOPT_POSTFIELDS, 'status='.urlencode(stripslashes(urldecode($message))));
    $result = curl_exec($ch);
    $resultArray = curl_getinfo($ch);
    curl_close($ch);
    if($resultArray['http_code'] == "200")
    {
        echo "<br />OK! postedo en http://twitter.com/".$username."/<br />";
    }
    else
    {
        // Esto lo podemos quitar, es sólo para analizar la salida.
        print_r($resultArray);
        echo "<br />Error! ha ocurrido un problema<br />";
    }
}

Con esta versión modificada del script ya podemos twitear :)

Y para llamar a esta función:

postToTwitter(’usuario’, ‘contraseña’, ‘140 letras de lo que queremos twitear’);

Foto: Free Twitter Bird Icon Set

A los de Linares les gusta la programación

Viernes, 28 de Mayo de 2010 Gaspar Fernández 3 comentarios

04082009574 Es un pequeño chiste (muy malo, por cierto).

Vemos cómo en la pantalla, en la línea 6 de autobuses de Linares aparece Array.-Geriatric.

Categories: General Tags: , ,

Saber si estamos conectados a internet [bash]

Miércoles, 26 de Mayo de 2010 Gaspar Fernández Sin comentarios

cat_linuxA menudo lanzo scripts que necesitan saber si la conexión a Internet está disponible para lanzarse, en caso de que no lo esté, invertirán mucho tiempo en terminar o terminarán con muchos errores. La forma más fácil de saber cuándo estamos conectados es intentar acceder a un ordenador que sepamos seguro que está conectado… por ejemplo google.com, que para eso está.

Podemos por ejemplo hacer ping al servidor, pero un ping es muy visual, necesitaremos hacer algo más para aprovechar la salida de ese ping; aunque también podemos intentar conectar por el puerto 80 (http).

Dejo varios métodos para poder hacerlo de forma sencilla desde la línea de comandos:

ping

$ if ping -c1 google.com &>/dev/null; then echo “Tienes conexion”; else echo “no tienes conexion”; fi

Con esta línea haremos un ping a google, sólo mandaremos un paquete (-c1) y mandaremos la salida de ping a /dev/null (no nos interesa lo que nos diga, queremos hacer un script amigable al usuario, sin mensajes raros), si ping no da errores, se ha hecho bien, mostramos el mensaje de tienes conexion, si no, el de no tienes conexión.

Aunque en los siguientes scripts haremos una salida de texto, siempre podremos hacer un exit y terminar el script cuando no haya conexión.

netcat

if netcat -z google.com 80; then echo “Tienes conexion”; else echo “no tienes conexion”; fi

Igual que antes pero probamos la conexión al puerto 80, netcat utiliza el parámetro -z para ver sólo si se puede conectar, una vez se conecta, se cierra la conexión.

escribiendo en el servidor directamente

Tenemos dos métodos más…

if echo “”>/dev/tcp/totaki.com/80; then echo “Tengo conexion”; else echo “no tengo”; fi

Aquí conectamos con el servidor a través de /dev/tcp (necesitamos tener permisos), al servidor le enviamos una cadena vacía.

También podemos hacer:

if exec 3>/dev/tcp/totaki.com/80; then echo “Tengo conexion”; else echo “no tengo”; fi

Utilidades y notas

Podemos utilizarlo por ejemplo en cron scripts que requieran conexión a internet (subir una copia de seguridad a un servidor externo, enviar nuestra ip de Internet a un servidor), o por ejemplo para saber la disponibilidad de un servidor, es decir, si tenemos alquilado un servidor a lo mejor nos interesa monitorizarlo para saber si está caído, en fin los usos son los que nos de la imaginación.

Antes dije que podríamos incluir un exit cuando el script no tenga conexión, pero también podremos llamar a otro script en el caso de tener conexión, o hacer lo siguiente (con el ejemplo de ping):

1
2
3
4
5
6
7
8
#!/bin/bash
if ping -c1 google.com &>/dev/null;
then
        echo "Ejecutando script";
        $@
else
        echo "no tienes conexion";
fi

Llamamos al fichero internet, damos permisos de ejecución y podremos llamar a cualquier script de la siguiente forma:

$ internet wget http://www.totaki.com/poesiabinaria

(por ejemplo), el script sólo se ejecutará si estamos conectados a Intenet

Mejoras

Bueno, puede pasar, que alguna vez google.com esté caído, podemos intentar pasar por dos o tres servidores, si vemos que uno de ellos responde (siempre que no sea de una red local) sabremos que estamos conectados.

Foto: fotohiro (Flickr)

Uso de llaves en BASH

Sábado, 15 de Mayo de 2010 Gaspar Fernández 1 comentario

llaves
Leo en el blog de Thalskarth (proveniente de Tux Files, que a su vez venía de Slice of Linux) un truco para hacer copias de seguridad de un archivo con bash de la siguiente forma:

cp archivo{,.bk}

Lo que hacemos es parecido a escribir esto otro:

cp archivo archivo.bk

Por lo que podemos intuir fácilmente para qué valen las llaves en este contexto: replicar alternativas. Es decir escribiremos lo que hay antes de la llave, y lo terminaremos con cada una de las opciones de dentro de las llaves que están separadas por comas. Y lo más fácil para entender esto es utilizar echo.
Probaremos lo siguiente:

$ echo “Voy a pintar mi casa de “{verde,azul,rojo,amarillo}
Voy a pintar mi casa de verde Voy a pintar mi casa de azul Voy a pintar mi casa de rojo Voy a pintar mi casa de amarillo

Bien, el mensaje se replica con un espacio entre réplicas. Podemos ahora probar algo más:

$ echo -e “Voy a pintar mi casa de “{verde,azul,rojo,amarillo}”.\n”
Voy a pintar mi casa de verde.
Voy a pintar mi casa de azul.
Voy a pintar mi casa de rojo.
Voy a pintar mi casa de amarillo.

Además, podemos ver que la llave no tiene por qué estar al final del parámetro, podemos ponerla en mitad y sigue funcionando. Hay un espacio al principio de la línea, como mencioné antes, las frases irán separadas por un espacio (es normal, las llaves nos sirven para introducir nuevos parámetros). Podremos solucionarlo con \b (backspace).

echo -e “\bVoy a pintar mi casa de “{verde,azul,rojo,amarillo}”.\n”
Voy a pintar mi casa de verde.
Voy a pintar mi casa de azul.
Voy a pintar mi casa de rojo.
Voy a pintar mi casa de amarillo.

Antes de nada un apunte, no debemos dejar espacios dentro de las llaves, ni entre las comas, ni dentro de cada opción, no olvidemos que son parámetros, aunque sí que podríamos poner un espacio si éste va entre comillas (igual que ocurre con los parámetros).

Crear PDFs

Y a partir de aquí, sólo necesitamos imaginación, por ejemplo podemos ver cómo lo usamos para crear un pdf con imágenes en jpeg (de una carpeta llamadas test-N.jpg). Lo creamos con ImageMagick y sólo queremos de la 1 a la 12:

$ convert test-{?.,10.,11.,12.}jpg todos.pdf

Aunque hay un método mejor, {} (las llaves) soportan rangos, por lo que podemos hacer:

$ convert test-{1..12}.jpg todos.pdf

Comprimir directorios

Podemos, por ejemplo crear un archivo comprimido de un directorio con el mismo nombre de la siguiente manera:

$ tar cvjf test{.tar.bz2,/}

como sustitución a:

$ tar cvjf test.tar.bz2 test/

Diferencias

Encontrar la diferencia de un archivo con su backup (suponemos que el backup es el mismo nombre terminado en ~ (tilde de la ñ):

$ diff test{,~}

O para diferencias rutas (recordemos que podemos poner llaves entre parámetros:

$ diff ~/proyectos/www/{proyecto1,proyecto2}/www/lib/my_lib.h

Que es lo mismo que:

$ diff ~/proyectos/www/proyecto1/www/lib/my_lib.h ~/proyectos/www/proyecto2/www/lib/my_lib.h

Lectura de datos en scripts

Para leer desde la entrada estandar tenemos read, y si queremos introducir cada palabra en una variable podemos usar read palabra1 palabra2 palabra3, y si queremos que estas variables tengan un prefijo común:

$ read palabra{A,B,C}

Combinaciones y juegos

Vamos a hacer múltiples sumas con bc:

$ echo -e {1..4}”+”{4..1}”\n” | bc

Esto pondrá en pantalla el resultado de: 1+4, 1+3, 1+2, 1+1, …, 4+3, 4+2, 4+1.
Con esto vemos que los rangos no sólo van en incremento sino también en decremento.
Pero aún más si hacemos:

echo test{a..z}

Nos completará con testa testb testc…testx, testy, testz

Por último, un ejemplo más complicado, y que, aunque pocas veces nos sirva (más que nada por no acordarnos), ahí queda, llaves anidadas:

$ echo test-{1{10..12},3{9..1}}
test-110 test-111 test-112 test-39 test-38 test-37 test-36 test-35 test-34 test-33 test-32 test-31

Tenemos la posibilidad de introducir opciones dentro de otras opciones y todas se representarán seguidas. ¿Tal vez nos sirva alguna vez para crear un fichero de texto con datos de prueba? Para crear un archivo con temperaturas de varias ciudades:

$ echo -e “\b”{”Madrid 1″{1..4},”Barcelona 1″{3..5},”Malaga “{19..22},”Sevilla 2″{3..4}}”\n” > test

Esto creará un fichero llamado test con el siguiente contenido:

Madrid 11
Madrid 12
Madrid 13
Madrid 14
Barcelona 13
Barcelona 14
Barcelona 15
Malaga 19
Malaga 20
Malaga 21
Malaga 22
Sevilla 23
Sevilla 24

Foto: bohman (Flickr)

EMACS: Cambiando la codificación

Miércoles, 12 de Mayo de 2010 Gaspar Fernández Sin comentarios

Es muy común, sobre todo en trabajos colaborativos, que cada persona trabaje en una codificación diferente (casi siempre porque se usan programas diferentes para editar, y poca gente se para a cambiar la codificación por defecto). Por ejemplo, hay quienes guardan todos sus archivos en iso-8859-1 o iso-8859-15, incluso utf-8. Pero llega el momento en que se edita el archivo de otra persona, y esas codificaciones producen extraños comportamientos en la ejecución.

Una solución desde EMACS sería:
M-x set-buffer-line-coding-system RET [codificación, TAB para ver opciones] RET

O también podemos utilizar la recla rápida:
C-x RET f [codificación] RET

Ya podemos salvar el archivo (C-x C-s) y seguir trabajando.

Descargar automáticamente todos los programas de Redes

Domingo, 9 de Mayo de 2010 Gaspar Fernández Sin comentarios

neuron
Apenas veo la televisión, pero hay ciertos programas que son interesantes y merecen la pena como Redes. Y tampoco me gusta verlos desde la web ya que Flash es muy lento, y me gusta tener lo que veo echar hacia atrás y hacia alante (como hace mplayer) y verlo cómodamente.

Para ello, lo más cómodo es descargarlos, pero cómo descargarlos si tengo que bajarlos uno a uno (y son muchos), y tengo que mirar dónde está el archivo de vídeo (lo primero que nos podemos bajar a mano es una archivo de metadatos que nos dirá dónde está el vídeo), es una tarea muy lenta para hacerla a mano. ¿ Por qué no automatizar el proceso ?

Vemos que desde la web de Redes para la Ciencia nos podemos descargar los programas desde 2008 (lástima que los anteriores no estén disponibles en vídeo desde esta web), y éstos están alojados en Smartplanet (blip.tv). Con estos datos, he confeccionado este script (aún en beta, no es muy estable, ni está optimizado, pero nos hace el apaño).

Si observamos los pasos intermedios de este script, y vemos el fichero de metadatos por dentro, veremos cómo podemos ver más información, descargar el archivo en mov o mp4 (a gusto del consumidor), también encontramos un resumen del programa; os invito a hacer pruebas y comentarlas en este post.

Una posible mejora a corto plazo, sería poner en orden la variable get_years y que, si descubre que varios capítulos han sido descargados, no intente bajar más (a la hora de descargar el último capítulo también con el script), o incluso almacenar en un archivo el número del último capítulo descargado, para así buscar el siguiente en la siguiente ejecución… todo se andará; por ahora, os dejo el script así, que con un poco de cuidado funciona bien.

Y otra cosa más, con un poco de suerte, para el año que viene, sólo tendremos que añadir a la variable get_years el link del blog con los enlaces a los capítulos del año 2011.

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
#/bin/bash

get_years="http://www.redesparalaciencia.com/programas-2009 http://www.redesparalaciencia.com/programas-de-2008 http://www.redesparalaciencia.com/programas-2010"

for i in $get_years
do
    echo Descargando $i ...
    wget -q -O /tmp/listado_year $i
    echo Descargado
    # Hay algunas URLS que salen con ../
    caps_year=`cat /tmp/listado_year | grep 'href' | grep '>Redes [0-9]' | sed -e 's/\.\.\//http:\/\/www\.redesparalaciencia\.com\//g' -n -e 's/\(.*\)href=\"\([^\"]*\)\"\(.*\)/\2/p'`
#   caps_year=`cat /tmp/listado_year | grep 'href' | grep '>Redes [0-9]' | grep -o '"http://[a-zA-Z0-9.\/\-]*"' | cut -d\" -f2`
    for j in $caps_year
    do
        echo Descargando metadatos del episodio...
        wget -q -O /tmp/episodio $j
        episodio=`grep -o 'http://blip.tv/rss/flash/[0-9]*' /tmp/episodio`
        wget -O /tmp/metadatos $episodio
        echo Metadatos descargados
        video=`awk -F "\"" '/media\:content/ {print $2}' /tmp/metadatos | grep flv`
        titulo=`sed -n 's/<media:title>\(.*\)<\/media:title>/\1/p' /tmp/metadatos`
        if [ -r "$titulo.avi" ] || [ -r "$titulo.flv" ]
            then
            echo "Episodio $titulo ya existe. Descartando."
        else
            echo "Descargando episodio... $titulo"
# Podemos quitar el -q para ver cómo va la descarga.
            wget -q -O "$titulo.flv" $video
            echo "Recomprimiendo episodio..."
            ffmpeg -i "$titulo.flv" -vcodec msmpeg4v2 -b 1200k -acodec mp2 -ab 128k "$titulo.avi"
        fi
    done
done

Requerimientos: wget, sed, awk, ffmpeg (si queréis recomprimir los programas) y algunos gigas libres de disco duro (unos 20 o así si queremos recomprimir).

Notas:

  • La compresión no está muy optimizada, tal vez comprimamos con más bitrate del que debemos, pero bueno. Si no queremos comprimir, basta con comentar la línea de ffmpeg, aunque si queremos verlo en algún reproductor debemos dejarla. El codec de audio (acodec), es mp2, ya que el mp3 no me funcionaba bien, libmp3lame debe estar instalado y ffmpeg compilado con soporte para él, aún así, probad antes).
  • Soy consciente de que hay demasiado sed, awk y scripts de sobra, pero fue un script rápido y tampoco importa mucho el tiempo que pasemos parseando los metadatos.
  • No hay control de errores, si falla algo y el script se vuelve loco… yo no garantizo nada :)
  • Por ahora, si un archivo no se baja del todo, debemos eliminarlo para que se baje de nuevo por completo.

Espero que disfrutéis del programa.

Foto: MikaNet (Flickr)

Enseñando a programar

Viernes, 7 de Mayo de 2010 Gaspar Fernández 5 comentarios

Desde hace tiempo, me ofrezco como profesor particular de programación en C/C++ (entre otros), he conocido bastantes alumnos, y metodologías de varios profesores. Este artículo es una opinión personal de mi experiencia.

En principio tengo que decir que muchos de mis alumnos, sólo venían para sacarse una asignatura, no tenían demasiado interés, aunque fuera una de las asignaturas claves de sus estudios, y algo que les ayudaría el día de mañana; aunque es cierto que no todo el mundo puede aprender a programar desde cero y con soltura en 3 ó 4 meses, requiere un entrenamiento, dedicación, mucho tiempo y enfrentarse con problemas una y otra vez, y si le sumamos a esto poco interés estamos perdidos.

Es cierto que igual que en todas las ciencias e ingenierías tiene un aspecto recursivo y es que lo más sencillo se enlaza con aspectos muy complicados y es difícil introducir a alguien en este mundo sin que queden preguntas sin resolver y huecos que en el futuro se rellenarán, pero algunas insaciables mentes quieren ir más deprisa, y cuando las respuestas a sus preguntas empiezan a sonar a chino, abandonan.

Es por esto, que como profesor hay que ofrecer algún valor adicional al alumno, y aunque no es complicado ofrecer en un grupo reducido, existen muchos centros de enseñanza en los que ni siquiera se intenta; no podemos pretender enseñar C a una persona con Borland C, un IDE del año 1992 (sí, ya es mayor de edad y aunque hace años luz de su salida, se sigue usando). Los alumnos de hoy en día no valoran que hace 16 años flipábamos haciendo un entorno en modo texo, y estábamos acostumbrados a los 80 caracteres x 25 líneas.
Hoy en día ver sólo 80 letras por línea y tan pocas líneas, agobia un poco, eso de no poder cambiar el tipo de letra, el tamaño y elegir entre una gran variedad de colores parece que lo hace todo un tanto inútil, y da la impresion de que nunca se van a utilizar esas cosas.

Soy consciente de que es difícil enseñar a programar prescindiendo del modo texto, ya que la entrada/salida es muy fácil de implementar y de probar, y si estamos empezando es normal que compilemos mil millones de veces sin éxito, y luego tengamos errores de en tiempo de ejecución y ocurran sucesos extraños en nuestros pequeños programas. Por lo que en principio propondría un poco de renovación de software, es cierto que los centros donde se sigue enseñando con Borland C y programas de la época llevan haciéndolo así durante años, pero aunque C va a seguir siendo el mismo, se pueden probar otros IDEs que nos permitan por lo menos hacer el tema un poco más ameno para el alumno. (Dev-C++, Netbeans, Anjuta, o utilizar Kate y compilar a mano, también soy consciente de que éstos también se utilizan en muchos sitios).

Por otra parte, me gustaría hablar sobre la programación amena, es cierto que al principio, tenemos que limitarnos a enseñar las posibles herramientas de las que disponemos, con paciencia, ejemplos, y viendo lo que es capaz de hacer cada herramienta; pero propongo hacer programas libres a corto plazo, es decir, embarcarnos en pequeños proyectos (siempre viendo lo que está dentro de las posibilidades de lo enseñado), con lo que se pueda practicar y seguir aprendiendo. Por ejemplo:

  • Si el alumno está interesado en la economía, se puede hacer un sencillo gestor de economía personal, o un pequeño simulador FOREX (Mercado de divisas) con unos pocos datos generados.
  • Si le gusta la fotografía, podemos empezar (con algunas funciones prediseñadas) a leer y escribir archivos BMP o JPG. Aunque suene complicado símplemente se pueden entregar un .h y un .c y una pequeña documentación de cómo llamar a esas funciones.
  • Está bien el hecho de hacer juegos, pero meternos en un juego directamente es una tarea un tanto complicada, ¿por qué no empezar con las tres en raya? O un juego de sumas y restas, un ahorcado…
  • Está bien empezar también con algo tangible y que todos conocemos, por ejemplo una máquina expendedora, un programa que diga una frase, tipo Facebook, un programa de envío de email (aunque tengamos que entregar algunas funciones extra).

Por esto, siempre empiezo preguntando a mis alumnos por algo que les guste, es verdad que para una clase particular es fácil, un grupo grande es mucho más difícil de llevar, sobre todo si cada uno hace un trabajo diferente, pero se puede guiar por lo que más o menos les interese a todos. Y una cosa importante, que hayamos hecho algo mil veces, no nos quita de currar, y de intentar hacerlo siempre lo mejor que podemos

Propongo unas pistas/consejos, para hacer la programación mucho más emocionante:

  • system() no sólo vale para hacer system(”PAUSE”); para que en Windows no se nos cierre la ventana; podemos ejecutar cualquier cosa, desde un programa que reproduce sonidos, hasta otro para mostrar una imagen, como un navegador web, lo que sea… podemos usarlo para más cosas.
  • Hay librerías fáciles de usar que nos pueden hacer la vida un poco más amena, por ejemplo xosd, con lo que podremos presentar mensajes en pantalla
  • Kdialog, dialog, Xdialog, Zenity… son programas que nos ayudarán a mostrar mensajes en pantalla de forma fácil, usémoslos.
  • Los alumnos se acostumbrarán antes a llamar código de terceros si les proporcionamos las librerías para ello, a lo mejor se ve demasiado complicado, pero obtener un texto de una página web, o que se vea que un mensaje se ha sacado de Google o Twitter, cuando acabas de empezar te anima un poco.
  • No podemos pedir ejercicios muy simples, y de repente un ejercicio extremadamente complicado, que nadie va a ser capaz de resolver, debemos ir progresivamente y pensar que aún no se tiene una mentalidad de desarrollador, tenemos que desarrollarla nosotros, no hacer que abandone.
  • Lo más importante, paciencia, nosotros tenemos años de experiencia y tratamos con personas que no tienen ninguna, y empiezan ahora, tenemos que hacer un seguimiento de lo que están haciendo, aunque es cierto que algún día hay que aprender a buscarse la vida, tenemos que hacerlo poco a poco y escoger el momento.

Casi todo este post, se ha basado en mi experiencia de programación en C/C++, y es verdad que en otros lenguajes (Visual Basic por ejemplo), se realizan otro tipo de ejercicios algo más interactivos y que generalmente gustan más; es cierto que nos deja muchas cosas hechas y no tenemos que recorrer tanto camino para llegar a algo complicado, aunque también es cierto que hay muchos más lenguajes cuya sintaxis se parece más a C que a Basic, por lo que considero uno de los grandes pilares de la programación.

Me gustaría dedicar un par de párrafos al pseudolenguaje o pseudocódigo, es cierto que a muchas personas les ha ayudado en la comprensión del código y el diseño de los algoritmos, así como cuando se quiere decir algo en un idioma diferente al idioma natal, primero lo pensamos en nuestro idioma (más o menos) y luego traducimos en dos o tres iteraciones (primero normal, luego cambiamos verbos de sitio, luego adjetivos…); aunque a la hora de programar, primero tenemos en mente nuestra idea de lo que queremos hacer, y luego diseñamos el algoritmo en pseudolenguaje, tras ello, traducimos línea por línea, en un proceso que puede llegar a durar varios minutos.

Es una expresión en lenguaje natural, que resulta de todo menos natural, y realmente lo veo un tanto pérdida de tiempo; para aprender a programar y a crear algoritmos uno de los procesos fundamentales es compilaro y probarlo hasta que salga, y con el pseudolenguaje no tenemos forma de hacerlo (sí, hay algún compilador, pero prácticamente no se utiliza). ¿Por qué no enseñamos a programar directamente? Así podemos probar lo que hacemos en tiempo real y sobre todo, saber que progresamos. Sí está bien utilizar diagramas de flujo y tratar de entender el algoritmo, hacer esquemas, etc; pero me refiero a intentar aprender una sintaxis nueva que en tres o cuatro meses que suele haber para aprender la materia se puede atragantar y evita que avancemos.

Búsquedas rápidas en el historial de BASH

Jueves, 6 de Mayo de 2010 Gaspar Fernández Sin comentarios

2683642114_bba3d6383e
Cuando pasamos mucho tiempo en escribiendo en terminal, a veces tenemos la necesidad de repetir algo que escribimos en el pasado. Puede que estemos compilando algún programa, o haciendo un ./configure e instalando dependencias de un programa…
Muchas distribuciones lo tienen por defecto (por ejemplo Gentoo), pero otras muchas (Ubuntu, Mandriva, ArchLinux…) no lo tienen; se trata de activar las teclas de Avance y Retroceso de página para hacer búsquedas en nuestro historial.
Esto sirve, por ejemplo para que, si escribimos algunas letras de una orden que enviamos en el pasado, y pulsemos RePag nos encuentre aquellas órdenes que enviamos en el pasado y nos ahorre unas cuantas pulsaciones de teclado.

Lo que debemos hacer es editar el archivo /etc/inputrc, muchas distribuciones traen ciertas líneas parecidas, por lo que si vemos alguna línea que empiece por “\e[5~” o “\e[6~” deberíamos comentarla (con #) o borrarla; y tras ello introducir lo siguiente:

“\e[5~”: history-search-backward
“\e[6~”: history-search-forward

Para mí, es la forma más cómoda de trabajar.

Foto: Liamdunn (Flickr)

Getters / Setters en PHP

Sábado, 1 de Mayo de 2010 Gaspar Fernández Sin comentarios

Cuando estamos programando con clases en PHP, a veces tenemos la necesidad de acceder a atributos privados de una clase desde fuera, tal vez para sólo lectura, sólo escritura, o porque estos no pueden tener cualquier valor.

Pero claro, son atributos privados, no podemos hacer esto tal alegremente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
class test
{
    private $privado;
    function test()
    {
      $privado="Variable privada";
    }  
}

$t=new test;

echo $t->privado;

?>

En C++, por ejemplo, definimos getters/setters para todos los atributos qud podamos “tocar” desde fuera, aunque, es escribir demasiado (tratamos cada atributo por separado, y está bien). Por otra parte, en PHP tenemos los métodos mágicos, y entre ellos encontramos __get() y __set() y haciendo caso al ejemplo anterior podemos hacer lo siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class test
{
    private $privado;
    function test()
    {
      $this->privado="Variable privada";
    }  
   
    function __get($atrib)
    {
      return $this->$atrib;
    }
}

$t=new test;

echo $t->privado;
?>

Aunque de esta forma, para qué queremos atributos privados ? Si bueno, podríamos leerlos todos, escribirlos no, aunque podemos hacer una pequeña implementación para tener un cierto control sobre qué atributos privados son visibles desde fuera:

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
<?php
class test
{
    private $privado;
    private $visible;
    private $oculto;
    private $atributos_visibles=array("privado", "visible");
    function test()
    {
      $this->privado="Variable privada";
      $this->visible="Atributo privado visible";
      $this->oculto="Atributo privado oculto";
    }  
   
    function __get($atrib)
    {
      if (in_array($atrib, $this->atributos_visibles))
        return $this->$atrib;
      else
        return false;
    }
}

$t=new test;

echo $t->privado."\n";
echo $t->visible."\n";
echo $t->oculto."\n";
?>

Obtendremos:

$ php getset.php
Variable privadaAtributo privado visible[gaspy@lytio blog]$ php getset.php
Variable privada
Atributo privado visible

De esta forma, podemos evitar errores en caso de atributos inexistentes, y evitar que los que no queremos no se puedan leer. Lo mismo podemos hacer con los setters:

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
<?php
class test
{
    private $privado;
    private $visible;
    private $oculto;
    private $atributos_visibles=array("privado", "visible");
    private $atributos_tocables=array("privado");
    function test()
    {
      $this->privado="Variable privada";
      $this->visible="Atributo privado visible";
      $this->oculto="Atributo privado oculto";
    }  
   
    function __get($atrib)
    {
      if (in_array($atrib, $this->atributos_visibles))
        return $this->$atrib;
      else
        return false;
    }

    function __set($atrib, $valor)
    {
      if (in_array($atrib, $this->atributos_tocables))
        $this->$atrib=$valor;
    }
}

$t=new test;

$t->privado="VALOR NUEVO DE PRIVADO";
$t->visible="VALOR NUEVO DE VISIBLE";
echo $t->privado."\n";
echo $t->visible."\n";
echo $t->oculto."\n";
?>

Por otra parte, si deseamos filtrar la entrada de esos atributos, es decir, que por ejemplo, privado deba ser un número entre 0 y 10, debemos implementarlo dentro de __set (con un switch por ejemplo, o comprobar si es un valor que debemos filtrar, entonces llamamos a una función que verifique su valor).

Visita otras webs de la red