viernes, 25 de julio de 2014

Habilitar las librerías de cifrado de PHP en Ubuntu

Para cifrar (encriptar no existe para la RAE, aunque muchas veces utilicemos ambos verbos como sinónimos) un bloque de datos, en PHP podemos utilizar la función mcrypt_encrypt

Fig. 1. Parámetros de mcrypt_encrypt

El primer parámetro de esta función hace referencia al algoritmo que emplearemos. Pero, ¿qué algoritmos podemos utilizar? Para ver los que hay disponibles en nuestro sistema, podemos utilizar la función mcrypt_list_algorithms. Por ejemplo, así:

 1 <?php
 2 echo "<pre>" . print_r (mcrypt_list_algorithms (), TRUE) . "</pre>";
 3 ?>
Listado 1. ¿Qué algoritmos puedo utilizar para cifrar mis datos?

He probado esto en Windows y la salida ha sido la siguiente:

Figura 2. ¡Hala, qué variedad para elegir! Pito, pito, gorgorito...

Pero, al probar lo mismo en Ubuntu, la salida ha sido...


...




¡absolutamente nada!


Pero... ¿qué está pasando?????


Fig. 2. WTF!!!!!?????

Vale. Tras un poco de surfeo web, parece ser que hay que hacer una receta de 3 pasos:

1) Instalar php5-mcrypt
2) Reiniciar el servidor web
3) Habilitar la extensión mcrypt

Si sabéis hacer esto, podéis dejar de leer ya. Si eres como yo, que no sabía cómo se hacía, aquí están los detalles:

1) Instalar php5-mcrypt

$ sudo apt-get install php5-mcrypt

Como podemos deducir del nombre, hemos de disponer de la versión 5 o superior de PHP. ¿Que cómo sabemos cuál tenemos? Pues así:

$ php -v

Si no tienes la 5 o superior, actualízala (si puedes).


2) Reiniciar Apache

Tienes varias formas. Por ejemplo, así

$ sudo /etc/init.d/apache2 restart

o bien

$ sudo service apache2 restart

Tras esto, aún seguimos sin poder obtener los algoritmos de cifrado ("cifradores" los llama la documentación oficial de PHP) disponibles.


3) Habilitar la extensión en el fichero php.ini

Para ello, se incluye la línea

extension = mcrypt.so

en el fichero de configuración de PHP, el famoso php.ini.

Y ahora ya... ¡sí! Al ejecutar en Ubuntu el script de antes (Listado 1) obtenemos la salida

Figura 3. La misma lista de "cifradores" que en Windows, aunque cambie el orden de algunos elementos

Hala, ya podéis darle un buen uso a las funciones de cifrado.

viernes, 18 de julio de 2014

Cuánto te mide, cariño (Un Programador Honesto e Inteligente [y guapo, sobre todo guapo]) - Parte 4 de 4

(continúa)

PARTE 4 DE 4 (¡POR FIN!)

¿Deberíamos contar las líneas en blanco en un programa como "líneas de código"? ¿Y los comentarios? A priori, todo parece indicar que no. Imaginemos que mi jefe mide mi productividad por el total bruto de líneas de código, incluyendo las líneas en blanco y los comentarios (por fortuna, un jefe que sabe lo que se hace no lo haría sólo así, es una medida muy chapucera). Entonces yo podría insertar deliberadamente líneas en blanco a troche y moche y comentarios innecesarios cada dos por tres con cualquier excusa, "para aumentar la legibilidad" (e intentar conservar mi trabajo hasta que detecten el "truco"). Esto da un argumento a favor de no contar las líneas en blanco ni los comentarios. Así, metas más o menos, da igual. Sólo cuenta el CÓDIGO DE VERDAD.

Sin embargo, es verdad que un par de líneas en blanco insertadas en lugares estratégicos pueden aumentar la legibilidad y comprensibilidad de una rutina, mientras que un código al que le falten esas líneas en blanco o unos comentarios puede ser bastante más difícil de comprender. Respecto a los comentarios, pasa tres cuartos de lo mismo. Bien usados, son un mecanismo útil. Mal usados (abusados, generalmente), son un problema: aumentan la cantidad de lectura, pueden quedar desfasados respecto al código... El debate es antiguo y ha dado (y dará) para ríos de tinta. McConnell lo plantea como una pequeña escenificación parodiando las obras de teatro griegas y los diálogos de Sócrates, en el capítulo 32 de Code Complete (punto 32.2 To Comment or Not To Comment). Es una lectura que os recomiendo, al menos está escrita de una manera "gracioseta".


Figura 1. Un libro sobre desarrollo de software + unos cuantos chistes malo-buenos

