miércoles, 27 de agosto de 2014

Convertir una maqueta en HTML en una página Web con contenido dinámico (2)

En el post anterior hablábamos del proceso para convertir una maqueta en HTML con una cantidad fija de información en una Web con contenido dinámico. Ahora, veremos cómo convertir una maqueta con una cantidad variable de información en una Web con contenido dinámico.

Ejemplo de sección con una cantidad variable de información


Volviendo al ejemplo de la Web de la escuela, supongamos que hay una página en la que se publica la lista de estudiantes que cumplen años en un día determinado. Para ello, será posible indicar una fecha y pulsar un botón  para obtener la lista de alumnos correspondientes. La sección maquetada podría quedar como sigue:

<div id="cumples">
    <input type="date"> <button>Buscar</button>
    <ul>
        <li>
            <img src="img/persona.png">
            <label>Juan Pérez</label>
        </li>
        <li>
            <img src="img/persona.png">
            <label>Manuel López</label>
        </li>
        <li>
            <img src="img/persona.png">
            <label>María González Gurrierrez</label>
            </li>
        <li>
            <img src="img/persona.png">
            <label>Clara Martínez</label>
            </li>
        <li>
            <img src="img/persona.png">
            <label>Julián del Corral</label>
        </li>
    </ul>
</div>

Cuyo resultado es el siguiente (después de formatearlo un poco con CSS):



Supongamos ahora que en dicha Web, hay un servicio REST que, al consultarlo indicándole una fecha, devuelve un JSON la lista de los alumnos que cumplen años. Por ejemplo, el JSON devuelto podría tener la estructura siguiente

[
    {
        "nombre": "María López González",
        "foto": "img/alumnos/maria_lopez.jpg"
    },
    {
        "nombre": "Juan Pérez González",
        "foto": "img/alumnos/juan_perez.jpg"
    },
    {
        "nombre": "Laura Gutierrez Pérez",
        "foto": "img/alumnos/laura_gutierrez.jpg"
    }
]

Veamos ahora, cómo transformar la maqueta para mostrar dinámicamente el contenido del JSON obtenido desde el servicio REST.

Proceso para convertir el contenido de una maqueta en HTML con una cantidad variable de información en una Web con contenido dinámico


Hay varias formas para generar una cantidad dinámica de contenido, aunque todas requieren lo mismo: insertar nuevos elementos en la página. Ahora, la forma de hacer estas inserciones, puede variar mucho. En el post XXX se muestra cómo insertar nodos nuevos (etiquetas HTML) mediante jQuery. Aunque el método ahí mostrado es más flexible y potente que el que mostraremos a continuación, el que sigue es más simple y directo; siendo un paso previo natural al uso de frameworks para el uso de plantillas HTML, como Mustage.

Entonces, el proceso sería el siguiente:

  1. Identificar el evento ante el cuál queremos actualizar la plantilla con los datos dinámicos.
  2. Localizar la sección de datos que se repiten
  3. Modificar la plantilla:
    1. Eliminar todos los elementos que se repiten, excepto el primero
    2. Si no lo están, encerrar los datos que se repiten en un elemento agrupador.
    3. Asignar un identificador único al elemento agrupador.
    4. Crear un bloque script con un identificador único y tipo "text/html"
    5. Mover el primer conjunto de datos que se repite, localizado en el paso 2, al bloque script del paso 3 - 4.
    6. Remplazar cada texto o atributo a modificar dinámicamente por el nombre del dato desde donde se extraerá, encerrado entre llaves dobles.
  4. Crear una cadena en JavaScript con la plantilla del HTML que deberá repetirse, extrayéndolo del contenido de la etiqueta script, del paso 3 - 4.
  5. Crear una función JavaScript para generar HTML, a partir de una plantilla HTML. Para ello, deberá recibir una cadena con una plantilla de una estructura HTML, un diccionario con el valor a remplazar por cada nombre de la plantilla, y deberá devolver una cadena con el HTML resultante de los remplazos.
  6. Crear una función JavaScript que modifique el HTML de la página para mostrar una lista de datos. Para ello, para cada elemento de la lista y para cada dato de dicho elemento: llamar a la función del paso 5, indicándole la plantilla HTML del paso 4, el nombre del dato y el dato en sí.
  7. Crear una función en JavaScript que cargue los datos que se quieren mostrar y llame a la función del paso 6 con los datos cargados.
  8. Cuando se produzca el evento deseado (identificado en el paso 1), llamar a la función de carga de datos (creada en el paso 7).
  9. Fin.

Para ilustrar el proceso anterior, veamos cómo dinamizar los datos de la plantilla de los "alumnos que cumplen año".

Ejemplo del proceso, ilustrado y explicado, paso a paso


1 Identificar el evento ante el cuál queremos actualizar la plantilla con los datos dinámicos


En la Web de lista de alumnos que cumplen años, primero hay que seleccionar la fecha del cumpleaños en cuestión y luego pulsar el botón de búsqueda; por lo que el evento para actualizar la plantilla será cuando se pulse en el botón para buscar.

2 Localizar la sección de datos que se repiten


En este caso, los datos que se repiten son la foto y el nombre, que se corresponden con una etiqueta img y label, encerradas por una etiqueta li. Por lo tanto, la sección de datos que se repiten son las etiquetas li y su contenido:

<li>
    <img src="img/persona.png">
    <label>Juan Pérez</label>
</li>
<li>
    <img src="img/persona.png">
    <label>Manuel López</label>
</li>
<li>
    <img src="img/persona.png">
    <label>María González Gurrierrez</label>
</li>
<!-- ... -->

3 - 1 Eliminar todos los elementos que se repiten, excepto el primero


En este caso, la lista pasaría de tener varios li, a tener uno solo:

<ul>
    <li>
        <img src="img/persona.png">
        <label>Juan Pérez</label>
    </li>
</ul>

3 - 2 Si no lo están, encerrar los datos que se repiten en un elemento agrupador


La sección que se repite es la contenida por las etiquetas li que están contenidas por una etiqueta ul; por lo que no es necesario encerrarlas en  ningún elemento agrupador. Si en lugar de una etiqueta li, la sección repetida fuera un div, por ejemplo, es posible que hubiera que encerrarlo en otro div; por ejemplo. No obstante, en este caso, los datos que se repiten ya están encerrados en un elemento agrupador: ul.

