jueves, 16 de febrero de 2023

Aprendiendo Inglés: pasar del B2 al C1

El leitmotive de este blog es, supuestamente "Sobre software, tecnología, aprendizaje... y lo que surja."; pero desde hace tiempo casi solo escribo sobre mi proceso para aprender inglés, dejando avandonados los temas de software y tecnología.

Parecería que no he hecho o aprendido nada más interesante, pero no es así. De hecho, en los últimos años he tenido que estudiar nuevas tecnologías, además de prepararme para afrontar las entrevistas que me llevaron a lograr un contrato en una FAANG, superando no solo el intenso proceso de las entrevistas, sino el aún más intenso (si cabe) período adaptación y de prueba. 

De modo que, si vuelvo a escribir sobre mi proceso para aprender inglés, es porque creo que ha sido el reto más grande que he tenido en los últimos años. Y no porque "el inglés se enseña mal", sino porque no hay fórmulas mágicas y esto lleva esfuerzo. Mucho esfuerzo. Y si te dedicas al 100% puede que lo hagas en menos tiempo y si no, como en mi caso, puede que te tome años.

Llegar al B2 no es lo mismo que tener el B2

Desde mi último post, de hace casi 2 años, decía que había llegado al B2, usando Busuu.com y que no me sentía realmente con ese nivel, por lo que tal vez, buscaría unas vías más formales para seguir estudiando.

Después de eso, empecé a estudiar usando Lingoda.com, una academia online, donde tienes un programa muy bien definido por niveles, con profesores nativos, clases en grupos muy reducidos (de hasta 5 estudiantes) y mucha flexibilidad para escoger cuándo tomar las clases.

Como no me sentía que "tuviera" el B2, en lugar de empezar por el C1, empecé por el principio del B2, así que tomé mi primera clase del B2.1 el 24 de junio de 2019. Lingoda divide cada nivel en 3 subniveles, para dosificar las horas que tienes que dedicarle a cada uno y poder ver algún progreso. 

Gráfica de barras con la cantidad de horas de clase por mes del 2019 a 2022
150 horas clase distribuidas por mes del 2019 al 2022

Me tomó 2 años y 9 meses, hasta el 28 de marzo de 2022, para terminar los 3 subniveles hasta el B2.3 y las 150 horas de clases "formales" para consolidar el B2. En todo ese tiempo, tuve meses de muy poca actividad y otros más intensos. Promediando unas 4,5 clases al mes. De modo que, con toda seguridad, si me hubiera enfocado, habría reducido ese tiempo significativamente.

Pero eso no pasó, porque justo eso es lo difícil de aprender inglés: que toma mucho tiempo y lo más difícil es mantener el foco y ser constante. No puedes concentrar el aprendizaje y hacer 8 horas diarias para asimilar esas 150 horas en 3 semanas; aunque tampoco tiene que tomarte una eternidad, como a mi.

Casi 3 años después de "llegar" el B2, ahora podía decir que finalmente "tenía" el B2 (que no es lo mismo). Y podía decirlo no solo porque lo dijera un certificado de Busuu y otro de Lingoda, sino porque lo decía la práctica. Desde el verano del 2021 había empezado a trabajar en Amazon y el trabajo requería hablar y escribir en inglés todos los días. Mis compañeros eran de todas partes: egipcios, polacos, rusos, indios, búlgaros, alemanes, americanos, portugueses, italianos, chinos y muchas otras nacionalidades que solo tenían en común el idioma oficial en la empresa: el inglés.

Así que, a fuerza de sufrir para vencer mis inseguridades, después de un año y medio escribiendo y hablando cada día en inglés, podría decir que ese B2 no era solo un premio de consolación de dos plataformas de aprendizaje online, sino algo palpable y práctico en un entorno laboral con el inglés como lengua franca.

Sin embargo, a pesar de haber "llegado" a mi objetivo inicial de alcanzar el B2, cuando creía que lo tenía, empecé a sentir que no era suficiente.

Un día, luego de preguntarle a algunos de mis compañeros sobre en qué creían que yo debía trabajar para mejorar, uno me dijo que se me notaba poco fluido, indeciso y que me costaba encontrar las palabras o expresiones cuando hablaba, por lo que daba la impresión de tener poca confianza.

En mi cabeza, mi forma de hablar era consecuencia de una pausa consciente para no cometer el error (bastante común en hispanohablantes) de intentar hablar rápido para aparentar fluidez, pero está claro que la impresión que estaba causando era justamente la contraria: la de hablar con pausas por no tener fluidez. De modo que me propuse seguir, no conformarme con el B2, sino trabajar para mejorar la fluidez y seguir progresando en la complejidad de mis expresiones.


Buscando tener el C1

De modo que el B2 ha demostrado ser un nivel suficiente para trabajar a diario, en inglés, en una empresa internacional. Con lo que Bussu y Lingoda demostraron ser una buena opción para estudiar y alcanzar ese nivel. Sin embargo, mis compañeros notaron esa falta de fluidez y vocabulario que a pesar de no ser un impedimento para hacer mi trabajo, podría estar limitando mi progresión u otras áreas que ni siquiera soy capaz de ver, justamente por las limitación aún tengo.