En cualquier caso, como decía en la entrada anterior, la utilidad o no de medir estas líneas en blanco y comentarios DEPENDE DEL OBJETIVO. En mi caso, quiero medir MIS proyectos. Es decir, YO soy el medidor y YO soy el padre de la criatura a medir. Por lo tanto, como no me quiero engañar a mí mismo, asumo que el programador que ha creado ese código, aparte de ser guapo a rabiar, tiene dos características importantes para conmigo: es honesto y es inteligente (hola, autoestima, ya sabía yo que no tardarías en salir).


Figura 2. Así se me pone la cara pensando si contar o no las líneas en blanco. Lo sé, me pongo un poco raro cuando pienso, y la Angelina me mira que me quiere comer 

1) Con lo de ser honesto, quiero decir que no va a insertar más líneas en blanco de las que suele insertar en su estilo normal de programación. Tampoco va a meter comentarios de relleno, más allá de los que suele meter habitualmente. Es decir, en los proyectos usa las líneas en blanco y los comentarios como elementos que también forman parte del programa, en su justa medida, como suele hacerlo habitualmente en el resto de los proyectos. Es decir, no va a engañar, ni (mucho menos), a engañarse.

2) Inteligente significa que no abusa de los comentarios, no mete paja... En fin, que los usa bien. Por lo tanto, unos buenos comentarios para mí tienen tanto valor como unas líneas de código. Aquí radica la clave de mi discurso. Para mí, esos comentarios útiles SON PRODUCTIVOS. Incluso esas líneas en blanco. Luego, si al sacar las métricas del proyecto no los tengo en cuenta, estoy descartando un producto de interés. Es verdad que esas líneas no son de interés para el compilador, pero sí son de interés para otro programador, o para mi YO del futuro cuando vuelva a leer ese trozo de código dentro de unos meses. Por lo tanto, esos comentarios (y líneas en blanco correctamente utilizadas) que mejoran la legibilidad y comprensibilidad del código, se deben contar. Aportan valor al código fuente.

Esto, además, tiene el efecto colateral de que simplifica mucho la tarea de contar las líneas de código de mi proyecto. Se limita a contar las líneas que tiene cada fichero de código. Hacer un pequeño programa para esto es trivial. Aunque esto es un efecto secundario, nunca el motivo principal para no excluir esas líneas en blanco y esos comentarios.

Bueno, creo que con esto ya me he explicado lo suficiente. Quizás me he enrollado un poco de más, pero necesitaba dejar esto claro para explicar mis siguientes entradas, en las que llevaré esto de las métricas a un caso práctico, y quería justificar un poco las decisiones tomadas.

Prometo que en la próxima entrada pondré código, que hace tiempo que no se ve por aquí y eso no puede ser.

---
Enlace a la parte 1
http://cosicasdeinformatica.blogspot.com.es/2014/07/cuanto-te-mide-carino-el-proyecto-se.html

Enlace a la parte 2
http://cosicasdeinformatica.blogspot.com.es/2014/07/cuanto-te-mide-carino-no-cuentes-lineas.html

Enlace a la parte 3
http://cosicasdeinformatica.blogspot.com.es/2014/07/cuanto-te-mide-carino-o-tanto-medir-pa.html

martes, 15 de julio de 2014

Cuánto te mide, cariño (o Tanto medir, pa qué) - Parte 3 de 4

(continúa)

PARTE 3 DE 4

Enlace a la parte 1
Enlace a la parte 2

En mi caso, creo que el número de líneas de código, aún con todos sus defectos asociados, es la métrica MÍNIMA IMPRESCINDIBLE que debería incluirse en todo conjunto de métricas de un proyecto. Esto no quiere decir que sea la única que haya que considerar, esta métrica deberá estar complementada y apoyada por algunas otras (tampoco muchas, repito lo de "pocas, pero buenas").

Pero si alguien me dice que no tiene ni idea de las líneas de código del proyecto en el que se está moviendo, algo va mal. Es como si un arquitecto me dijera que está trabajando en un puente y no sabe de cuántos metros es (claro está, redondeando, no le voy a exigir saberlo al milímetro). Yo mismo, en mis primeros años como programador profesional, muchas veces he trabajado en proyectos de los que luego no he sabido describir su tamaño con una medida objetiva. Y no, no me valen cosas como "un proyecto grande", "un proyecto mediano". Eso no me parece propio de un ingeniero. Como ingeniero, te pido que me des algún dato OBJETIVO del proyecto. El número de líneas de código será un dato muy básico, de utilidad muy limitada, pero es OBJETIVO. Todas las métricas han de ser objetivas.



