Mostrando entradas con la etiqueta desarrollo. Mostrar todas las entradas
Mostrando entradas con la etiqueta desarrollo. Mostrar todas las entradas

jueves, 23 de junio de 2016

Sesión de galletitas y galletitas de sesiones

Ayer me surgió un problemilla relacionado con sesiones y cookies, y algún pequeño misterio (aún) sin resolver. A ver si consigo explicar un poco el tema de las cookies y las sesiones para mi yo del futuro, y a ver también si alguien me puede dar una pista acerca del misterio.

1. Sesiones

Una sesión es una forma de mantener el estado utilizando un protocolo como HTTP que, por construcción, no está pensado para mantener el estado. Normalmente, una sesión dura desde que el usuario abre el navegador hasta que lo cierra. El servidor web puede pasar información entre diferentes páginas durante la misma sesión. Cuando el navegador solicita la página (esa que va a trabajar con sesiones), el servidor web le asigna un identificador de sesión (SESSID), se lo envía al cliente y le pide que lo guarde "en algún sitio" (normalmente, en una cookie). Después, cada vez que el usuario haga una petición de página, el servidor web recibirá ese SESSID en una cookie (eso es lo habitual, aunque también puede enviarse en la propia URL de acceso). Conservando cierta información ligada al identificador de la sesión (en el servidor web), puede darse un servicio personalizado al usuario, como mantener un carrito de la compra, por ejemplo. Para mantener esta información, el desarrollador web puede almacenar determinadas variables (nombre:valor) en la sesión.

El servidor web guardará la información de la sesión en algún sitio, puede ser en ficheros de texto, binarios, en una base de datos... Normalmente, una configuración por defecto de Apache + PHP implica que se guarden en ficheros de texto plano.

Vale. Hasta aquí bien.

2. Cookies

Para guardar en el navegador del cliente el ID de sesión se utilizan cookies habitualmente. El servidor web le pide al navegador del usuario: "Anda, porfa, ¿puedes guardar por ahí en algún sitio que la variable <loquesea> almacene el valor <patatín-patatán>? Más adelante, cuando vuelvas, yo te pediré si tienes esta información guardada y, si la tienes, te reconoceré y sabré que eres tú, mi amor" (sí, los servidores web son así de ligones con los navegadores).

Los servidores pueden usar así esta información para "recordar" las preferencias del usuario, su login automático y un sinfín de cosas más útiles y beneficiosas para el usuario, y algunas otras que no son tan beneficiosas para el usuario (pero sí para ciertos sitios web, especialmente si venden publicidad o si tienen intenciones algo más siniestras), por ejemplo, para rastrear las preferencias y hábitos de navegación.

Los navegadores o, lo que es lo mismo, los usuarios, sabemos que si nos hacemos los estrechos la página no nos va a dar mucha funcionalidad, así que nos ponemos en modo facilón, nos dejamos querer y accedemos fácilmente a que el servidor web nos penetr meta esos datos sin excesivos reparos. (¿Cuántas veces has "Entendido" que un sitio web utiliza cookies y has consentido? Luego no vayamos con excusas, que así pasa lo que pasa).

El navegador guarda ese paquetito de información, esa cookie, en un fichero pequeño normalmente de texto (también pueden ser binarios) o, algo que se ve cada vez más en las últimas versiones de los navegadores, en bases de datos locales tipo SQLite o similares. En cualquier caso, ficheros en el ordenador del cliente web. O, al menos esto es así en teoría, ya que aquí me surge el primer misterio que mencionaba en la introducción. Pero antes de abordar el misterio, recapitulemos lo que llevamos dicho hasta ahora.


Resumiendo:

- Cookies: pequeños trozos de información que almacena el navegador en ficheros de texto, binarios o BD locales tipo SQLite. Se pueden usar para muchas cosas, una de ellas para almacenar ID de sesión (pero también para rastrear al usuario, conocer preferencias...)

- Sesiones: interacciones entre navegador y servidor web que recuerdan info (estado) del usuario, normalmente usando cookies. La información se almacena en el servidor, ya sea en ficheros de texto (pares nombre:valor), binarios, bases de datos...