3 - 3 Asignar un identificador único al elemento agrupador


Ya que el elemento agrupador es la etiqueta ul y ésta contiene la lista de alumnos que cumplen años, identificaremos a dicho elemento con el id "alumnos":

<ul id="alumnos">
    <li>
        <img src="img/persona.png">
        <label>Juan Pérez</label>
    </li>
</ul>

3 - 4 Crear un bloque script con un identificador único y tipo "text/html"


El bloque script será el contenedor de la plantilla de los datos que se repiten para cada alumno y, aunque puede estar en cualquier parte de la página, es una buena práctica ponerlo lo más cerca posible de la zona donde vamos a insertar los datos posteriormente:

<ul id="alumnos">
    <li>
        <img src="img/persona.png">
        <label>Juan Pérez</label>
    </li>
</ul>
<script id="plantillaAlumno" type="text/html">
</script>

3 - 5 Mover el conjunto de datos que se repite (localizado en el paso 2), al bloque script del paso 3 - 4


Aquí se trata, simplemente de mover la etiqueta li y su contenido, hacia dentro de la etiqueta script del paso anterior:

<ul id="alumnos">
</ul>
<script id="plantillaAlumno" type="text/html">
    <li>
        <img src="img/persona.png">
        <label>Juan Pérez</label>
    </li>
</script>

3- 6 Remplazar cada texto o atributo a modificar dinámicamente por el nombre del dato desde donde se extraerá, encerrado entre llaves dobles


En este punto modificaremos cada elemento que deba cambiar dinámicamente por el nombre de la variable o el atributo del objeto en el que tendremos dicha información en JavaScript. En este caso, se trata de la Url de la fotografía y del nombre del estudiante por lo que la plantilla quedaría, finalmente, así:

<div id="cumples">
    <input id="fecha" type="date"> <button id="buscar">Buscar</button>
    <ul id="alumnos">
    </ul>
    <script id="plantillaAlumno" type="text/html">
        <li>
            <img src="{{foto}}">
            <label>{{nombre}}</label>
        </li>
    </script>
</div>

El motivo para poner el nombre del dato encerrado en llaves dobles es evitar colisiones entre el nombre de nuestra variable y elementos válidos del HTML, de modo que, cuando generemos el contenido dinámico no sustituyamos por accidente una parte de nuestra estructura HTML. Del mismo modo, encerramos nuestra plantilla en una etiqueta script con tipo "text/html" para que el marcado HTML de la plantilla no genere ningún elemento visual que deforme la información de la página.

4 Crear una cadena con la plantilla del HTML que deberá repetirse, extrayéndolo del contenido de la etiqueta script, del paso 3 - 4.


La cadena la crearemos extrayendo el contenido de la etiqueta script identificada como plantilla:

var plantillaAlumno = $('#plantillaAlumno').html();

5 Crear una función JavaScript para generar HTML, a partir de una plantilla HTML.


La función que se ilustra a continuación es un elemento reaprovechable del proceso; es decir: que podremos usar esta función en cualquier caso, independientemente del marcado HTML que hayamos puesto en la plantilla, siempre y cuando, cumplamos con encerrar entre llaves dobles los nombres de los datos a remplazar. De modo que, el siguente es un código que podremos copiar y pegar de una Web a otra sin ningún cambio:

/**
 * Genera código HTML a partir de una plantilla y datos de sustitución
 * @param {string} pantilla - Cadena con la plantilla HTML
 * @param {Object} datos - Diccionario de nombres de datos a remplazar 
 *      con su respectivo valor
 */
function generarHtml(plantilla, datos) {
    var html = plantilla;                   // Inicializar el HTML
    var nombresDeDatos = Object.keys(datos);// Obtener lista de datos a remplazar
    nombresDeDatos.forEach(function (nombreDato) {  // Por cada dato a remplazar:
        var nombre = new RegExp('{{' + nombreDato + '}}', 'g'); // Obtener nombre
        var valor = datos[nombreDato];              // Obtener valor de remplazo
        html = html.replace(nombre, valor);         // Remplazar nombre por valor
    });
    return html;                                    // Devolver HTML generado
}

6 Crear una función JavaScript que modifique el HTML de la página para mostrar una lista de datos


Esta función, básicamente llamará a la función del paso anterior, por cada elemento a mostrar e insertará en el DOM el HTML generado con cada dato:

/**
 * Actualiza la lista de alumnos cuyo cumpleaño coincide con la fecha indicada
 * @param {object[]} listaAlumnos - Lista de objetos con los datos de los
 *      alumnos: nombre y foto
 */
function actualizarListaAlumnos(listaAlumnos) {
    $('#alumnos').html('');                  // Inicializar la lista HTML
    listaAlumnos.forEach(function (alumno) { // Por cada alumno:
        var html = generarHtml(plantillaAlumno, alumno); // Generar su HTML
        $('#alumnos').append(html);          // Añadir el HTML generado a la Web
    });
}

7 Crear una función en JavaScript que cargue los datos que se quieren mostrar y llame a la función del paso 6 con los datos cargados


Como hemos supuesto que existe un servicio REST que, dada una fecha, devuelve un JSON con la lista de alumnos que cumplen años en dicha fecha, vamos a necesitar:


  1. Identificar la Url del servicio REST
  2. Construir la Url de la consulta con la fecha seleccionada
  3. Pedir los datos JSON mediante Ajax
  4. Llamar a la función del paso 6, con los datos obtenidos.

Para simplificar, supongamos que el servicio REST está en la misma Web, en la Url relativa "api/cumpleanyos" y que llamaremos a la función actualizarListaAlumnos, quedando la función como sigue:

/**
 * Carga la lista de alumnos que cumplen años y actualiza la interfaz 
 * con los datos cargados
 */
function cargarCumpleanyos() {
    var fecha = $('#fecha').val();          // Obtener fecha de consulta
    var url = '/api/cumpleanyos/' + fecha;  // Generar Url de consulta
    $.getJSON(url, function (result) {      // Solicitar lista de alumnos
        if (result) {                       // Si se obtiene alguna lista
            actualizarListaAlumnos(result); // Actualizar lista de alumnos
        }
    });
}

8 Cuando se produzca el evento deseado (identificado en el paso 1), llamar a la función de carga de datos (creada en el paso 7).