Así que sigo en Lingoda, no solo para mejorar la fluidez, sino para continuar aprendiendo y formalizar los conocimientos.

Seis meses después de terminar el B2.3, completé el C1.1 y estoy empezando el C1.2, con pleno entendimiento de que solo tomar clases ya no es suficiente y que tengo que hacer un esfuerzo consciente para mejorar la fluidez y el vocabulario. Además, aunque no lo necesite en absoluto porque en el mundo laboral vale más una conversación que un título, estoy planteándome hacer las pruebas oficiales para certificar el C1 y así autoimponerme una fecha que me fuerce a estudiar y prevenga que me pase 2 años más para mejorar el nivel.

Veremos cuándo termino y con qué resultado.

sábado, 22 de junio de 2019

Aprendiendo inglés: llegar al B2, subir y caer

Certificado de McGraw-Hill Education
al terminar el test del B2 en Busuu
Ya está, he completado el B2. Se acabó Busuu. Ya no hay más niveles ahí. Como se dice: me he pasado el juego completo. ¿Y ahora qué?

Hace más de 2 años y medio que empecé mi viaje para mejorar mi inglés, usando la plataforma Busuu.com. Durante ese tiempo he abandonado los estudios y los he vuelto a retomar. He estudiado durante unas pocas semanas en 2 academias de mi barrio, he regresando a Busuu, y viajado 2 veces a Irlanda para vivir la experiencia de una inmersión lingüística.

Durante ese tiempo, han sido mayores los meses de inactividad que de estudio pero, al final, he alcanzado mi objetivo inicial de terminar el B1 y lo he sobrepasado terminado el B2.

Sin embargo... ahora que "supuestamente" he formalizado un B2, no estoy satisfecho. Ahora soy mucho más consciente de los errores que cometo y tengo la sensación de que mi B2 es "de cartón".

La sensación de mejora


Sí es cierto que mi inglés ha mejorado mucho. La semana pasada viajé a Grecia para asistir al evento DEVit 2019. Como era en Grecia todas las charlas fueron en inglés. Los patrocinadores y todas las personas implicadas en la organización hablaban en inglés y, por si fuera poco, para subir a un autobús, pedir comida o preguntar por un lugar, debía hacerlo en inglés.

Durante esos días Google Photos me refrescó la memoria con esa funcionalidad tan oportuna de recordarte que "un día como hoy, hace tres años" estaba en Berlín. Aquél viaje fue para participar en el hackathon Spacehack organizado por WELCOME con la cooperación de Facebook (entre otros).

El viaje a Berlin lo recuerdo muy diferente: me costaba comunicarme, tenía que pedir que me repitieran lo que me decían una y otra vez y, como consecuencia, no hacía mucho esfuerzo para hablar y comunicarme.

Este viaje a Grecia, tres años después, fue diametralmente opuesto. Seguro cometí mil errores cuando hablaba y, por supuesto, entendía como mucho el 70 o el 80 por ciento de lo que escuchaba... pero la comunicación fluyó. Esta vez, sentí autonomía y confianza para hablar y escuchar casi a cualquier persona.

En la charla y durante los días posteriores escuché y hablé con personas de acentos de lo más variopintos. Durante la semana intercambié con personas de Estados Unidos, Inglaterra, Polonia, Bulgaria, Rumanía, Italia, Israel, Turquía y, por supuesto, Grecia.

Así que puedo decir con total certeza que en el lapso de 3 años, mi oído ha mejorado y la soltura para halar (sin temor a cometer errores) también lo ha hecho.

La sensación de incompetencia


Durante estos dos últimos años, a medida que mi inglés ha mejorado, ha aumentado también la percepción de mis errores y limitaciones.

Desde hace unos meses tenemos una nueva profesora irlandesa en las clases que recibo una vez por semana en la empresa. Con ella empezamos a hacer énfasis en la pronunciación y el vocabulario y, desde entonces, en cada clase, tengo la sensación de que deberían cambiarme a un grupo de menor nivel.

Lo de hablar, explicar, argumentar, rebatir y discutir sobre cualquier tema lo he mejorado significativamente; pero sigo cometiendo errores de principiante que lastran mi sensación de mejora.

Y no se qué hacer.

Desde el año pasado escucho con regularidad, casi a diario, podcast en inglés y la mayoría del contenido de Youtube que consumo está en inglés.

Y sigo cometiendo los mismos errores.

¿Y ahora qué?


No sé si habré alcanzado mi nivel máximo de incompetencia en el inglés o es que va siendo hora de buscar una vía de estudio más formal.

En los meses que siguen intentaré aumentar las horas de formación guiada con clases y Meetups de idiomas. Para finales de año, volveré a reflexionar sobre el tema y revaluar el progreso.

domingo, 28 de abril de 2019