3. Vale. ¿Y dónde se almacenan?

3.1 LAS COOKIES

Pues... depende del navegador. En el caso de Firefox, el directorio es el del perfil del usuario, como explican aquí

https://support.mozilla.org/es/kb/perfiles-el-lugar-donde-firefox-almacena-tus-contr

que se encuentra dentro de la carpeta %AppData%\Roaming\Mozilla\Firefox\Profiles

Si sólo tienes un perfil de usuario, éste incluye la palabra 'default' en el nombre de la carpeta. En mi caso:

%AppData%\Roaming\Mozilla\Firefox\Profiles\67bl3kpn.default-1443683694326

y, dentro de esta carpeta, hay un archivo cookies.sqlite


Fig. 1. Archivo SQLite de cookies en Firefox

El contenido de este archivo se puede ver con cualquier visualizador de ficheros SQLite. A mí me gusta mucho el SQLite Expert (edición Personal). Más adelante le echaremos un vistazo.

En el caso de Chrome, la ruta donde se almacena la BD de cookies es

%LOCALAPPDATA%\Google\Chrome\User Data\Default\Cookies

y el fichero se llama cookies a secas, sin extensión. También lo podemos abrir con SQLite Expert o cualquier otro visor.


Si echamos un vistazo a ambos ficheros, veremos cosas parecidas a esto en el caso de Firefox


Fig.2. Fichero de cookies en Firefox 47.0

y esto en el caso de Chrome



Fig.3. Fichero de cookies en Chrome

3.2 LAS SESIONES

La información de la sesión se almacena, como hemos dicho, en el servidor web. En el caso de Apache con PHP, que es el servidor que yo voy a utilizar en este caso, la ubicación de las variables de sesión se almacenan en el directorio que se especifique en php.ini, en el parámetro session.save_path. En mi caso, utilizando un paquete XAMPP integrado, la ruta es C:\xampp\tmp. 

 Fig.4. Configuración de la ruta donde guardar las sesiones

Si miramos en esa carpeta, veremos las sesiones que se han ido creando en los últimos días:




Fig.5. Contenido de la carpeta de almacenamiento de sesiones

4. ¿Me puedes poner un ejemplo?

Sí, será lo mejor. Todo esto puede ser un poco confuso, y la mejor forma de verlo claro es con un ejemplo. Haremos dos páginas PHP que se pasarán información de una a otra utilizando una sesión de usuario, e iremos viendo dónde, cómo y con qué contenido se van creando los ficheros.

Página 1


01 <?php
02 session_start();
03 ?>
04 <!DOCTYPE html>
05 <html lang="es">
06
07 <head>
08 <meta charset="utf-8" />
09 <title>Sesiones - Página 1</title>
10 </head>
11
12 <body>
13 <?php
14 echo 'Estamos en la sesión [' . session_id() . ']<br />'
15 . 'Nombre: ' . session_name() . '<br />';
16
17 //almacenamos algún dato en esa sesión
18 $_SESSION['mes'] = 'junio';
19 $_SESSION['usuario'] = 'pepe';
20 $_SESSION['flor'] = 'amapola';
21
22 echo '<pre>';
23 print_r($_SESSION);
24 echo '</pre>';
25 echo "<br>Ir a <a href='pagina2.php'>la página 2</a> a consultar las variables de sesión"
26
27 ?>
28
29 </body>
30 </html>



Y esta es la página 2


01 <?php
02 session_start();
03 ?>
04 <!DOCTYPE html>
05 <html lang="es">
06
07 <head>
08 <meta charset="utf-8" />
09 <title>Sesiones</title>
10 </head>
11
12 <body>
13 <?php
14 echo 'Estamos en la sesión [' . session_id() . ']<br />Nombre: ' . session_name() . '<br />';
15
16 //recuperamos los valores almacenados en la sesión
17 echo 'Recuperamos el valor mes=' . $_SESSION['mes'] . '<br />';
18 echo 'Recuperamos el valor usuario=' . $_SESSION['usuario'] . '<br />';
19 echo 'Recuperamos el valor flor=' . $_SESSION['flor'] . '<br />';
20
21 echo '<pre>';
22 print_r($_SESSION);
23 echo '</pre>';
24 ?>
25 </body>
26 </html>