Finalmente, el evento generado por el usuario que desencadena la ejecución de la búsqueda y la actualización dinámica de los contenidos de la página:

$('#buscar').click(cargarCumpleanyos);

Poniéndolo todo junto 


Para ver el resultado completo de todo lo anterior, ir a los siguiente enlaces, donde están las páginas funcionando y el código fuente de las mismas:



Conclusiones y siguientes pasos


La dinamización de una maqueta en HTML que deba tener una cantidad variable de elementos repetitivos es más compleja que la de una maqueta con una cantidad fija de elementos y requiere una reestructuración de la maqueta. Sin embargo, con organización y metódica pueden obtenerse muy buenos resultados con muy poco código en JavaScript, reduciéndose el proceso en general a:

  1. Modificar la maqueta para:
    1. Prepararla para su actualización desde JavaScript.
    2. Crear una plantilla de los elementos repetitivos.
  2. Crear funciones en JavaScript para cargar y visualizar el contenido dinámico, remplazando en la plantilla los valores cargados.
  3. Ejecutar las funciones de carga y visualización, luego de la ejecución de un evento determinado.

Ahora, una vez vista la forma de generar estos contenidos dinámicos de forma manual, lo siguiente es aprender a hacerlo usando un framework o librería apropiados para esta tarea que, con toda seguridad, nos facilitará el proceso y proveerá de muchas más opciones.

Una buena opción para continuar es el tutorial interactivo de Knockout disponible en http://learn.knockoutjs.com, donde enseñan los conceptos y la práctica de la separación de la presentación de la información, de la lógica de su operación, mientras aprendemos a usar la biblioteca.



Si te ayudó este tutorial, compártelo con otros y si tienes alguna sugerencia o cambio para mejorarlo... haz tus comentarios.

domingo, 24 de agosto de 2014

Convertir una maqueta en HTML en una página Web con contenido dinámico (1)

Después de maquetar una página, el paso siguiente es modificarla para que su contenido pase a ser dinámico. Lo ideal sería utilizar un framework o una librería que facilitara este trabajo, como un sistema de plantillas como Mustache o un framework más completo como Knockout o AngularJS; pero la base del proceso siempre es la misma, tanto si usas un framework como si lo haces todo a mano.

Aquí vamos a explicar el proceso, así que, para no desviarnos con las particularidades de uno u otro framework, vamos a dinamizar esa maqueta en HTML con JavaScript "a secas", sin el apoyo de ninguna libería, ni siquiera jQuery.

Para ello, vamos a dividir el proceso en dos casos cuyas soluciones presentaremos por separado: dinamizar el contenido de una maqueta con una cantidad fija de información y, después, dinamizar el contenido de una maqueta con una cantidad de información variable.

Ejemplo de sección con una cantidad fija de información


Supongamos que tenemos la Web de una escuela en la que, cada día, se publican los datos de un alumno destacado mostrando el nombre del alumno, su foto y un pequeño párrafo diciendo los motivos por los que se le considera un alumno destacado. La sección maquetada podría ser como sigue:

<div id="alumnoDestacado">
<h3>Nombre del alumno</h3>
<img src="img/persona.png" />
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
   Mauris vehicula dictum lectus vel auctor.</p>
</div>

Cuyo resultado es el siguiente (después de formatearlo un poco con CSS):

Nombre del alumno


Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris vehicula dictum lectus vel auctor.

Supongamos ahora que en dicha Web, hay un servicio REST que, al consultarlo, devuelve un JSON con los datos del alumno destacado. Por ejemplo, el JSON podría tener la estructura siguiente:

{
    "nombre": "María López González",
    "foto": "img/alumnos/maria-lopez-gonzalez.jpg",
    "motivo": "Galardonada en las Olimpiadas Municipales de Lengua Inglesa"
}

En la maqueta anterior, aún no hay cambios en el contenido pues es solo una maqueta. Entonces: ¿cómo transformar la maqueta para mostrar dinámicamente el contenido del JSON obtenido desde servicio REST?

Proceso para convertir el contenido de una maqueta en HTML con una cantidad fija de información en una Web con contenido dinámico


Por supuesto, hay muchas formas de solucionar este problema. Aquí propondremos una (de entre tantas) en la que basarse para buscar alternativas y soluciones propias. De modo que el proceso quedaría como sigue:

  1. Identificar el evento ante el cuál queremos actualizar la plantilla con los datos dinámicos.
  2. Modificar la plantilla HTML asignando un identificador único a cada elemento cuyo contenido queremos actualizar dinámicamente (desde JavaScript).
  3. Crear una función en JavaScript que reciba como parámetro los datos a mostrar y modifique el HTML para reflejar los cambios. Para ello, para cada dato a actualizar:
    1. Obtener el elemento HTML con el identificador correspondiente al dato a actualizar
    2. Modificar el atributo a actualizar, con el dato correspondiente
  4. Crear una función en JavaScript que cargue los datos que se quieren mostrar y llame a la función del paso 3 con los datos cargados.
  5. Cuando se produzca el evento deseado (identificado en el paso 1), llamar a la función de carga de datos (creada en el paso 4).
  6. Fin.

Para ilustrar el proceso anterior, veamos cómo dinamizar los datos de la plantilla del "alumno destacado".

Ejemplo del proceso, ilustrado y explicado, paso a paso


1 Identificar el evento ante el cuál queremos actualizar la plantilla con los datos dinámicos


En la Web de la escuela, el proceso de selección del alumno destacado se hace una vez al día; por tanto, solo vamos a actualizar la plantilla cuando se cargue la página. Por tanto, el evento para actualizar la plantilla será cuando la página se ha cargado y está lista para su actualización.

2 Modificar la plantilla HTML asignando un identificador único a cada elemento cuyo contenido queremos actualizar dinámicamente (desde JavaScript)


En este caso, los datos a mostrar son el nombre, la foto y la descripción que se corresponderán con las etiquetas h3, img y p, respectivamente. De modo que, asignaremos un id único a cada etiqueta para su actualización desde JavaScript, quedando la plantilla modificada, como sigue:

<div id="alumnoDestacado">
<h3 id="nombre">Nombre del alumno</h3>
<img id="foto" src="img/persona.png" />
<p id="motivo">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
   Mauris vehicula dictum lectus vel auctor.</p>