Aprendiendo inglés: cómo preparé y terminé el B1

El 3 de diciembre del 2018 comencé las lecciones del B1. Un año y medio antes había completado el A2 por lo que necesité un calentamiento previo, antes de retomar los estudios.

La planificación del estudio


Cuando planifiqué el B1, estimé que tardaría 2 sesiones de estudio por lección. Dado que el nivel tenía unas 20 lecciones, tardaría cerca de 2 meses para completarlo. Para esa estimación asumí que el B1 sería más duro que el A2 pero no mucho más pues un test en la propia plataforma y otras pruebas previas de distintas fuentes ya me había dado un B1como mi nivel actual.

Para dar seguimiento al progreso hice un gráfico burn down porque, psicológicamente, me ayuda a motivarme tanto si voy bien como si voy mal. Si voy bien, me estimula a mantener el ritmo y si voy mal me recuerda, cada vez que abro a la nevera, que tengo que volver al trabajo.

Esta vez, además del trabajo pendiente, añadí el tiempo invertido en cada lección; marcando además en línea discontinua si la sesión de estudio había sido por la noche.

Cuanto tardé realmente


Progreso de estudio del B1: en negro lo estimado y en azul el progreso real
 
En la planificación pasé por alto un detalle importante: el fin de año estaría en medio del proceso de estudio y, por ende, era muy probable que durante al menos una semana no hiciera absolutamente nada. No obstante, a pesar de esa semana sin estudiar, tardé menos de lo esperado.

La estimación inicial de 2 días de estudio por lección se pasó de largo y, al final, necesité un día por lección, igual que con el A2. Así que terminé el contenido justo cuatro semanas después de haber empezado.

Después del parón de navidad, invertí una semana para repasar los contenidos y el vocabulario. El 14 de enero, 11 días antes de lo planificado, hice el examen y completé el nivel B1 de inglés en Busuu. En resumen:
  • Invertí un día por lección
  • Necesité una semana extra para "repasar" los contenidos
  • Cada día estudié unos 45 minutos
  • Uno de cada cinco días me salté el estudio matutino y necesité recuperar por la noche

Ya tengo el B1... ¿y ahora qué?


Cuando comencé a estudiar en Busuu, pensaba que mi meta estaba en "formalizar" un B1 pero un amigo me incentivó a no quedarme ahí. Con el tiempo, a medida que progresaba, me iba dando cuenta de que tenía razón: un B1 estaba bien para sobrevivir, pero no era suficiente para tener un nivel de competencias decente en un entorno laboral donde se hablara exclusivamente en inglés. Así que, al mes siguiente del terminar el B1, comencé con el B2.

Curiosamente mientras más he avanzado en los estudios mi sensación de incompetencia con el idioma ha avanzado también. En las clases de conversación que recibo en la empresa me doy cuenta de cuan mal pronuncio y que, muy a pesar de los estudios y exámenes, sigo cometiendo errores de principiante.

Solo espero que, con el tiempo, todo vayan mejorando.

¡Más me vale!

jueves, 20 de diciembre de 2018

Liberando CSAcademia como proyecto open source... 5 años después y 6.000€ de menos

CSAcademia es una herramienta para gestionar la información de profesores y estudiantes de una academia. El nombre no es muy original pero el software funciona, lleva en uso 5 años... y ahora es open source.

¿Cómo se nos ocurrió hacer un software de gestión académica?


Este proyecto comenzó al final del verano del 2012, con la solicitud de un posible cliente que quería remplazar el ya obsoleto software de gestión de su academia. Una vez entendidas sus necesidades y visto el software existente, hicimos una propuesta de remplazo con un plan de entrega y un presupuesto ajustados. Sin embargo, dado que el curso académico había comenzado recientemente, no llegamos a ningún acuerdo hasta el final del invierno, en Marzo del 2013.

Hicimos el primer commit el 12 de marzo de 2013. Durante los siguientes meses trabajamos dos personas unas 10 o 12 horas por semana (cada una), principalmente por las noches y los fines de semana. Cinco meses después, a finales de agosto, teníamos una versión del sistema funcionando y con datos de la primera academia. De modo que se empezó a usar con el comienzo del curso académico de 2013 - 2014, en paralelo con el sistema existente, para ir reemplazándolo poco a poco.

Actualmente es una herramienta de uso diario en la academia Dundee School of English.

Módulo de gestión de profesores

¿Cuánto ganamos con este software por encargo?


La idea inicial no era ganar dinero con la "venta" del sistema, sino cobrar lo suficiente para motivarnos y amortizar parcialmente el esfuerzo de desarrollo, con la esperanza de generar ingresos a largo plazo. Pretendíamos promocionar la aplicación entre otras academias y cobrar una cuota por uso. Por eso hicimos el ejercicio de estimar el esfuerzo y luego lo ajustamos a la baja y, por si fuera poco, añadimos una rebaja significativa. Pedimos finalmente 3.280 €, a pagar en 3 plazos de 40% al inicio del desarrollo, 40% con la puesta en marcha y 20% al finalizar la formación del personal que usaría el sistema.