Abramos en el navegador la página 1

 Fig. 6. Página 1, creando la sesión y almacenando algunas variables en ella.

Antes de pasar a la página 2, veamos qué ha pasado en los sistemas de archivos del servidor y del cliente.

En el servidor

Fig. 7. Fichero de sesión en el sistema de archivos del servidor web

como se ve, el nombre del archivo coincide con el session_id que hemos visto en la página. Si abrimos ese fichero, su contenido es:


Fig. 8. Contenido del fichero de sesión con las variables de la misma

Hmmm... Interesante. Vemos que junto a cada variable aparece un tipo de datos (s=string), su tamaño (5) y su valor ("junio"). Las distintas variables de sesión se separan con pipelines.


Pero es a la hora de ver qué ha pasado con las cookies en el cliente cuando aparece el primer "misterio". En teoría, las cookies se almacenan en la BD SQLite que hemos dicho. Pero, cuando muestro las cookies ordenadas por fecha de acceso, no encuentro la cookie de nombre PHPSESSID, que es el nombre que me devuelve la función session_name(). Esto es lo que consigo ver cuando accedo a la BD y filtro por el dominio 'localhost':

Fig. 9. Contenido del fichero de cookies para el dominio 'localhost' en Firefox. 
¿Y la cookie PHPSESSID?

Como tras muchos intentos no he conseguido encontrar esta información en la BD, al final he instalado el plugin Firebug en Firefox, que permite visualizar las cookies y ahí sí que puedo ver la cookie que me interesa, como se puede ver un poco más arriba en la figura 6. También si abro la página 2 con el Firebug activado (F12) puedo ver que la cookie de sesión PHPSESSID es la misma

Fig. 10. Página 2 mostrando la cookie de sesión y las variables asociadas, junto a sus valores

Aún no he conseguido averiguar dónde se almacena la cookie PHPSESSID, pero es obvio que el navegador la está guardando en algún sitio y a mí me gustaría saber dónde. Vale que con el Firebug puedo inspeccionar la cookie, lo cual me soluciona la papeleta por el momento, pero me quedo un poco mosca con no haber podido encontrar la ubicación exacta de la cookie en el disco.

¿Alguien tiene alguna idea?

martes, 10 de mayo de 2016

Estilos CSS alternativos

A veces nos puede interesar ofrecer dos páginas de estilos CSS diferentes para una página web. Por ejemplo, una versión normal y otra aumentando el contraste, para facilitar la accesibilidad de personas con problemas visuales. O simplemente por ofrecer dos temas diferentes al usuario, basados en gustos por determinados colores o fuentes, disposición de elementos en la página...

Veamos cómo hacer esto.

Definiremos dos hojas, estilo1.css y estilo2.css con los siguientes contenidos:

Fichero 1
/* estilo 1, normal */
body {
    font-family: verdana,helvetica;
    color: #0000FF; /* texto azul */
    background-color: #f8e8a0; /* fondo amarillo */
    font-size: 16px;
}


Fichero 2
/* estilo 2, alto contraste, letras grandes */
body {
    font-family: verdana,helvetica;
    color: #ffffff; /* texto blanco */
    background-color: #000000; /* fondo negro */
    font-size: 36px;
}


Y ahora hacemos nuestra página, tal que así

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>sin título</title>
<link href="estilo1.css" rel="stylesheet" type="text/css" title="Estilo 1">
<link href="estilo2.css" rel="stylesheet" type="text/css" title="Estilo 2">
</head>

<body>

<h1>Elija una de las siguientes opciones</h1>
<ol>
    <li>Opción primera</li>
    <li>Opción segunda</li>
    <li>Opción tercera</li>
</ol>
</body>

</html>


Si abrimos ahora la página en el navegador, la veremos con el primer estilo aplicado:



Fig 1. Página mostrada con el Estilo 1

Y en el menú Ver / Estilos podemos elegir cambiar a otro estilo

Fig 2. Elegir un estilo diferente en el navegador


Y veríamos el resultado que hemos definido de alto contraste y letras grandes, tal que así:

Fig 3. Página mostrada con el Estilo 2

ALGUNAS EXPLICACIONES

En los atributos "title" hemos puesto los valores "Estilo 1" y "Estilo 2". Si no hubiéramos definido el atributo "title" en alguno de los estilos esto significaría que el estilo es permanente. Esto significa que se aplica siempre, independientemente de otros estilos que se eligieran por el usuario. Si hay enlaces a varias páginas CSS sin "title", se aplicarían todas ellas.

Al incluir el atributo "title", lo que estamos haciendo es indicar que esos estilos son preferidos. Esto significa que se aplican por defecto (en nuestro caso, el "Estilo 1"), pero si el usuario selecciona otra(s) página(s) con título diferente, dejarían de aplicarse las primeras y pasarían a aplicarse todas las que tuvieran el otro estilo (en nuestro caso, el "Estilo 2"). Si dos o más páginas tienen el mismo título, entonces se aplican todas ellas al elegir el estilo correspondiente en el menú Ver del navegador.

Normalmente, hasta aquí suele ser suficiente. Pero el estándar HTML también define otro valor posible para el atributo "rel"

rel="alternate stylesheet"

Aunque no todos los navegadores implementan esto. Básicamente, está indicando que hay otros estilos alternativos, pero, al contrario que los estilos preferidos (que se aplican por defecto, al menos el primero de ellos), los estilos alternativos no se aplican por defecto, sino sólo en el caso de que el usuario lo seleccione explícitamente.

La verdad es que con utilizar estilos con títulos ya tendríamos un sistema de estilos alternativos, así que en general esta etiqueta me parece innecesaria para solucionar situaciones como la planteada al principio. Seguramente pueda idearse algún caso donde la diferencia sea significativa, pero en general no lo considero algo crítico, al menos para casos típicos.

Si queréis unas explicaciones más detalladas, echadle un vistazo a esta página, que está muy bien explicado todo esto.

miércoles, 2 de diciembre de 2015

Visto y no visto: una parte ocultable en una página web

Los usuarios, esas ricuras

Me encantan los usuarios contradictorios. Al fin y al cabo, esas contradicciones no dejan de reflejar la naturaleza humana, así que no hay por qué asustarse. Hay que saber escucharlos, y darles lo que realmente quieren o necesitan, que muchas veces no coincide exactamente con LO QUE TE PIDEN.

En esta ocasión, por un lado me piden que les incluya un texto fijo en una página web, unas instrucciones que deben ser utilizadas y tenidas en cuenta por todos los que utilizan la página. A veces la aplicación web les devuelve determinados resultados y los usuarios tienen que consultar en la documentación en papel, unas normas complejas que en los últimos meses están cambiando bastante (dependen de unas leyes un tanto "inestables"). Tener la información a la vista en la página, mientras usan el programa, les evitaría tener que abandonar la página para sumergirse en los papeles.

Pero, por otro lado, tener delante el texto, todo el tiempo, les molesta. Funcionalmente, no aporta utilidad al programa. No se necesita consultar siempre, sólo si el programa devuelve determinados datos, para dar explicaciones, para realizar procesos manuales... Así que, mientras unos me piden que el texto esté a la vista, otros me pregunta si no se puede quitar, ya que les "ensucia" la página.

O sea, resumiendo, quieren que las instrucciones se vean, pero al mismo tiempo, no se vean. Qué ricos.

Fig. 1. Que se vea, pero que no se vea. 
Foto: Jorge A. Loffler, Flickr, licencia CC BY-SA 2.0

Texto ocultable

Para resolver esto se pueden dar muchas soluciones, y seguro que los especialistas en interacción persona-ordenador lo han estudiado hasta la saciedad. El tema de dónde ubicar un elemento en la interfaz de usuario no es algo para tomarse a la ligera, sobre todo en aplicaciones que tengan cierta repercusión, con un alto número de usuarios. 

Una opción sencilla sería poner las instrucciones en una página aparte, y en la página principal poner un enlace, que se abra en una nueva ventana o pestaña. Sin embargo, en esta ocasión, yo me voy a limitar a una solución también muy simple y bastante efectiva, a juzgar por el feedback que me han dado los usuarios.