¿Cuáles son mis objetivos al medir el tamaño de mi proyecto?

1. Conocer algún DATO OBJETIVO de él, que pueda ser medido por un tercero sin influencia de factores subjetivos. El número de líneas de código lo es. Da igual que lo mida yo o que lo mida un revisor externo. Otra cosa es que establezcamos condiciones que sean las mismas para todos: si cuentan las líneas de comentario, si cuentan las líneas en blanco, los tipos de archivos que consideraremos (código fuente, ficheros de configuración, páginas HTML estáticas...) y todos los demás detalles. Normalmente, estos dos tipos de líneas, las blancas y las de comentarios, no se suelen contar, aunque yo tengo un criterio diferente en algunos casos, pero de momento no me quiero ir por las ramas. Lo importante es que los criterios estén bien fijados; una vez hecho, la métrica es un valor objetivo.

2. Poder COMPARAR dos proyectos (o más). Al menos, dos proyectos realizados por el mismo programador. Ya he hablado anteriormente de que diferentes programadores significa diferentes estilos de programación, y el mismo programa puede cambiar de "tamaño" según las manos por las que pase. Pero si lo que quiero es comparar dos programas hechos por la misma persona, entonces sí que significa algo el número de líneas de código. O si quiero medir la productividad de un programador a lo largo del tiempo, sí tiene sentido comparar el número de líneas de código que ha producido en diferentes semanas.

3. GESTIONAR LA COMPLEJIDAD, intentando detectar, por ejemplo, variaciones bruscas en el tamaño del proyecto. O intentando reducir el tamaño cuando sea posible sin menoscabo de la funcionalidad (por ejemplo, por hacer una refactorización). Si un lunes extraigo una métrica del proyecto y veo que se mueve por las 50.000 líneas, y al lunes siguiente el proyecto ha pasado a 60.000 líneas, algo significa, ¿no? Habrá que entrar luego en detalles, pero al menos podemos tener un sistema automatizado que nos haga saltar un aviso para después ponernos a bucear en los pormenores del proyecto de manera más refinada. Otro ejemplo: si voy a acometer una fase de refactorización de mi proyecto, sí tiene sentido medir las líneas de código antes y después de la operación, para evaluar de alguna manera de qué nos ha valido (también tendrá otros beneficios aparte de reducir el número de líneas, claro, como una mejor organización del código, una mayor legibilidad, simplificación de uso, etc.).

Curiosamente, cuando he empezado a medir mis proyectos con estos tres únicos objetivos, resulta que después las métricas me han servido para otras cosas. Una vez que tienes datos objetivos, se te ocurren nuevas formas de dotarlos de significado y hacer cosas interesantes con ellos. Es lo que decía al principio: pocas métricas, pero explotándolas a tope.


--
Enlace a la parte 1
Enlace a la parte 2


viernes, 11 de julio de 2014

Cuánto te mide, cariño (no cuentes líneas, cuenta líneas) - Parte 2 de 4

Una de las medidas más básicas del tamaño de un proyecto es contar el número de líneas de código.

Como principal ventaja, tiene que es una medida de las más sencillas de obtener, pero tiene muuuuuuuchos inconvenientes. Algunos de ellos son que no se pueden contar las líneas de aquellos artefactos del proyecto que no se corresponden directamente con texto, como ficheros binarios. Por ejemplo, elaborar un informe en Crystal Report conlleva una cantidad de trabajo y tiempo cuya productividad no se puede cuantificar en líneas de código, ya que este informe es un fichero binario. O elaborar unas plantillas RTF que luego se rellenarán con datos. Aunque el RTF resultante sea texto, probablemente, el número de líneas variará mucho si se elabora con un editor como Word o con el LibreOffice o con el WorPad, ya que el salto de línea probablemente se insertará de manera diferente. Y también variará mucho si se inserta una imagen, que quedará codificada como un chorizo gigante de texto (binario codificado en hexadecimal) incomprensible y que computaría probablemente como una única línea de texto. 

Otro inconveniente importante es que el número de líneas de código es muy dependiente del estilo de programación, es "marca de la casa" del programador. Dos programadores pueden formatear el mismo programa de diferente manera, pueden incluir muchos o pocos comentarios, usar diferentes convenciones para colocar los delimitadores de bloques (llaves {}, palabras clave "begin", "end", "case", "default", y similares), diferentes estilos de sangrado, embellecer el código con más o menos líneas en blanco... 

Y es que ya lo sabemos: todo programador lleva un artista dentro, y no puede evitar que ese artista se le cuele por entre las líneas que teclea y se refleje en el código que produce.