Volumen de trabajo estimado por mes,
según Gitential.com, en base a los commits
Tardamos 6 meses en tener el software suficientemente completo y casi un año en terminar los pequeños ajustes y solicitudes que aparecieron sobre la marcha. Durante los primeros meses, acumulamos unas 480 horas de trabajo que, estimadas a 20 € la hora, resultaría en un esfuerzo de unos 9.600 €.

Nunca recuperamos ese dinero.

Ninguna otra academia se enteró de la existencia del sistema así que nuestros ingresos fueron los acordados inicialmente con el cliente. Con el tiempo, añadimos algún que otro módulo que cobramos también a precios ridículamente bajos porque siempre albergamos la esperanza de licenciar el uso a otros centros.

De modo que, financieramente hablando, perdimos dinero con este software.

Pasando a ser Open Source


Después de reflexionar sobre las ventajas y consultarlo con nuestro (primer y único) cliente, decidimos hacer público el código fuente del sistema. El objetivo principal es ponerlo a disposición de cualquiera que pudiera necesitarlo y facilitar las aportaciones de colaboradores para garantizar la evolución y el mantenimiento del mismo. Hoy CSAcademia está disponible en GitHub:

https://github.com/casabesoft/csacademia

No ha sido un camino de rosas. Publicar el código nos trajo algunos problemas y preparar el repo para hacerlo público ha costado varias noches y fines de semanas durante los últimos cinco meses.

Pero ahí está, con una lista de 19 issues abiertos, listo para seguir recibiendo amor. Así que si eres desarrollador y quieres colaborar puedes empezar leyendo la sección de Contributions.

Si no sabes programar, pero has llegado hasta aquí buscando un software para tu academia o centro de estudios, adelante: es gratis y libre para su uso comercial sin coste alguno. Además estaremos encantados de ayudarte para que puedas ponerlo a punto y usarlo.

No obstante, si no tienes el tiempo, los recursos o el conocimiento para instalarlo y prefieres una solución lista para ser usada, prueba con https://academia.casabesoft.com; daremos de alta tu centro y en unos minutos podrás empezar a probar.

En cualquier caso... ¡Que aproveche!

jueves, 6 de diciembre de 2018

Aprendiendo inglés: calentamiento previo al B1

Estaba decidido a retomar los estudios. Pagué la suscripción de un año en Bussu. Entré en la Web y... algo me impidió empezar. No era un problema técnico. Era yo. Aunque quería hacerlo no debía empezar con el B1. Aún no. No era el momento.

. . .

Eso (o más o menos eso) fue lo que pasó en el verano; cuando decidí que debía retomar los estudios en Busuu. Al entrar, después de un año y medio, descubrí que la plataforma había cambiado y, con los cambios, aparecieron contenidos nuevos. Aunque ya había completado el A1 y el A2 en el año anterior, ahora lo nuevo me forzaba (moralmente) a repasar estos niveles, antes de seguir adelante.

En total, tan solo en el A2, tenía 23 lecciones incompletas de las 30 que pasó a tener el nivel (26 de contenido y 4 de repaso). Restando todo lo nuevo, mi A2 se redujo hasta el 47% de progreso. Como si me faltaran por hacer 16 lecciones enteras.

Completando las actividades nuevas del A1 y el A2

 

Lista de lecciones, % pendiente y tiempo dedicado
Las actividades pendientes del A1 eran pocas y las terminé más o menos rápido. Para el A2 hice una lista con todo lo que faltaba y la puse en la puerta de la nevera para tener el progreso o el retraso siempre presentes. Cada vez que terminaba una lección apuntaba cuánto tiempo tardé en completarla y qué día lo hice.

En resumen: me tomó 13 días, dedicando unos 34 minutos diarios.

Fue más rápido de lo que esperaba. Probablemente porque casi no tuve que hacer ejercicios de redacción o expresión oral, que suelen ser los que más tiempo me toman.

Comenzar con el B1


Para el B1 voy a hacer una pequeña variación en la estrategia: seguiré estudiando al menos 30 minutos cada mañana, pero introduciendo la práctica del vocabulario en la la rutina diaria.

Hasta ahora había dejado el vocabulario para los últimos días, cuando estaba a punto de terminar el nivel y, sobre todo, los fines de semana. Hora tengo reservados 15 minutos adicionales de "colchón" de tiempo antes de salir al trabajo. Así que, los días que pueda, haré uso de ese tiempo extra avanzando en las lecciones y repasando el vocabulario.

¿Cuánto voy a tardar en completar el B1?


El B1 es el tercer nivel del Marco Común Europeo de referencia para las lenguas. En la web oficial de Exámenes de Cambrige y en la del British Council (entre otros lugares) se dice que cuesta entre 180 y 200 horas alcanzar el A2 y entre 350 y 400 tener un B1, si se parte de cero. De modo que deberíamos emplear entre 170 y 200 horas pasar de un A2 a un B1.