La técnica consiste en comenzar con el texto oculto en la página, y un botón que permita visualizarlo o volver a ocultarlo a placer. También se podía haber hecho justo al contrario: empezar con el texto visible, y que el usuario pueda ocultarlo. La elección de cualquiera de las dos alternativas depende de la naturaleza y necesidad del texto. En mi caso, es un texto que sólo hay que consultar de forma ocasional, con lo que interesa que la mayor parte del tiempo esté oculto. Por eso al cargar la página el texto no se muestra. Si fuera un mensaje de lectura obligatoria, para que nadie pueda decir que no lo ha visto, por ejemplo, pues comenzaría con el texto visible y el botón permitiría ocultarlo (y visualizarlo de nuevo, claro). En fin, estos detalles parecen tonterías pero muchas veces son tonterías importantes, así que si uno se encuentra situaciones similares, es buena idea dedicarle una pensada de unos minutos o, mejor aún, preguntarle a los usuarios, que son quienes al fin y al cabo van a valorar la utilidad del software.

Pasando ya a lo meramente técnico, nos basaremos en tres cosas:
  • identificadores de elementos
  • código HTML de un elemento (propiedad innerHTML)
  • botón con una función Javascript asociada

Identificadores de elementos

Prácticamente cualquier elemento de una página puede tener un identificador (un id) que podemos utilizar para hacer referencia a él desde código Javascript. Esto incluye también a los párrafos, así que en vez de escribir

<p>Párrafo de texto</p>

Escribiremos

<p id="mensaje">Párrafo de texto</p>

Para poder manipularlo desde el código Javascript, accederíamos a ese elemento con la llamada

document.getElementById("mensaje");

Queremos comenzar con el texto oculto, lo que equivale a decir que el texto inicial del párrafo esté vacío. Debajo de ese párrafo pondremos un botón y debajo del botón, el resto de la página:


1 <p id="mensaje"></p>  
2 <button id="bInfo1" onclick="botonPulsado()">Mostrar mensaje</button> 
3 <p>Aquí va el resto de la página</p>

Como puede verse, el botón responderá al clic invocando a la función botonPulsado, que mostraremos más adelante.

Código HTML

Por otro lado, algunos elementos DOM tienen la propiedad innerHTML, que es un valor textual que representa el código HTML asociado a ese elemento. En el caso de un párrafo, es el texto HTML que se mostrará dentro. Esta propiedad puede ser tanto de lectura como de escritura, así que podemos recuperar el valor del párrafo o podemos asignarlo. Por ejemplo:

texto = "hola, caracola";
document.getElementById("mensaje").innerHTML = texto;

La función Javascript

Por último, necesitaremos una función que cambie el contenido del párrafo en cada pulsación del botón, mostrando u ocultando el texto, alternativamente. Esto se hará comprobando si el párrafo en ese momento está vacío o no:

    if (document.getElementById("mensaje").innerHTML == "") {
        document.getElementById("mensaje").innerHTML = texto;
        document.getElementById("bInfo1").innerHTML = "Ocultar mensaje";
    } else {
        document.getElementById("mensaje").innerHTML = "";
        document.getElementById("bInfo1").innerHTML = "Mostrar mensaje";
    }

Con esto, ya tenemos las tres piezas de nuestro pequeño puzzle. Así quedaría la página completa:



01 <HTML>  
02 <HEAD> 
03 <script> 
04 function botonPulsado() { 
05 texto = 'Esto es un bloque de texto <br>\  
06 que debería poder mostrarse u ocultarse <br>\  
07 según lo desee el usuario. Por ejemplo, unas<br>\  
08 instrucciones de cómo actuar en determinados casos,<br>\  
09 o unos teléfonos de contacto de emergencia...<br>\  
10 En general, cualquier información útil que tenga que<br>\  
11 estar rápidamente accesible<br>'  
12 if (document.getElementById("mensaje").innerHTML == "") { 
13 document.getElementById("mensaje").innerHTML = texto;  
14 document.getElementById("bInfo1").innerHTML = "Ocultar mensaje";  15 } else { 
16 document.getElementById("mensaje").innerHTML = ""; 
17 document.getElementById("bInfo1").innerHTML = "Mostrar mensaje"; 18 }  
19 }  
20 </script> 
21  
22 </HEAD> 
23 <BODY> 
24 
25 <H1>Página importantísima, con un mensaje secreto</H1>  
26  
27 <P ID="mensaje"></P>  
28 <BUTTON ID="bInfo1" ONCLICK="botonPulsado()">Mostrar mensaje</BUTTON>  
29 <P>Aquí va el resto de la página</P>  
30  
31 </BODY>  
32 </HTML>