Test para programadores: ¿cuántas líneas de código hay aquí? ¿Pero quién ha programado esto?

Así pues, ¿vale la métrica de líneas de código para medir el esfuerzo de generar esos artefactos binarios, o para medir el tamaño de dos programas escritos con estilos muy diferentes? No, desde luego que no.

Y, sin embargo...

Y sin embargo, los mismos autores que explican por qué no vale el número de líneas de código, cuando cuentan experiencias personales suelen hablar de "...cuando trabajé en un proyecto de 400.000 líneas de código...". Pero bueno, ¿en qué quedamos?

En Code Complete, uno de mis libros preferidos sobre desarrollo de software, Steve McConnell habla varias veces de las líneas de código de un programa cuando quiere dar una idea acerca de su complejidad o tamaño.

En el capítulo 8, hablando de un programa insignificante, de esos que casi seguro que nadie conoce, llamado Microsoft Word (no os suena, ¿verdad?), McConnell dice

"...la aplicación es tan compleja (millones de líneas de código) y ha pasado
 por tantas generaciones..."

Como veis, el autor asume que el número de líneas de código de alguna manera le da al lector una idea de la complejidad de la aplicación. También habla constantemente del número de líneas de código de rutinas para hacer referencia a su complejidad. En el capítulo 11 dice

"...a mediados de 2003 trabajé con un cliente que tenía cientos de miles de 
líneas de código escritas en RPG..."

Y en el capítulo 13, hablando de modularidad,

"...La esencia de la creación de programas mayores que unos cientos 
de líneas de código es la gestión de la complejidad..."

Los ejemplos se repiten, en este y en muchos otros libros, artículos, ponencias, etc, así que no seguiré.

Por supuesto, McConnell es sobradamente consciente de las limitaciones de la métrica de las líneas de código. Pero como vemos, en cierto modo, aunque las líneas de código no sean una medida buena si se considera de manera aislada, tampoco son una medida del todo inútil. De hecho, muchas veces es la única métrica que se cita cuando no hay tiempo para entrar en más detalles. El autor habla como si esa medida, con todos sus inconvenientes, significara algo. ¿Lo significa?

Lo significa.

Y lo sabes (como diría Julito).

O al menos, lo significa para algunos objetivos, y tomándola siempre con las debidas reservas.

(continuará)
--
Enlace a la parte 1.

miércoles, 9 de julio de 2014

Cuánto te mide, cariño (el proyecto, se entiende) - Parte 1 de 4

Un principio básico de cualquier ingeniería es MEDIR (diría incluso que es importante en muchos otros aspectos de la vida, pero no quiero profundizar, que enseguida os da por pensar en lo mismo, golfos). Así pues, medir también es importante en la Ingeniería del Software, pero ¿Cómo mido mi proyecto? ¿Cómo puedo evaluar su tamaño, la productividad del equipo de desarrollo, el esfuerzo? ¿Cómo puedo hacer predicciones basándome en el tamaño? ¿En qué tamaño? Mejor aún, ¿qué es el tamaño, cómo se mide el tamaño?

Medir, medir, medir... ¡Estáis obsesionados!

La teoría sobre las métricas es muy amplia y daría lugar a varios blogs y libros sobre ello. De hecho, existen, podéis buscarlos si estáis interesados (o pinchar aquí si sois muy comodones). Diversos autores han definido literalmente cientos, si no miles, de métricas, ya sea genéricas o específicas, por ejemplo, para sistemas orientados a objetos, para aplicaciones funcionales, de gestión, métricas de calidad, de acoplamiento, de dependencia, de diseño, de programación, de arquitectura, etc...

Sin embargo, es preferible tener un conjunto pequeño de métricas, y sacarles todo el partido posible, que hacer unos informes cojonudos, llenos de gráficas y colorines, con miles de parámetros medidos, y que luego no se tengan en cuenta esos valores calculados para nada. Por eso, métricas sí, pero teniendo claro el objetivo de esas métricas y las acciones a las que van a dar lugar. Es decir, saber cuál es el objetivo de las métricas.

¿Y tú, cómo mides tus proyectos? ¿Qué medidas has encontrado que te son las más útiles durante el desarrollo de tus proyectos? ¿Cuál es el objetivo de esas medidas, para qué las tomas?

(continuará)

miércoles, 11 de junio de 2014

¿Qué día me dijiste que teníamos la reunión? (Manejo de fechas en SQLite3)

Como dicen en la propia documentación de SQLite, en SQLite3 no existe el tipo de datos fecha.

Cito directamente de http://www.sqlite.org/datatype3.html


1.2 Date and Time Datatype