A 5 horas por semana (20 horas por mes) tardaría entre 8 y 10 meses. ¡Todo un año!

Pero eso sería en el supuesto caso de no tener ninguna idea de los contenidos del B1 y, por suerte, esa no es mi situación. Así que, basándome en mi progresión previa de casi un día y medio por lección y que el B1 en Busuu tiene 20 lecciones (18 de contenido y 2 de revisión), debería tardar unos 30 días de estudio.

No obstante, asumiré que el B1 será más duro y tardaré 2 días por lección, 5 lecciones cada 2 semanas y 2 meses para completar el nivel.

¡Ya veremos!

domingo, 18 de noviembre de 2018

Aprendiendo inglés: 18 meses y 1700 euros después

En abril del año pasado dije que en marzo empezaría a estudiar el B1 de inglés. Después de 1700 euros y 18 meses aún no he empezado. Pero el gasto y la espera no han sido en vano. Dos viajes a Irlanda y pasar por tres academias han servido para algo, aunque no sea estudiar formalmente el B1.

En un post de abril del 2018 comentaba cómo escogí dónde estudiar inglés y cuánto tiempo me costó completar los 2 primeros niveles (A1 y A2). Además, describía cómo me organicé para estudiar y mantenerme motivado. Aquél post terminaba con un compromiso que no cumplí: comenzar el nivel B1 de inglés en marzo y comentar los resultados.

No obstante no haber cumplido el compromiso, estuve estudiando. Después del intento frustrado de pasar una semana en una academia en Dublin, pasar un mes en una academia en Madrid, una semana en otra academia en Dublin y un par de meses en otra academia en Madrid... he vuelto a los orígenes: Busuu.

Los viajes y las academias


Academia Your English Language School, en Dublin


En octubre de 2017 viajé por primera vez a Irlanda. Lamentablemente el viaje se vio frustrado por una tormenta que paralizó medio país, obligó a cerrar los centros de estudio y me retuvo en mi habitación de Airbnb durante 2 días. Así que mi primera estancia en Dublin no incluyó formación alguna. No obstante, regresé decidido a hablar y escuchar más inglés, matriculando un mes después en una academia en Madrid, cerca de casa.

Duré poco allí: el grupo era muy heterogéneo y no sentía que avanzaba al ritmo que esperaba. Así que antes de terminar el mes, lo había abandonado.

Mientras tanto, me mantenía con la clase semanal que recibo en el trabajo, cada jueves. Pero como una hora a la semana no es suficiente y me había quedado con ganas en el viaje a Dublin, en la primavera del 2018 me fui otra vez a Irlanda.

Esta vez sí pude materializar la formación. Una semana con 5 horas al día en la escuela más otras tantas de parloteo extra no me cambiaron de nivel, pero me ayudaron a conocer mejor mis fortalezas y debilidades con el idioma. En la escuela me evaluaron como un B1 y me ubicaron en un grupo con compañeros que iban del B1 al B2.

A mi regreso a Madrid estaba otra vez convencido de la necesidad de escuchar más inglés, así que en junio había comenzado en otra academia. Ésta tenía un sistema muy parecido a la de Dublin pero la exigencia no era la misma: de entrada me asignaron un B2 y me pusieron en un grupo, otra vez, muy heterogéneo.

En esta academia duré un poco más, pero no llegué a completar los 3 meses.

Para septiembre estaba otra vez limitado a solo una hora semanal de clases, en la oficina; aunque, esta vez, compaginadas con el "listening" matutino de las noticias de la BBC y algunas estaciones de radio locales de Irlanda. No obstante, esto no era suficiente; así que decidí retomar los estudios en casa.

¿Cuánto me costó darme cuenta de que debía volver a mi estrategia inicial?


Entre los 2 viajes a Irlanda y las 2 academias en Madrid gasté algo más de 1700 €.

  • Viaje de 2017: 550 € de hospedaje + transporte
  • Academia Madrid 2017: 124 € de matrícula + 1 mes
  • Viaje 2018: 650 € de academia + hospedaje + transporte
  • Academia Madrid 2018: 425 € de matrícula + 3 meses

Por otra parte, los 69,99 € de una suscripción anual de Busuu me darían acceso a las funcionalidades y contenidos de pago en cualquier momento y durante todo un año. Con esa cuota anual no podría pagar siquiera un mes en la academia más barata. Sin embargo, estudiar 30 minutos cada mañana seguía siendo la estrategia que mejor me había funcionado.

Por supuesto, no se puede sustituir un profesor real con una plataforma de autoaprendizaje.

Un buen profesor y un buen grupo de estudio son insustituibles. Pero mis limitaciones de horario y las opciones que tenía disponibles, me hicieron decantarme por el autoestudio, otra vez.

Retomando los estudios en Busuu.com


Dieciocho meses después, he reiniciado los estudios matutinos con la intención de formalizar ese supuesto nivel B1. Durante estos meses la plataforma se ha renovado, han añadido contenidos nuevos y nuevas funcionalidades.