</div>

3 Crear una función en JavaScript que reciba como parámetro los datos a mostrar y modifique el HTML para reflejar los cambios.


Este es el pollo del arroz con pollo: aquí es donde hay que poner énfasis pues es la parte donde se hace la actualización de los datos en cuestión. Para ello, hay que intentar ser claros y consecuentes con los nombres que se asignen a variables y funciones. La función que vamos a implementar va a actualizar los datos del alumno destacado así que la llamaremos actualizarAlumnoDescataco. Luego, recibirá los datos del alumno destacado, por lo que tendrá un parámetro que llamaremos datosAlumno. Finalmente, va a actualizar los datos nombre, foto y motivo; por lo que el proceso de actualización será:

  1. Localizar el elemento que contendrá el nombre y actualizar el texto del mismo, con el nombre del alumno.
  2. Localizar el elemento que contendrá la foto y actualizar la url de la imagen, con la url de la foto del alumno.
  3. Localizar el elemento que contendrá el motivo y actualizar el texto del mismo, con el motivo por el que se destaca el alumno.

Teniendo en cuenta lo anterior, el código de la función quedaría más o menos como sigue:

/**
* Actualiza los datos de un alumno, en la sección de alumno destacado
* @param datosAlumno - Objeto con los datos del alumno: nombre, foto y motivo
*/
function actualizarAlumnoDescatado(datosAlumno) {
    $('#nombre').text(datosAlumno.nombre);
    $('#foto').attr('src', datosAlumno.foto);
    $('#motivo').text(datosAlumno.motivo);
}

4 Crear una función en JavaScript que cargue los datos que se quieren mostrar y llame a la función del paso 3 con los datos cargados


Usualmente, la fuente de obtención de datos puede variar: puede venir de un servicio REST propio, de uno externo, o ser un dato calculado o generado a partir de otros ya cargados. De modo que la implementación de esta función variará, según la fuente de los datos. No obstante, en el caso del alumno destacado hemos supuesto que la Web cuenta con un servicio REST que devuelve un JSON con los datos del alumno; por lo que, en este punto, necesitaremos:

  1. Identificar la Url del servicio REST
  2. Pedir los datos JSON mediante Ajax
  3. Llamar a la función del paso 3, con los datos obtenidos.

Una vez más, intentaremos ser organizados y consecuentes con los nombres, así que supongamos que el servicio REST está en la misma Web, en la Url relativa "api/alumnoDestacado" y que llamaremos a la función cargarAlumnoDestacado, quedando la función como sigue:

/**
* Carga los datos del alumno destacado y actualiza la interfaz 
* con los datos cargados
*/
function cargarAlumnoDestacado() {
    var url = "api/alumnoDestacado";
    $.getJSON(url, function (result) {
        if (result) {
            actualizarAlumnoDestacado(result);
        }
    });
}

Esta implementación, por supuesto, es muy básica e ignora muchos posibles casos de fallo: ¿Qué pasa si no se obtienen resultados del servicio REST? ¿Qué pasa si se produce un error en la llamada Ajax? ¿Qué pasa si los datos no tienen la estructura esperada...? Estos y muchos otros fallos quedan aquí sin tratar, porque complejizarían el código de la función y lo que pretendemos aquí es mostrar lo mínimo necesario para lograr un objetivo: cargar los datos desde un servicio y mostrarlo en nuestra Web. De modo que, queda como ejercicio personal extender éste código y tratar todos los casos que se nos puedan ocurrir.

5 Cuando se produzca el evento deseado (identificado en el paso 1), llamar a la función de carga de datos (creada en el paso 4)


Este paso final es el aglomerador: aquí es donde pondremos a funcionar nuestro código, partiendo del acontecidmiento de un evento determinado. En nuestro ejemplo, definimos que la carga y visualización del alumno destacado se produciría una única vez, después de haber cargado la página; por lo que la llamada a la función de carga de datos quedaría como sigue:

$(document).ready(cargarAlumnoDestacado);

Poniéndolo todo junto


Para ver el resultado completo de todo lo anterior, ir a los siguiente enlaces, donde están las páginas funcionando y el código fuente de las mismas:


Conclusiones y siguientes pasos


Como hemos visto hasta aquí, el proceso para convertir el contenido de una maqueta en HTML en una Web con contenido dinámico puede reducirse a:

  1. Modificar la maqueta para prepararla para su actualización desde JavaScript.
  2. Crear funciones en JavaScript para cargar y visualizar el contenido dinámico.
  3. Ejecutar las funciones de carga y visualización, luego de la ejecución de un evento determinado.

No obstante, las particularidades de la implementación varían si la cantidad de contenido dinámico es fija o variable. Aquí mostramos el proceso para convertir el contenido de una maqueta en HTML con una cantidad fija de información en una Web con contenido dinámico y en el post siguiente veremos el proceso para convertir el contenido de una maqueta en HTML con una cantidad variable de información en una Web con contenido dinámico.

Si tienes alguna duda, comentario o sugerencia... ponla en los comentarios.

jueves, 10 de julio de 2014

Geocodificación inversa: convertir coordenada GPS en dirección postal


Uno de los usos más frecuentes de las aplicaciones de mapas es el de buscar la localización exacta de una dirección determinada. Para ello, introducimos una dirección que la aplicación convierte en una posición GPS y, finalmente, en un marcador en nuestro mapa. A este proceso se le llama geocodificación. Por otra parte, otro uso habitual es el de obtener la dirección de una localización exacta conocida. Para ello, señalamos un punto en el mapa, que la aplicación convierte en una coordenada GPS y ésta en una dirección. A este procese se le llama geocodificación inversa.

Supongamos, por ejemplo, que hacemos una aplicación Web con un mapa que se centra en la posición del usuario y muestra un marcador en la misma. La posición (coordenadas GPS) podría obtenerse con las APIs de geolocalización de HTML5 que indican las coordenadas del punto más cercano a la ubicación del usuario. Sin embargo, mostrarle al usuario unas coordenadas numéricas es poco útil porque no le sirve para orientarse. De modo que tendríamos que convertir dichas coordenadas en una dirección postal; pero para ello, lamentablemente, no hay una API en HTML5, por lo que habrá que usar un servicio de algún proveedor de geocodificación inversa.

Proveedores de geocodificacón inversa