SQLite does not have a storage class set aside for storing dates and/or times. Instead, the built-in Date And Time Functions of SQLite are capable of storing dates and times as TEXT, REAL, or INTEGER values:

    TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
    REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.
    INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.

Applications can chose to store dates and times in any of these formats and freely convert between formats using the built-in date and time functions.

Así que lo más conveniente es declarar el tipo de ese campo como TEXT (o números, también vale), almacenar las fechas en el formato ISO8601 (básicamente: 'YYYY-MM-DD HH:MM:SS'), así además se puede ordenar por ese campo simplemente ordenando como texto, y utilizar las funciones de fecha de SQLite3 para procesarlas.

Por ejemplo, para hacer una comparación:

 1 select * from tabla where julianday(f1) > julianday('2014-01-01 00:00:00')


 

UN EJEMPLO PRÁCTICO


Bien, hasta aquí la teoría. Vamos a probarlo. Para ello, voy a utilizar SQLite Expert Personal, donde he creado una base de datos y dentro de ella crearé una tabla con un campo fecha.

1. Creamos la tabla

 1 CREATE TABLE PERSONAS
 2 (
 3   ID         NUMBER(10)  NOT NULL,
 4   NOMBRE     VARCHAR(30),
 5   APE1       VARCHAR(30),
 6   APE2       VARCHAR(30),
 7   FNACIM     DATETEXT  
 8 );

El tipo de dato DATETEXT (línea 7) se corresponde internamente en SQLite Expert con WideString, pero en realidad debería valer cualquier tipo de datos de texto.

2. Insertamos unos cuantos datos de ejemplo

 1 insert into PERSONAS(ID, NOMBRE, APE1, APE2, FNACIM) values (1, 'MARIANO', 'RAJOY', 'ZAPATERO', '1965-05-20');
 2 insert into PERSONAS(ID, NOMBRE, APE1, APE2, FNACIM) values (2, 'JOSE LUIS', 'RAJOY', 'ZAPATERO', '1970-06-20');
 3 insert into PERSONAS(ID, NOMBRE, APE1, APE2, FNACIM) values (3, 'PETER', 'SCHWARZENEGGER', NULL, '1973-08-30');
 4 insert into PERSONAS(ID, NOMBRE, APE1, APE2, FNACIM) values (4, 'ARNOLD', 'LANDA', 'CLARK', '1982-08-30');

Antes de consultar nada, comprobamos que los datos se han insertado bien, yéndonos a la pestaña "Data" de SQLite Expert
Fig. 1. Los datos. Cuántos conocidos por aquí.


3. Hacemos una consulta 

En ésta, utilizamos la función "julianday" para comparar fechas

 1 SELECT * FROM PERSONAS WHERE julianday(FNACIM) > julianday('1970-07-01')


El resultado:
Fig. 2. Resultado de la consulta. Los más jovencitos del grupo


Bueno, parece que todo ha ido bien.

Además de juliandate, SQLite incorpora otras cuatro funciones para trabajar con fechas: date, time, datetime y strftime. Os recomiendo la lectura de la página donde se describen (enlace al final).

Una vez que se sabe esta forma de trabajar con las fechas en SQLite3, la cuestión parece una tontería, pero el hecho de que SQLite no tuviera un tipo de dato nativo para las fechas me ha hecho perder un buen rato. Espero que no le pase a quien lea esto.

¿Y tú, te has peleado con fechas en SQLite?

Más info:

SQLite. http://www.sqlite.org/

Funciones de fecha en SQLite. http://www.sqlite.org/lang_datefunc.html

SQLite Expert Personal. Un estupendo gestor de bases de datos SQLite. http://www.sqliteexpert.com/download.html

jueves, 5 de junio de 2014

Recorrer un directorio en PHP procesando los ficheros en su interior

Vamos a ver un pequeño ejercicio en el que recorreremos un directorio contando cuántos ficheros hay colgando de él, incluyendo los de sus subdirectorios. Esto es un paso hacia una herramienta un poco más ambiciosa. Pero empecemos por el primer paso...


1. Funciones de Directorios en PHP

Hay tres funciones que son claves para recorrer un directorio con PHP.

La primera, opendir, toma el nombre del directorio a leer (sin la barra del final) y devuelve un identificador del directorio, que se podrá usar con las otras funciones. Llamada:

    $dir = opendir($path)

La segunda, readdir, va devolviendo en sucesivas llamadas los nombres de las entradas contenidas en el directorio. Normalmente, esto se utiliza en un bucle de la forma

    while ($elemento = readdir($dir)){
        ...procesar
    }