Tengo hasta el verano del 2019 para intentarlo otra vez. Mientras tanto, seguiré con mi clase semanal en la empresa, escuchando la radio de vez en cuando y viendo las películas y series que pueda en versión original.

Si no vuelvo a distraerme, estaré escribiendo en breve sobre cómo ha sido la vuelta y el progreso.

martes, 25 de abril de 2017

Aprendiendo inglés: cuánto me ha costado y cuánto me falta

A finales del año pasado decidí que no podía seguir postponiendo el inglés como materia de estudio que tenía pendiente desde hacía mucho, mucho tiempo. Así que me propuse que en el 2017 dedicaría tiempo, con regularidad, para estudiar inglés.

Escogiendo dónde estudiar


A finales de diciembre hice un repaso de algunas academias que me quedaban cerca del trabajo y la casa. Después de descartar algunas más caras (no por el precio sino por mi absoluta falta de fe en mi propia capacidad de persistir) visité las academias que tenían mejor relación precio / calidad / cercanía para minimizar las posibles pérdidas en tiempo y dinero si abandonaba antes de lo esperado.

Así que, con un par de academias en la mira, pasó el fin de año y, con él, la tendencia impulsiva de apuntarme en una de ellas por las simples "ganas" de mejorar mi inglés.

Ese tiempo me sirvió para reflexionar y adoptar una estrategia más conservadora y realista: aprovecharía un curso online que ya había pagado y no estaba utilizando; de modo que, si me demostraba a mi mismo que estaba dedicando varias horas a la semana, con regularidad, podría dar el paso siguiente y apuntarme a un curso regular que requeriría tiempo para trasladarse, ser más constante... y sería más caro.

Así que retomé las lecciones en Busuu.com, una plataforma para aprender inglés, parecida a Duolingo.com o Babbel.com.

La estrategia de estudio


Como mi objetivo primario era crearme el hábito de estudio y mi horario estaba bastante ajustado solo tenía una opción: levantarme más temprano para afrontar como primera tarea del día el estudio de inglés. Así que, para comenzar, decidí que intentaría dedicar 30 minutos cada mañana, de lunes a viernes.

Por otra parte, necesitaría un mecanismo para autocontrolarme y verificar mi progreso. Así que comencé a plasmar las lecciones vencidas y el tiempo dedicado cada día en un gráfico que pegué con imanes a la puerta de la nevera, de modo que mi progreso -o la falta de él- estaría presente cada día, a la vista, para estimularme a seguir y evitar caer en el abandono.

Finalmente, muy a pesar de que mi ego me tentaba a comenzar a estudiar por el nivel B1, decidí (por suerte) comenzar desde el principio, repitiendo, incluso, algunas lecciones que ya tenía vencidas.

El progreso


El nivel A1 fue rápido pero no controlé el tiempo desde el principio, ni con detalle: solo apunté las lecciones vencidas, a partir de la 8va lección. Así que como terdé 9 días para las últimas 11 lecciones, debería haber tardado, aproximadamente, unos 16 días para completar las 19 lecciones del nivel. Y ya que, en ese período, estudié también los sábados, habré empleado 2 semanas y media para completar el A1.

El nivel A2 fue más lento y controlé el tiempo dedicado cada día, incluyendo los días que debí estudiar y no lo hice. De modo que, cuando pasaban varios días sin estudiar, el gráfico de mi vagancia me daba una bofetada, cada vez que abría la nevera.

Como era de esperar, el nivel A2 no fue tan bien como el A1 y, para colmo, tuve algunos bajones en el estudio que el gráfico sacó a relucir muy bien y, gracias al cual, no fueron a peor. De modo que, al final, dediqué 26 días a lo largo de casi 2 meses, para las 19 lecciones, haciendo un total de 18 horas o, lo que es lo mismo, unos de 42 minutos de promedio, por día.

Lo que falta


Me he propuesto terminar el nivel B1 en Busuu.com antes de probar con la formación presencial. Así que, como mínimo, intentaré con este nivel antes de dar el salto. No obstante, dado que ahora estaré cerca del tope de mi nivel actual, seguramente avanzaré más lento, acercándome más a las cifras que se dan en algunos post y que serían unas 200 horas para pasar del A2 al B1.

Entonces, empezaré el B1 en mayo y, cuando termine, pondré por aquí el tiempo y el esfuerzo real que me tomó.


lunes, 6 de febrero de 2017

Liberando VirtualMenu como proyecto open source

VirtualMenu es un software para la gestión de parte de un servicio de catering como la gestión de platos, planificación de menús y recogida de pedidos.

Diseño de un menú del día

VirtualMenu surgió en la primavera del 2012, como una prueba de concepto para un restaurante que tenía un servicio de catering cuya oferta del menú se hacía por correo electrónico para recibir posteriormente los pedidos por e-mail o teléfono. Por supuesto, el uso de distintos canales y la falta de automatización provocaba confusión en los clientes y problemas de gestión del restaurante generando pedidos erróneos y algún que otro olvido.