Listado 1. La página al completo

Y si la probamos veremos el resultado de las imágenes:


Y una vez pulsado el botón


Unos comentarios finales

Como vemos, la técnica de mostrar y ocultar un elemento es muy sencilla, pero también muy versátil. Se puede utilizar, entre otras cosas, para
  • textos de instrucciones, notas legales o mensajes de ayuda para el usuario
  • bloques de iconos
  • una sección de enlaces corporativos
  • ...y cualquier otra cosa que se os ocurra y para la que tenga sentido verse y ocultarse
Como curiosidad, os comento que un par de usuarios me han felicitado efusivamente por el resultado. Para ellos, resulta muy práctico olvidarse de mirar los papeles cuando están en la página y tienen que consultar la normativa. La técnica empleada en la página, desde un punto de vista técnico, es una trivialidad, pero oyendo sus alabanzas parece que uno les hubiera hecho la aplicación del siglo, ya que han quedado muy satisfechos.

Esto viene a recordarnos que no todo es calidad técnica o calidad objetiva, sino que también es muy importante la calidad percibida por el usuario. De hecho, podemos rompernos la cabeza ideando virguerías técnicas y haciendo que nuestro programa sea una maravilla tecnológica, pero si los usuarios no lo perciben así, entonces quizás no tiene tanta calidad. O sin quizás.

Quien de verdad puede valorar algo es quien lo usa. Esto no es una verdad absoluta (recordemos el caso de los coches de Volkswagen: los usuarios podían estar satisfechos con la conducción, comodidad... pero su calidad tecnológica no llegaba a las exigencias legales en materia de emisiones), pero es importante tener en cuenta qué cosas podemos dar que aporten mayor valor a los usuarios de nuestras aplicaciones.

Esas cosas que aportan valor no siempre han de suponer un esfuerzo técnico muy alto, así que es bueno estar atentos para detectarlas y poder darlas. Así, con poco esfuerzo podemos aumentar el nivel de satisfacción de nuestros usuarios. Que los usuarios estén contentos es bueno para ellos y mejor aún para nosotros.

Bueno, aquí corto ya el rollo. A seguir programando.Y que los usuarios de vuestros programas os lo agradezcan, al menos ahora que se acerca la Navidad.


miércoles, 8 de abril de 2015

Configurar Eclipse para desarrollar para Liferay

Esta entrada podría verse como un complemento a la entrada que publiqué hace unos días sobre instalación y configuración de Liferay. Esta explicación que sigue es la que a mí me hubiera gustado tener cuando tuve que configurar Eclipse para trabajar con Liferay.

Una vez instalado Liferay, lo que queremos es prepararnos un entorno adecuado para comenzar a desarrollar portlets para publicarlos en nuestro portal. El entorno ideal para esto (aunque no tiene por qué ser el único, claro) es Eclipse. ¿Y cómo lo dejamos listo para esto? Veamos cómo hacerlo en tres pasos. Vamos allá.

Paso 1. Descargar e instalar Eclipse

Dirección de descarga: https://www.eclipse.org/downloads/
Ten la precaución de elegir la versión acorde con tu sistema: 32 o 64 bits.

Descomprime el ZIP descargado en la carpeta que quieras. En mi caso, lo descomprimiré en c:\bin\eclipse. Iniciando el ejecutable, debería verse una pantalla como esta.

Fig. 1. Desvirgando Eclipse

Pulsando en Workbench (arriba a la derecha) se accede a la zona de trabajo.

Paso 2. Instalar la perspectiva para Liferay