Hay que tener cuidado con los dos directorios especiales "punto" (actual) y "punto punto" (superior), más conocidos como "." y "..". Normalmente, al procesar los elementos del directorio se controla con un if si el elemento a tratar no es ninguno de estos dos. Algo así:

    $dir = opendir($path)
    while ($elemento = readdir($dir)){
        if( $elemento != "." && $elemento != ".."){
            ... procesar
        }   
    }

Por último, para diferenciar si el elemento a tratar es un fichero o es un subdirectorio, tenemos la función is_dir. En caso de que sea un subdirectorio al que queramos aplicar el mismo tratamiento que al actual, podemos hacer una llamada recursiva a la misma función (que aquí llamaremos analizar_directorio).


2. Todo Junto

Pongámoslo ahora todo junto, en una función que se limita a contar los ficheros contenidos en el directorio inicial y los subdirectorios que hay dentro, recorridos de manera recursiva (¡ojo, cuidado con la recursividad). Más adelante haremos cosas más interesantes que contar ficheros. Para probarlo todo, guardaremos el siguiente listado como index.php:

 1 <html>
 2 <head>
 3     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 4 </head>
 5 
 6 <body>
 7 <?php
 8     $path = "../../rips";
 9     $total_ficheros = analizar_directorio($path);
10     echo "Hay $total_ficheros ficheros en el directorio $path<br>";
11     
12 //------------------------------------------------------------- 
13 function analizar_directorio($path) {
14     $total_ficheros = 0;
15     $dir = opendir($path);
16     while ($elemento = readdir($dir)){
17         if( $elemento != "." && $elemento != ".."){
18             // Si es una carpeta
19             if( is_dir($path."/".$elemento) ){
20                 // Muestro la carpeta
21                 echo("Procesando subdirectorio: ". $elemento . "<br>");
22                 $total_ficheros += analizar_directorio($path."/".$elemento);
23             // Si es un fichero
24             } else {
25                 $total_ficheros++;
26             }
27         }
28     }
29     return $total_ficheros;
30 }
31 
32 ?>


El resultado en el navegador:


Referencias sobre las tres funciones

http://www.php.net/manual/es/function.opendir.php
https://php.net/manual/es/function.readdir.php
https://php.net/manual/es/function.is-dir.php

martes, 3 de junio de 2014

Configurar Apache con PHP en Ubuntu Linux

Guía breve, breve, brevísima, para recordar los pasos que he dado para la instalación, pero sin muchas explicaciones.

1. Instalar Apache

$ sudo apt-get install apache2

2. Instalar PHP, versión 5 (PHP5)

$ sudo apt-get install php5

$ sudo apt-get install libapache2-mod-php5


3. Habilitar el módulo de PHP5 en Apache

$ sudo a2enmod php5


Y ya podemos probarlo con un sencillo fichero de prueba, por ejemplo:

Fichero index.php:

 1     <HTML> 
 2     <H1>Probando PHP</H1>
 3     Salida del comando phpinfo:
 4     <?php
 5         phpinfo();
 6     ?>
 7     </HTML>
Listado 1. El HTML no es perfectamente ortodoxo, pero sólo es una prueba

¡Ojo! En la línea 4 del anterior código, la instrucción de apertura del código PHP, es decir
   
    <?php

    en teoría también debería funcionar si se omiten las letras "php", es decir
   
    <?
   
Bueno, pues resulta que esto sí que me ha funcionado en Apache2 sobre Windows XP, pero en Ubuntu me ha tenido un ratico dándole vueltas a la cabeza, pues no funcionaba, y me mostraba, en vez de la salida de la función phpinfo(), el texto hasta la línea 3, y el resto de la página en blanco. Es decir, como si no interpretara la función phpinfo(), e ignorara todo lo situado entre las etiquetas "<?" y "?>". Al final se ha arreglado cuando a la etiqueta de apertura le he añadido esas tres letras, dejándola así: "<?php" (sin las comillas, claro). Así que cuidado con este detalle, pues os puede hacer creer que PHP no está funcionando cuando en realidad sí que está bien instalado.

Directorios de interés
Fichero de configuración de Apache2
/etc/apache2/apache2.conf

Directorio por defecto para publicación de contenidos
/var/www/html

Más info
http://doc.ubuntu-es.org/HTTPD_Servidor_web_Apache2
Bien explicada, con muchísimos detalles y sin molestos banners publicitarios.

viernes, 30 de mayo de 2014

Leer ficheros, contar el número de líneas y procesarlas

¿Os gusta la lectura? A mí me encanta, uno de mis géneros preferidos es la ciencia ficción. Pero uno no siempre puede leer lo que quiere, y en ocasiones hay que leer cosas que no son tan entretenidas como una buena novela. Por ejemplo, programando, a veces tenemos que leer un fichero de texto línea a línea. (Vale, es un chiste muuuuyyyyy malo, pero al menos es corto ;-)