El desarrollo lo hicimos entre 2 personas, en unas 2 semanas, distribuidas a lo largo de 3 meses: unas 160 horas de trabajo que, estimadas a 20 € la hora, resultaría en un prototipo de 3200 €... que nunca se llegó a utilizar.

No obstante, 5 años después, hemos decidido sacar del olvido este producto pues la necesidad que lo hizo nacer sigue existiendo. Hoy, sin embargo, resurge como un proyecto abierto y gratuito. Disponible para su descarga y evolución en GitHub:

https://github.com/casabesoft/virtualmenu

Así que, si eres diseñador, programador o tienes cualquier idea y quieres colaborar: bienvenido, hace falta mucho trabajo para actualizar y "embellecer" un producto que no se había tocado en 5 años.

Igualmente, si tienes un restaurante o una empresa de catering y estás interesado en usarlo, adelante: es gratis, puedes descargarlo, usarlo con fines comerciales y hacer lo que mejor estimes conveniente.

lunes, 1 de agosto de 2016

¿Cómo ser programador? ¿Existe alguna guía?

Saber mover las piezas, no te hace ajedrecista; saber tocar el piano no te vuelve concertista... y saber programar no te convierte en programador. ¿Cómo se aprende, entonces, a ser programador?

Programador junior tirándose a la piscina del mercado laboral

Aterrizando en el mercado laboral


Cuando llegué a España, en el 2008, no sabía nada del mercado laboral español. Vine a trabajar en una Universidad, por un tiempo corto de 3 meses que se extendió a 4 y, después, tuve que enfrentarme a un entorno desconocido: tenía 7 años de experiencia laboral; pero era un programador que no sabía cómo buscar trabajo de programador pues el entorno universitario no tiene absolutamente nada que ver con la realidad fuera del campus.

Durante un tiempo, fui a entrevistas con una vestimenta inadecuada, con currículos penosos y con una idea nula de cómo acometer ese proceso de auto-venta que es la entrevista de trabajo.

Después de leer muchos artículos y recomendaciones sobre el tema fui haciéndome una idea de qué y cómo debía hacer las cosas. Las lecturas y los consejos de amigos fueron dando forma a mi proceso de búsqueda de empleo; pero lo que me marcó, profundamente, fue una antigua oferta de trabajo titulada "Sorpréndenos", que pasó a ser para mi como un manifiesto: el manifiesto de "Me importa un carajo tu currículo", aún accesible aquí, gracias al proyecto de Internet Archive.

Así que entre consejos, lecturas y la repetición del probadísimo método de prueba-error-corrige-y-vuelve-a-probar, conseguí mi segundo trabajo en España y el primero en el libre mercado de oferta y demanda de trabajo.

Pero un tiempo después resultó que saber programar y venderse en una entrevista, fueron solo el comienzo. Mantener el puesto y evolucionar como programador, eran habilidades que no me habían enseñado en la escuela y que tuve que adquirir, sobre la marcha.

Ayudando al que sigue


Un año después, podría decirse que estaba asentado y tenía algo de know how. Conocimiento que algunos con experiencia podrían considerar elementales; pero para mí, que era un recién llegado, fue como para un niño su primer día de colegio: maravilloso y abrumador.

En septiembre del 2009, un amigo con muchos años de experiencia como desarrollador, se encontró en la misma situación que yo: recién llegado a un mercado laboral desconocido, tenía los conocimientos técnicos requeridos, pero le faltaba el entendimiento del mercado. Así que mis conocidos errores y el poco de experiencia adquirida le sirvieron para saber que no hacer y orientarse sobre qué hacer. Y con eso, sus conocimientos, un currículo pulido por "El Manifiesto", una orientación clara y preparado para las entrevistas consiguió trabajo un día antes de cumplirse el mes de empezar a buscar.

Después de éste, vinieron otros y cada vez, la transmisión oral del qué, cómo y dónde buscar trabajo se fue regularizando y tomando forma hasta transformarse en un correo con consejos y direcciones Web.

Ocho años después


A estas alturas ya perdí la cuenta de cuántas entrevistas he hecho y todo para cambiar una sola vez de trabajo, en todo este tiempo. De mis entrevistas y después de conocer a otros programadores en reuniones, eventos, cursos, hackathons e incluso, después de haber entrevistado a algunos, comprendí que mis carencias del 2008 eran más frecuentes de lo que pensaba. Al parecer:

En muchos lugares pueden enseñarnos a programar, pero en pocos nos enseñan cómo ser programador.

Y aunque parezca lo mismo no lo es: ser programador es mucho más que saber programar porque el oficio de programador no es una profesión desconectada. El programador encerrado en su garaje, cambiando el mundo, en solitario... es un mito.

Por eso, después de conversar con varios recién llegados y evolucionar esa guía por e-mail, he pensado que, tal vez, sea útil escribir un poco más sobre el tema, creando una guía práctica con instrucciones paso a paso, que describa los perfiles actuales y cómo prepararse para obtener un empleo.