Eclipse puede trabajar con perspectivas, que son agrupaciones de vistas y editores. (Más info, aquí [http://www.comscigate.com/cs/valle/vistas.htm] o aquí [http://www.tecgurus.net/foro/19-eclipse/616-perspectivas-en-eclipse.html]), por ejemplo.

Si nos fijamos, recién instalado Eclipse sólo vemos la perspectiva típica para el desarrollo en Java.

 Fig. 2. Perspectivas en Eclipse

Vamos a instalar el soporte para la perspectiva de desarrollo para Liferay y veremos cómo cambia la cosa. Para ello, hay que ir al menú Help de Eclipse, y elegir la opción Install new software.... Pegar en Work with la dirección siguiente http://releases.liferay.com/tools/ide/latest/stable/
y seleccionar "Liferay IDE" (contiene 3 subopciones, que dejamos marcadas).

Fig. 3. Seleccionando el IDE de Liferay para integrar en Eclipse

Tras pulsar Next (2 veces) y aceptar los términos de la licencia, comienza la descarga. Puede ser que a mitad de la misma os pregunte si queréis descargar contenido no firmado. Lo descargamos y continuamos adelante.
 Fig. 4. Descargando complementos Liferay para Eclipse

Al terminar (en mi caso, la descarga dura unos 5 minutos), nos pedirá reiniciar Eclipse para que los cambios tengan efecto.

Fig. 5. Reiniciar, la eterna solución

Tras reiniciar, aparentemente todo está igual, pero no es así. (Por cierto, si por un casual alguien intenta instalar por segunda vez el plugin de Liferay, verá algo como esto)

Fig. 6. ¿Ande vas? Que eso ya está instalaaaaaadooooo

El caso es que ahora ya podemos pulsar en el botón que abre las diferentes perspectivas, y podemos ver una para Liferay


Fig. 7. Abrir la perspectiva para Liferay

Y podemos ver algunos puntos interesantes, como el botón para activar la perspectiva para desarrollo Liferay, y la vista de Servidores donde (por el momento) aún no tenemos ningún servidor configurado (todo se andará, tranquilos).

Fig. 8. Perspectiva Liferay instalada en Eclipse

Paso 3. El servidor de Liferay

Lo único que nos falta es configurar nuestro servidor para tener un entorno de desarrollo y pruebas para empezar a desarrollar portlets con Liferay. Para configurar el servidor, utilizaremos el que instalamos en la anterior entrada.

Pulsamos sobre el enlace para crear un nuevo servidor (esquina inferior izquierda) y elegimos el tipo de servidor dentro del grupo Liferay. En mi caso, Liferay v6.2 CE Server (Tomcat 7)

 Fig. 9. Elegir el tipo y versión del servidor Liferay

Al pulsar siguiente, nos pregunta que dónde está instalado el Tomcat. Se lo decimos

Fig. 10. ¿Dónde está el gatito Tom?

Si nos hemos descargado los Javadocs y los fuentes de Liferay, podemos configurarlos en la siguiente pantalla. Si no, podemos darle directamente a Finish, y ya veremos que nos aparece el servidor disponible para que lo arranquemos y podamos hacer cosas con él. Para iniciarlo, sólo hay que darle al play.
Fig. 11. El servidor Liferay disponible y a punto de ser iniciado

El arranque del servidor no es rápido. En mi equipo se lleva casi dos minutos, durante los cuales se van viendo diferentes mensajes en la consola, y junto al nombre del servidor aparecen las palabras "Starting, Synchronized". Cuando termina, se lanza automáticamente una ventana del navegador y en Eclipse se ven junto al servidor las palabras "Started, Synchronized". En la consola, deberéis ver entre los últimos mensajes algo así como

INFORMACIÓN: Server startup in 70733 ms

(En mi caso, tras este mensaje de "Server startup" tengo alguno más, de warning, pero creo que se debe a que para hacer esta pequeña guía he hecho varias instalaciones / desinstalaciones y seguramente he dejado algo de basurilla por ahí.)

Bueno, creo que éste es un buen sitio para dejar aquí el asunto de momento. Ya tenemos un entorno disponible; lo siguiente sería hacer nuestro primer portlet. Pero eso es cosa para otra entrada.

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

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á)

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...