Bueno, ahora en serio, lo de leer el fichero lo podemos hacer como mínimo de dos formas:

1) Si no nos interesa todo el contenido del fichero, sino que únicamente estamos buscando las líneas que cumplan una determinada condición, podemos ir leyendo línea a línea y procesar esas líneas individualmente. Para ello, abrimos el fichero (fopen) y en un bucle vamos leyendo cada línea (fgets). Esto nos da control sobre cada línea individualmente, y no consume demasiada memoria, ya que una vez procesada la línea la podemos descartar (también la podemos almacenar si nos interesa, claro).

2) Si queremos todo el contenido del fichero de golpe, por ejemplo, en un array de líneas, con PHP podemos usar la función "file" que nos devuelve precisamente eso. Lógicamente, esta segunda opción ocupará más memoria, lo cual puede ser importante si el fichero leído tiene un tamaño grande, aunque me imagino que posiblemente sea una forma más óptima en tiempo, leerlo todo de un golpe. Ya sabéis, el eterno dilema de memoria frente al tiempo. Si después queremos analizar esas líneas leídas y almacenadas en el array, tendremos que hacer un bucle para recorrerlas.

Bien, ¿y qué técnica me conviene? Pues como siempre, depende de lo que quieras hacer. En un primer caso, para ilustrar ambas técnicas, mi objetivo va a ser contar el número de líneas del archivo, sin procesar cada línea individualmente. Os dejo aquí dos funciones en PHP (contar1 y contar2) que ilustran ambos métodos, aunque fácilmente se pueden traducir a cualquier otro lenguaje.

Según lo explicado en el caso 1)

 1 //-------------------------------------------------------------
 2 function contar1($filename) {
 3     $file = fopen($filename, "r");
 4     $num_lineas = 0;
 5     while (!feof($file)) {
 6         if ($line = fgets($file)){
 7            $num_lineas++;
 8         }
 9     }
10     fclose($file);
11     return $num_lineas;
12 }

Y para el caso 2), la función "count" nos da el número de elementos de un array, lo que en este caso coincide con el número de líneas del fichero

 1 function contar2($filename) {
 2     $num_lineas = count(file($filename));
 3     return $num_lineas;
 4 }



Rendimiento de cada opción

Para analizar el rendimiento de ambas opciones, he hecho pruebas contando el número de líneas con un grupo de unos 2.000 ficheros aproximadamente que tengo en un directorio, una aplicación web. He limitado la lectura a ficheros de código fuente en Javascript, PHP, CSS y HTML, con una longitud media de 316 líneas por fichero, aunque esta medida tiene una varianza alta, pues el fichero más largo tiene 30.000 líneas (no es un caso frecuente), y el fichero más pequeño está vacío (cero líneas).

Tras ocho o diez ejecuciones, contando las líneas por el método 1) tardo alrededor de 1.50 segundos, mientras que el método 2) está sobre los 1.25 segundos, es decir, un 17% más rápido. No he hecho pruebas de consumo de memoria RAM, pero supongo que cuando se cargó el fichero de 30.000 líneas en memoria (método 2), mi ordenador debió emitir una pequeña queja, aunque creo que nada preocupante para los estándares de memoria que puede tener un ordenador hoy en día. Claro, esto puede ser muy diferente si esta aplicación la va a ejecutar un único usuario o la van a utilizar varios usuarios a la vez sobre el mismo servidor web.

En mi caso, la diferencia entre ambas técnicas no es significativa, y sin embargo el método 1) me da mucha más flexibilidad para un objetivo que tengo en mente, pues me gustaría hacer algo de procesamiento con cada línea conforme las voy leyendo.

Pero esta entrada ya me está quedando demasiado larga, así que ya hablaré de ello en otra ocasión, y también pondré el código utilizado para el test, con las explicaciones pertinentes.

¿Y tú, sueles enfrentarte al problema de procesar ficheros línea a línea habitualmente? ¿Utilizas alguna de las técnicas de las que hablo aquí o tienes otra forma de hacerlo?

Referencias
La función file es quizás la más interesante de las aquí mencionadas.

lunes, 19 de mayo de 2014

María Jesús y su acordeón (o cómo aprovechar mejor la interfaz de usuario)