Una guía para aprender a ser programador 


Si mi impresión es correcta y una buena parte de los recién llegados al mercado del trabajo del sector TIC necesitan más conocimiento del oficio, entonces una guía bien concreta podría complementar los conocimientos técnicos adquiridos en escuelas, cursos y libros.

Llegados a este punto, me gustaría saber si:
  • ¿Sabes de alguien que quiera ser programador y no pueda ir a la Universidad o a una escuela técnica?
  • ¿Conoces a algún programador que le cueste encontrar empleo?
  • ¿Sabes de algún programador veterano que se sienta desactualizado y le preocupe su futuro?

Si conoces de alguien así y crees que una guía como ésta pudiera serle útil, coméntamelo y hazme todas las sugerencias que creas. Igualmente, si sabes de la existencia de algún recurso o lugar donde aprender sobre estos temas, compártelo: yo me ahorraré una guía y tú ayudarás a mucha gente.

El debate está abierto.

¿Cuál es tu opinión?

Responde en los comentarios, por Twitter @bellopauste o en Google+

domingo, 12 de junio de 2016

Plantillas para hacer prototipos de aplicaciones en papel

Me gusta dibujar, no lo hago muy bien, ni frecuentemente, pero es una de esas cosas que me entretiene y por eso casi siempre empiezo la concepción de las apps que hago, dibujándolas.

Muchas personas se preguntarán por qué perder el tiempo dibujando la interfaz de una aplicación, cuando hay tan buenos IDEs con los que generar la interfaz, directamente; pero a las interfaces se aplica lo mismo que a los programas: salvo que vayas a hacer un programa que sume a + b, no es buena idea sentarse a programar sin antes pensar y (potencialmente) escribir o concebir cómo atacar el problema... y lo mismo aplica a las interfaces: es mejor pensar un poco antes de ponerse manos a la obra.


Plantillas para hacer prototipos


Por supuesto, hay discimiles herramientas para prototipar o diseñar apps móviles y Web: desde plantillas en distintos formatos para aplicaciones como Photoshop, Ilustrator o Sketch, hasta software más rústico pero de uso específico como Pencil. Sin embargo, el acto de garabatear mientras pienso, me ayuda a generar y organizar las ideas mientras me pongo en contexto.

No obstante el disfrute del dibujo, hacer cuadrados y círculos no es lo más divertido del mundo, así que luego de buscar muchísimo, encontré dos plantillas de distintos fabricantes para ayudarme con las partes más monótonas o que requirieran más precisión: unas de acero cortado a láser, con muy buen aspecto y calidad, pero caras y otras de acrílico, más ligeras y baratas.

Un ejemplo de prototipo de una pantalla muy simple


Los que siguen son un par de vídeos que ilustran el uso de ambas plantillas para hacer ese diseño básico de una pantalla muy simple.




Conclusiones


Las dos plantillas generan unos resultados muy parecidos y, aunque es verdad que las de acero son un gustazo para trabajar con ellas, el precio juega en su contra: con lo que cuesta una sola plantilla de acero, puedes comprar casi el pack completo de las plantillas de acrílico.

Por otra parte, si vas a viajar y solo llevarás equipaje de mano, es probable que las plantillas de acero te den algún problema para pasar un control de aeropuerto.

Así que si quieres tener un pack completo gastando poco, la mejor opción es la ofrecida por mobilestencil.com. Por otra parte, si te quieres dar un capricho o hacerle un regalo de calidad a un amigo ;-) entonces las plantillas de uistencils.com son la opción.

martes, 10 de mayo de 2016

Retomando el blog... casi 2 años después

Han pasado casi 2 años y muchas cosas desde el último post: varios libros leídos, nuevos frameworks aprendidos, algún premio en metálico en un hackathon ;-)... y hasta un cambio de empresa.

Debí haber escrito sobre todo esto pero la inercia me llevó a esta sequía por pereza: cada vez los post se hacían más largos y más tediosos de escribir. Así que en lugar de ser más escueto, terminé no escribiendo nada.

Pero como el ejercicio de escribir en este blog es, sobre todo, un ejercicio de memoria para dejar escrita las lecciones que he aprendido que, si sirven a otros, ya valen el doble... he decidido que intentaré retomar la escritura.

Así que, para ser consecuente y aplicar la última lección aprendida: seré más escueto y terminaré aquí.

Peeero... termino con un adelanto de lo que viene: retomaré los temas técnicos pero introduciendo algunos temas no "tan" técnicos pero que me han ayudado con algún proyecto o a mejorar mis relaciones profesionales.

Y aquí va un adelanto: desde septiembre del 2015 he comenzado a trabajar en Tuenti y estos son algunos de los dibujos que me ayudaron a "socializar" en las charlas técnicas que se suelen hacer los viernes.

Apuntes en tinta, en vivo, de los conferencianes en las "Tech talks"
Viendo el adelanto... ¿Crees que hago bien tratando otros temas o debería mantenerme en la línea más "técnica"?

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?