La geocodificación inversa es un proceso que requiere amplias bases de datos y depende de la disponibilidad de información que puede variar de un país o región a otro. Por eso, hay proveedores que compilan o centralizan el acceso a esa información. Algunos de estos proveedores son compañías tan conocidas como Google o Microsoft y otros menos conocidos pero más especializados, como Esri o MapQuest... 

Los proveedores de geocodificación inversa son, en sentido general, los mismos proveedores de cartografía o APIs de mapas y, en su mayoría, ofrecen el servicio previo pago o con ciertas limitaciones en su uso. Por ejemplo, no se permite el uso de la geocodificación inversa de Google si no se muestra el resultado en un mapa de Google y solo se permiten 2500 geocodificaciones diarias de forma gratuita (ver detalles de límite de uso en https://developers.google.com/maps/documentation/geocoding/?hl=es#Limits). De modo que siempre que vayamos a usar un servicio, deberíamos verificar si nuestra aplicación cumple con las políticas de uso de la API en cuestión.

Una alternativa a estos servicios de pago o con limitaciones, es el uso de proveedores gratuitos como Nominatim, asociado a los datos de OpenStreetMaps. Hay que tener presente que Nominatim, para evitar el abuso de un recurso gratuito, también tiene cierto límite en la "intensidad" de uso del servicio, limitándolo a 1 geolocalización por segundo. Sin embargo, este límite, comparado con el de la API de Google, por ejemplo, es mucho menos restrictivo pues permitiría un volumen de consultas casi 35 veces superior.

Ejemplo de geolocalización inversa mediante el servicio Nominatim


La conversion de una coordenada GPS a una dirección postal con Nominatim se realiza mediante un servicio Web fácilmente consultable. Es tan fácil como copiar la siguiente dirección y pegarla en la barra de direcciones del navegador, remplazando {lat} por la latitud y {lon} por la longitud, cuya dirección postal quiere obtenerse:

http://nominatim.openstreetmap.org/reverse?format=json&addressdetails=1&accept-language=es&zoom=18&lat={lat}&lon={lon}

Por ejemplo, si se visita la dirección siguiente:

http://nominatim.openstreetmap.org/reverse?format=json&addressdetails=0&zoom=18&lat=40.4111188922952&lon=-3.704248666763305

Se obtendría un documento en formato JSON con los siguientes detalles de la localización:
{
  "place_id":"20678078",
  "licence":"Data \u00a9 OpenStreetMap contributors, ODbL 1.0.
             http:\/\/www.openstreetmap.org\/copyright",
  "osm_type":"way",
  "osm_id":"4350172",
  "lat":"40.4090377",
  "lon":"-3.7025752",
  "display_name":"Calle del Amparo, Barrio de las Letras, Centro,
                  Madrid, \u00c1rea metropolitana de Madrid y 
                  Corredor del Henares, Comunidad de Madrid, 28012,
                  Espa\u00f1a"
}

Automatización del acceso al servicio Nominatim en JavaScript


Para realizar geocodificaciones inversas desde JavaScript, usaremos jQuery y la siguiente función

/**
 * Convierte una posición GPS a una dirección postal
 * @param lat - Latitud
 * @param lon - Longitud
 * @param callback - Función a ejecutar una vez se han obtenido 
 * los datos de la geocodificación inversa
 */
function convertirGpsADireccion(lat, lon, callback) {
    $.getJSON("http://nominatim.openstreetmap.org/reverse?" +
              "format=json&addressdetails=0&zoom=18&" +
              "lat=" + lat + "&lon=" + lon + "&json_callback=?",
        callback);
}

Para verla en funcionamiento, teclee una coordenada en los cuadros de texto siguientes y pulse en el botón Obtener geocodificación inversa.




En este caso, la función callback utilizada para mostrar la dirección obtenida fue la siguiente:

function mostrarDireccion(response) {
    $('#direccion').text(response.display_name);
}

Poniéndolo todo junto


Saber de antemano las coordenadas GPS de una posición, no es muy frecuente que digamos, de modo que, para ilustrar la geocodificación inversa en un entorno más natural, la integraremos con un mapa interactivo en el que, al pulsar en el mapa, se obtendrá la dirección postal asociada a la posición GPS del punto seleccionado. Para ver el código fuente en el que se basa este mapa, ver https://github.com/carlosbello/efectodemo/blob/master/WebMaps/Leaflet/reverse_geocoding.html


Instrucciones

Pulse en el mapa para centrarlo en dicha zona y obtebner la dirección de la localización.

domingo, 16 de marzo de 2014

Instant Node.js Starter

Esta semana me pasaron el código de un pequeño proyecto en Node.js y, aunque el código fuera JavaScript de toda la vida, nunca había trabajado con Node.js así que, para entenderlo mejor, busqué un libro que me introdujera en el tema.

Portatada del libro Instant Node.js Starter

El libro


Después de buscar varios títulos, di con Instant Node.js Starter y me decanté por éste por una cuestión de tiempo pues la serie "Instant ... Starter" generalmente da buenas introducciones en tiempos muy cortos (como ya pudimos constatar con el libro Instant OpenLayers Starter).

En este caso, la elección fue un acierto pues el libro de menos de 50 páginas puede leerse con fluidez en un día, mientras se van implementando los ejemplos de código que ilustran los conceptos a lo largo del libro. De modo que en un día, puedes pasar de no conocer nada sorbre Node.js, a entender cómo funciona y generar algunas aplicaciones sencillas pero ilustrativas sobre el potencial de la plataforma.

Está claro que en tan pocas páginas solo pueden cubrirse tópicos primarios, pero, cuando se está buscando introducirse rápidamente en un tema nuevo, la parafernalia sobra, así que el enfoque completamente práctico y la elección de temas del libro resultaron una buena combinación.

Lo que sigue

Después de un día de lectura y práctica, terminé comprendiendo mejor el código que me habían pasado y con una pequeña colección de código funcional (disponilbe en https://github.com/carlosbello/instant-node-starter), resultante de implementar los ejemplos del libro, con la única excepción del ejemplo de acceso a Twitter que, debido a su uso de la versión 1.0 de la API de Twitter -ya en desuso-, dicho código ha dejado de funcionar.

No obstante, ahora hay que complementar los conocimientos básicos con algo más. Así que es posible que lo siguiente sea leer sobre Express para profundizar en la creación de servicios y aplicaciones Web.

¿Y, si no fuera sobre Express, qué debería leer?

jueves, 30 de enero de 2014

¿Cómo migrar una aplicación de Firefox OS a Android con Netbeans?

Este es un tutorial para desarrolladores Web que han comenzado sus andares en el desarrollo de aplicaciones móviles haciendo su primera app para Firefox OS y ahora quieren dar el salto a Android, sin necesidad de programar en Java, ni utilizar Eclipse.

Atención: Esto es un borrador, de modo que aún está en proceso de organización y escritura. Por favor, deja cualquier sugerencia en la sección de comentarios. 

El proceso en resumen


  1. Instalar Node.js
  2. Instalar Cordova
  3. Instalar Git
  4. Instalar SDK de Android
  5. Configurar Netbeans
  6. Crear proyecto HTML5 con Cordova
  7. Importar código de aplicación de Firefox OS existente
  8. Ejecutar aplicación en Android

El proceso en detalle










































martes, 21 de enero de 2014

¿Cómo responder a la pregunta de "Cuánto vas a tardar"?

Cartas para estimar la complejidad
Utilizando la técnica de Planning Pocker
Es inevitable. Te lo van a preguntar; y no importa cuanta información te falte: quien te pregunte "¿Cuánto vas a tardar?" querrá una contestación inmediata y no aceptará otra respuesta que una cifra. El asunto entonces es cómo responder rápidamente y con cierto criterio.

Negocia, calcula y argumenta


Para decir cuánto vas a tardar no vale mirar al cielo, esperar la inspiración divina y dar una cifra. Si dices un número sin más criterio que la "inspiración" o la "intuición", no podrás justificarlo cuando te rebatan la cifra diciendo que es muy grande.

Y lo harán, tarde o temprano.

Quien te pregunta cuánto vas a tardar, espera que le digas el menor número posible porque es tu cliente y quiere tenerlo cuanto antes y pagar poco, porque es tu jefe y quiere que termines pronto para asignarte a otras tareas, porque es un comercial y quiere que el producto sea "barato" para venderlo mejor...

El asunto es que debes asumir que en algún momento alguien dirá o pensará que te has pasado de lo que esperaba, cuando dices cuánto vas a tardar. De modo que, para darle credibilidad a tu respuesta y evitar o cambiar el criterio de tu interlocutor, deberías justificar el dato basándote en una estimación consensuada con tu interlocutor.

¿Cómo estimar rápidamente cuánto vamos a tardar?


Partamos del hecho de que estamos hablando de estimaciones rápidas, en momentos previos a la existencia del proyecto. De modo que queda absolutamente descartado cualquier método de estimación paramétrica como Puntos de Función, COCOMO, Puntos de Casos de Uso o, incluso, estimaciones más ágiles, como las basadas en Puntos de Historias de Usuario; primero, porque no se ha analizado suficientemente el problema como para descomponerlo al nivel que éstos métodos requieren y, segundo, porque no hay tiempo para hacerlo.

De modo que, para no adivinar, ni intentar aplicar unas métricas imposibles, una buena opción es hacer una estimación por analogía, haciendo una lista de los requisitos que se nos piden y asignándoles una complejidad a cada uno que, finalmente, traduciremos a un valor en horas.

Entonces, el proceso para estimar por analogía cuánto tardaríamos en hacer un desarrollo, podría ser el siguiente:

  1. Hacer una lista de los requisitos que nos han planteado.
  2. Buscar el requisito más simple que encontremos y calificarlo con la complejidad que estimemos.
  3. Seleccionar el siguiente requisito no calificado y asignarle una complejidad, teniendo en cuenta las calificaciones asignadas a los requisitos previamente analizados.
  4. Repetir el paso 3, hasta que no queden requisitos por calificar.
  5. Asignar un valor en horas a cada requisito, según su complejidad para pasar de un valor cualitativo de complejidad a uno cuantitativo de su duración.
  6. Sumar el total de horas teniendo en cuenta todos los requisitos.

Dicho así parece simple y, al mismo tiempo indefinido. ¿Qué complejidad asigno a un requisito? ¿Qué pasa si no tengo experiencia previa? ¿Qué cantidad de horas asigno a requisitos de determinada complejidad?

¿Cómo calificar la complejidad de un requisito?


Para simplificar la calificación, siempre partiremos del principio de que es más fácil calificar la complejidad de algo simple y conocido, que de algo complejo y desconocido

Por ese motivo, cuando se comienza a estimar, se parte buscando lo que parece el requisito más simple, intentando recordar si ya hemos hecho alguna vez algo parecido y cuán complejo fue; para asignar entonces a dicho requisito la misma complejidad que la de nuestras experiencias pasadas. Ahora, si no encontramos ninguna experiencia parecida, tendremos que descomponer este primer requisito (y solo este) hasta el punto de entender cómo podríamos desarrollarlo y, una vez entendido, estaremos en condiciones de definir la complejidad del mismo.

Una vez calificado el requisito más simple con un grado de complejidad, el resto se calificaría basándose en la experiencia y comparándolo con el requisito ya calificado sin necesidad de comprender a fondo las interioridades del mismo. Para ello, bastaría con responder a las preguntas:

  1. ¿Ya he hecho antes algo parecido? ¿Cuán complejo fue?
  2. ¿Este requisito es igual, más complejo o mucho más complejo que los anteriores?

Al final del proceso de calificación se obtiene una lista de requisitos cuya complejidad de implementación está justificada en nuestra experiencia y en el análisis realizado. Por supuesto, no es una estimación inmutable y, seguramente las estimaciones cambien, si repetimos el proceso varias veces o consultamos con otra persona. Sin embargo, es probable que estos cambios sean puntuales y con poca variación, sin grandes saltos, en sentido general.

¿Cómo cuantificar en horas la duración la complejidad?


Después de la cualificación, necesitamos cuantificar la complejidad para obtener un resultado en horas y poder responder a la pregunta de cuánto vamos a tardar para hacer determinado desarrollo.

Cuantificar a partir de datos previos


Lo ideal sería contar con estadísticas de proyectos anteriores. Tener una base de datos donde hemos ido guardando por cada proyecto realizado, la lista de requisitos, su complejidad estimada y su duración real.

Con estos datos, podríamos hacer una estimación del proyecto actual con unas cifras cercanas a nuestro desempeño medio y dar una estimación difícil de cuestionar porque, simplemente, negar las estadísticas sería poco razonable.

Cuantificar a partir de una duración "negociada"


Si no tenemos estadísticas que faciliten una cuantificación completa de todos los niveles de complejidad, podríamos, una vez más, apoyar la estimación en la adaptación del principio antes mencionado: es más fácil estimar la duración de algo simple y conocido, que de algo complejo y desconocido.

De modo que, partiremos asignando una duración en horas a la funcionalidad más simple del proyecto y negociaremos esa duración con quien nos ha pedido la estimación. 

Una vez consensuada la duración del requisito más simple, asignaremos duraciones proporcionales a cada complejidad.

Una convención generalmente aceptada es que a medida que aumenta la complejidad, la duración suele aumentar en una proporción mayor, debido a que mientras más complejo es lo que se estima, más imprecisa será la estimación y, por tanto, deberá admitirse un mayor margen de error.

Por ejemplo, algo simple, podría ser el doble de largo que algo muy simple y no, solamente, un poco más largo. De hecho, es frecuente considerar que, a medida que aumenta la complejidad, el tiempo estimado se duplique.

Algo a tener en cuenta es que el punto donde se asigna la primera estimación es clave pues, una vez nuestro interlocutor haya aceptado la estimación inicial, el resto se justificará en el propio sistema de estimación de la complejidad y la duración donde cada valor estará ligado al resto. 

Es decir, que el tiempo que tendrás que negociar será el de la funcionalidad más simple, en la que ambas partes podrán argumentar y justificar sus cifras y, una vez hecho, el resto de las estimaciones será una consecuencia coherente con esa estimación inicial y, por tanto, el resultado final será difícil de cuestionar pues estará basado en un valor consensuado.

Un ejemplo práctico


Supongamos que alguien nos pregunta cuánto tardaríamos en hacer una pequeña aplicación móvil para generar una alarma en caso de una emergencia. La idea es que el usuario pueda indicar un teléfono y que, en caso de emergencia, baste con abrir la aplicación para que ésta recupere el teléfono guardado y le envíe a dicho número un SMS con el texto "SOS" y un enlace a un mapa con la posición del usuario.

Lo primero sería listar las funcionalidades del sistema:


  1. Guardar teléfono de contacto para emergencias.
  2. Enviar SMS con mensaje y enlace a mapa con posición del usuario.

Sin embargo, la segunda funcionalidad, podríamos descomponerla en dos más simples y más fáciles de estimar: obtener posición del usuario y enviar SMS con un texto predeterminado. De modo que la lista de funcionalidades podría quedar así:

  1. Guardar teléfono de contacto para emergencias.
  2. Obtener posición del usuario.
  3. Enviar SMS.

Luego tendríamos que estimar la complejidad de cada una. Debido a que tenemos poca experiencia en desarrollos móviles (solo hemos hecho cosas básicas) estimamos que:


  1. Guardar teléfono de contacto para emergencias es "muy simple" pues ya hemos hecho antes otras aplicaciones de gestión de datos y guardar un solo dato en local es una tarea bastante sencilla. 
  2. Obtener posición del usuario es "muy complejo" porque -por lo que sabemos- hay que lidiar con distintos niveles de precisión en la localización, temas de batería y no lo hemos hecho nunca.
  3. Enviar SMS es algo "simple" pues, aunque no lo hemos hecho nunca, hemos leído algo sobre las APIs implicadas en las comunicaciones por SMS y parecen bastante fáciles de usar.

No obstante, nuestro potencial cliente nos dice que lo de la posición no debería ser "muy complejo" pues ya le hicieron anteriormente una aplicación con localización integrada y los desarrolladores le comentaron que era menos complejo de lo que parecía. De modo que, con la promesa de ponernos en contacto con esos desarrolladores para que os ayuden con las dudas que puedan surgir, acordamos bajar la complejidad del segundo punto de "muy complejo" a "complejo", quedando la complejidad por requisito así:

  1. Guardar teléfono de contacto para emergencias: "Muy simple" (XS). 
  2. Obtener posición del usuario: "Complejo" (L).
  3. Enviar SMS: "Simple" (S).

(Con el tiempo verás que es cómodo utilizar el sistema de tallas XS, S, M, L, XL y XXL para definir cualitativamente la complejidad de los requisitos.)

Ahora toca estimar cuánto tardaremos en implementar el requisito más simple: el número 1.

Dada nuestra experiencia, decimos que implementar la interfaz, guardar el dato y hacer las pruebas pertinentes, nos tomaría algo más de medio día de trabajo (5 horas, aproximadamente); pero nuestro cliente -siempre inconforme- protesta porque le parece excesivo 5 horas para algo "tan elemental"; así que nos enzarzamos en un debate sobre la calidad del software, la documentación que no ve el usuario final, las pruebas unitarias, los test exploratorios... y después de estirar y encoger las propuestas, quedamos en que 4 horas para el requisito 1 estarían bien.

Así que solo nos falta trasladar la duración en horas a cada requisito restante, partiendo de que cada requisito podría tomar el doble de tiempo que otro con una complejidad inferior. Es decir, si tuviéramos un requisito por cada complejidad, la duración de cada uno sería:


  1. Muy simple (XS): 4 h.
  2. Simple (S): 8 h.
  3. Medio (M): 16 h.
  4. Complejo (L): 32 h.
  5. Muy complejo (XL): 64 h.
  6. Muy muy complejo (XXL): 128 h.

Lo que en nuestro caso, significaría una duración en horas por requisito de:


  1. Guardar teléfono de contacto para emergencias: "Muy simple" (XS), 4 h.
  2. Obtener posición del usuario: "Complejo" (L), 32 h.
  3. Enviar SMS: "Simple" (S), 16 h.

Lo que en total, nos daría una duración de 52 horas o 6 días y medio, ideales; es decir, 6 días y medio si trabajáramos 8 horas exclusivamente en el proyecto.

No obstante, para ser realistas, de las 8 horas diarias, es muy probable que perdamos 1 o 2 horas en comunicaciones (e-mails, llamadas telefónicas), o interrupciones varias (consultas, incidencias con otros productos, etc.). De modo que, siendo objetivos,  aunque el tiempo de desarrollo serían 52 horas, el tiempo para entregar el producto sería de casi 9 días.

Un par de aclaraciones útiles


Las estimaciones de requisitos muy complejos son malas


Volvamos a la lista de tiempos por complejidad enunciada para el ejemplo anterior y fijémonos cómo, a pesar de que el requisito más simple dura solo 4 horas, el más complejo puede parecer excesivamente extenso.

  1. Muy simple (XS): 4 h.
  2. Simple (S): 8 h.
  3. Medio (M): 16 h.
  4. Complejo (L): 32 h.
  5. Muy complejo (XL): 64 h.
  6. Muy muy complejo (XXL): 128 h.

Ese contraste es, justamente, lo que nos ayudará a hacer estimaciones más realistas pues, a medida que aumentemos la complejidad de un requisito, estamos diciendo que sabemos poco de él y que, por tanto tenemos menos idea de cuánto va a durar su desarrollo y, por ende, que estamos siendo imprecisos.

De modo que, si tienes un requisito estimado como "muy muy complejo", es sinónimo de que deberías descomponer ese requisito en otros menos complejos que puedas entender mejor y, por tanto, estimar mejor.

Demasiadas estimaciones de requisitos muy simples son malas


Esto podría parecer una contradicción con la afirmación anterior, pero no lo es. Es mejor tener requisitos con estimaciones de complejidad pequeña, que estimaciones de complejidad muy grande porque significa que seremos más precisos a la hora estimar la duración de los mismos.

Sin embargo, no es frecuente que tengamos información tan detallada como para comprender a fondo todos los requisitos y evaluarlos con complejidades simples. De hecho, es muy frecuente que cuando estemos generando estimaciones, subestimemos la complejidad de las mismas y generemos estimaciones a la baja.

Por eso, si tienes muchas estimaciones de requisitos muy simples, deberías reevaluarlas con detención intentando ver posibles riesgos que podrías estar pasando por alto.

Conclusiones


Lamentablemente, en muchas ocasiones que nos piden estimar cuánto vamos a tardar en un desarrollo, no disponemos de la información ni el tiempo suficiente como para aplicar un método de estimación que tenga en cuenta la mayor cantidad de variables posibles y, en su lugar, debemos apoyarnos en la experiencia y unos principios simples que nos permitan hacer unas estimaciones que, si no son tan precisas, al menos sean justificables; porque, sin olvidar que cualquier estimación de tiempo en una fase temprana y con poca información de base puede tener una desviación grande del resultado final, siempre será mejor una estimación argumentada que una "corazonada".

martes, 14 de enero de 2014

¿Dónde publicar mi primera aplicación móvil hecha con HTML5?

Aplicación ejecutándose en BlackBerry 10, Tizen 2.2 y Firefox OS 1.2

Es un echo que las tecnologías Web ya no son solo para hacer "páginas Web". Los principales sistemas operativos móviles soportan, de una forma u otra, aplicaciones basadas en HTML, CSS y JavaScript; sin embargo, crear una aplicación móvil con estas tecnologías puede variar mucho de un sistema a otro. Por eso, si eres un desarrollador Web que quiere publicar su primera aplicación móvil, podrías comenzar por el sistema que te lo ponga más fácil para enfrentarte, después, a los más populares pero más complejos.

HTML5 embebido


Aunque cada vez sea más frecuente ver apliaciones móviles desarrolladas con HTML5, los sistemas operativos móviles más populares (iOS y Android) no soportan la creación de aplicaciones con esta tecnología, por lo que es necesario crear una aplicación con la tecnología específica de la plataforma para encapsular nuestro código "Web".

De modo que, para crear una aplicación para iOS o Android, utilizando HTML, CSS y JavaScript, primero habrá que crear una aplicación utilizando Objective C, en iOS o Java, en Andrid para embeber en ésta, nuestra aplicación HTML5. Por ese motivo, ni Android ni iOS son buenas elecciones para generar nuestra primera aplicación móvil, si todo lo que conocemos es HTML, CSS y JavaScript.

HTML5 nativo


Al contrario de los sistemas más populares ya mencionados, los SO móviles que han ido apareciendo más recientemente incorporan las tecnologías Web como herramientas naturales para la creación de aplicaciones, soportando el acceso directo al hardware del dispositivo desde APIs de JavaScript. Sin embargo hay diferencias marcadas entre uno y otro a la hora de generar la aplicación final.

Windows Phone y BlackBerry 10 son los que siguen a los significativamente más pupulares iOS y Android; mientras Tizen y Firefox OS son los nuevos contendientes que pretenden encontrar un hueco en el mercado y, para ello, intentan atraer a los desarrolladores poniendo a su disposición las mejores herramientas que pueden. De modo que, si eres un desarrollador Web, podrás crear aplicaciones móviles con tecnologías conocidas, de forma mucho más natural con cualquiera de estos sistemas.

Ahora, cada plataforma tiene más o menos requisitos para generar las aplicaciones que pueden representar una barrera para un desarrollador Web, adaptado a la libertad de utilizar cualquier editor, con cualquier navegador, en cualquier sistema:


Sin embargo Firefox OS, es el único sistema de estos que es absolutamente fiel a la filosofía Web: para generar una aplicación móvil para Firefox OS no es necesaria ninguna SDK, ni ningún sistema operativo en particular, ni ningún editor específico. De modo que, para cualquier desarrollador Web que quiera generar su primera aplicación móvil, el sistema con la menor barrera de entrada es Firefox OS.

Por dónde empezar


Claro está que Firefox OS no es el SO móvil más popular: a penas está comenzando y aún es bastante raro ver móviles con dicho sistema. Sin embargo, aquí no hemos pretendido escoger el sistema más popular para publicar aplicaciones, sino el que haga más fácil la tarea de generar una aplicación móvil con HTML5 a un programador Web que está empezando en el desarrollo móvil y eso, en Firefox OS, es tan fácil como compactar nuestro proyecto Web en un .zip que tiene un fichero de texto con una estructura muy simple y fácil de generar.

Si en este punto te ha parecido que va a ser fácil no te quedes en la suposición y compruébalo siguiendo alguno de estos tutoriales:


Y si quieres más, entonces el centro de referencia está en https://marketplace.firefox.com/developers/, donde encontraras toda la documentación que puedas necesitar.