Habréis observado que muchas aplicaciones y páginas web, en particular en su versión para teléfonos móviles, organizan la información de una forma muy útil, que consiste en agrupar secciones de información bajo un título, de manera que cada uno de esos bloques se puede expandir o contraer. Eso permite aprovechar mejor la interfaz de usuario y agiliza la organización de la información en pantalla. Este tipo de interfaz se denomina "acordeón", por el hecho de que cada sección se puede expandir y contraer como el cuerpo de dicho instrumento.

Fig. 1. Las secciones del acordeón contienen info "en su interior"

Al desplegar la sección de Historia

Fig. 2.Al desplegar una sección, el icono cambia

En la documentación de jQuery sobre los "acordeones" [http://jqueryui.com/accordion/]se describe en detalle cómo utilizar este tipo de interfaz, pero aquí os dejo una brevísima introducción para que en un minuto podáis tener algo así funcionando con tres sencillos pasos:

1) Como siempre, crear una página e incluir en ella la referencia a jQuery

 1 <head>
 2 ...
 3     <link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
 4     <script src="//code.jquery.com/jquery-1.10.2.js"></script>
 5     <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
 6 ...
 7 </head>

2) Crear una división (DIV) que contendrá todas las secciones del acordeón. Cada sección ha de ir precedida por una etiqueta de cabecera (H1, H2... H6). Si hacéis pruebas, veréis que da igual usar H1 que H2 que H3... e incluso se pueden mezclar indistintamente, que jQuery las usará como títulos de las secciones.

 1 <body>
 2 ...
 3 <div id="bloque_acordeon">
 4   <h1>Sección 1. Mis personas preferidas</h1>
 5     <div>
 6     <p>
 7     Esto está dentro del bloque1
 8         <ul>
 9             <li>Claudia Chífer</li>
10             <li>Mariano Gandhi</li>
11             <li>Jason Voorhees</li>
12         </ul>
13     </div>
14 
15   <h1>Sección 2. Mis animales preferidos</h1>
16     <div>
17     <p>
18     Esto está dentro del bloque2
19         <ul>
20             <li>Lassie</li>
21             <li>El pollo a la brasa</li>
22             <li>Claudia Chífer</li>
23         </ul>
24     </div>
25     
26   <h1>Sección 3. Mis plantas preferidas</h1>
27     <div>
28     Esto está dentro del bloque3
29         <ul>
30             <li>El algarrobo mediterráneo</li>
31             <li>María</li>
32             <li>Claudia Chífer</li>
33         </ul>   
34     </div>
35     
36 ...
37 </body>

y 3) Incluir el código jQuery que hace que esta sección funcione como un acordeón. Una simple llamada a una función

 1   <script>
 2   $(function() {
 3     $("#bloque_acordeon" ).accordion();  
 4   });
 5   </script>


Hay un detalle que a mí me gusta, y es el hecho de que la primera sección se pueda cerrar sin tener que abrir ninguna otra. Para esto, basta con añadir dentro de la función "accordion" la propiedad "collapsible: true", quedando así el paso 3:

 1   <script>
 2   $(function() {
 3     $("#bloque_acordeon" ).accordion(
 4         { collapsible: true }
 5     );
 6   });
 7   </script>

Pues aquí está todo junto en esta plantilla que podéis adaptar a vuestras necesidades:

 1 <html>
 2 <head>
 3     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 4     <title>Ejemplo de un acordeón con jQuery</title>
 5     <link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
 6     <script src="//code.jquery.com/jquery-1.10.2.js"></script>
 7     <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
 8   <script>
 9   $(function() {
10     $("#bloque_acordeon" ).accordion(
11         { collapsible: true }
12     );
13   });
14   </script>
15   
16 </head>
17 
18 <body>
19 Organizar la interfaz de usuario con un "acordeón"
20 <div id="bloque_acordeon">
21     <h1>Mis personas favoritas</h1>
22     <div>
23         Esto está dentro del bloque1
24         <ul>
25             <li>Claudia Chífer</li>
26             <li>Mariano Gandhi</li>
27             <li>Jason Voorhees</li>
28         </ul>
29     </div>
30     
31     <h1>Mis animales favoritos</h1>
32     <div>
33         Esto está dentro del bloque2
34         <ul>
35             <li>Lassie</li>
36             <li>El pollo a la brasa</li>
37             <li>Claudia Chífer</li>
38         </ul>
39     </div>
40     
41         <h1>Mis plantas favoritas</h1>
42     </span>
43     <div id="contenido_bloque3" style='display: none'>
44         Esto está dentro del bloque3
45         <ul>
46             <li>El algarrobo mediterráneo</li>
47             <li>María</li>
48             <li>Claudia Chífer</li>
49         </ul>       
50     </div>
51 </div>
52  
53 </body>
54 </html>

Related Posts Plugin for WordPress, Blogger...