Offboarding se convierte en un libro (con tu ayuda)

Te acuerdas del artículo sobre Offboarding de septiembre del año pasado? Después de aquella entrada me quedé con muchas ganas de hablar más del tema, y mientras más lo pensaba, más veía que el tema daba para hablar más sobre los procesos que necesitamos tener en cuenta cuando hacemos un cambio de proyecto a destiempo, cuando nos apartamos de un equipo o empresa y el proyecto sigue adelante.

Por coincidencias de la vida, en la Tarugo4 del pasado octubre tuve la ocasión de conocer a Guillermo de Libros.com, y estuvimos hablando sobre la editorial, el modelo de financiación y el hecho de que estaban buscando ideas para publicar. Conocí también a Roberto y a otros miembros del equipo, y les enseñé el artículo. Tras varios conflictos de agenda un día pasé por las oficinas donde pude ver cómo trabajaban, y estuvimos hablando de cómo transformar este artículo en un libro.

Pasadas las navidades, el proyecto empezó a tomar forma, incluyendo algunas sesiones de formación y algún que otro papeleo para asegurarnos que todo fuera sobre ruedas, y eso nos lleva a hoy.

Hoy el proyecto de Offboarding está mucho más cerca de ser una realidad, un manual de cómo podemos dejar atrás un proyecto con la mente clara y la tranquilidad de haberlo hecho lo mejor posible, y para ello necesita tu ayuda.

Con tu colaboración consigues que Offboarding se edite, se publique y se distribuya, te llevas una de las primeras copias y además puedes seguir de cerca el proceso de creación, edición y puesta en el mercado de un libro. Para colaborar, hazte mecenas en Libros.com

2019. Fin de una década

Siempre he pensado que las fechas tienen un significado trascendental más allá de un número en un calendario, y es por eso que en la familia siempre hemos sido de celebrar cosas.

Celebramos los cumpleaños, aniversarios de novios, aniversarios de vivir juntos, aniversarios de aquel viaje que hicimos a aquel sitio, cierres de etapa, inicios de etapa, y también celebramos por aquellos que han estado y ya no están.

2019 se acaba, con él se lleva por delante una década que para mí ha sido increíblemente intensa desde el punto de vista personal y profesional, diez años en los que he podido compartir lo aprendido contigo querido lector, a lo largo de 270 entradas (271 con la que estás leyendo en estos momentos).

Este año he podido compartir contigo reflexiones, libros que he leído como Atomic Habits, eventos en los que he estado como Tarugo4, patrones de diseño como BFF o procesos y maneras de trabajar como es el caso de Offboarding y el modelo C4.

Se me han quedado algunas series en el tintero que quiero retomar, entre las que está la segunda parte de Cloud Running, el artículo sobre la influencia del idioma inglés en palabras relacionadas con desarrollo de software y el pet project que me ha mantenido ocupado estas últimas semanas, un editor de markdown de escritorio escrito en C++.

El año pasado fijaba algunos hábitos para este año, desde concentrarme en bloques, correr cada semana, mejorar la organización, desconectar activamente, leer, aprender más, y respirar.

Este año he leído, y mucho, de acuerdo con GoodReads he leído, entre audio y texto, 28 libros respecto a 13 del año pasado, y tengo varios a medias que pretendo rematar a principios de año.

Respecto al resto de hábitos es difícil cuantificarlo, ya que he podido tener más sesiones de concentración pero me he distraído más, desconectar activamente ha sido un reto, y aunque he aprendido mucho este año, no le he dedicado el tiempo necesario para sentarme y estudiar.

Para 2020 me gustaría dedicar más tiempo a leer y a aprender, a escribir y compartir contigo las cosas que leo y aprendo, más eventos (de momento tengo entradas para DosConf y WeCode, así que si estás por ahí seguramente nos veamos), y como comentaba en mi reflexión de principios de mes, más tiempo y espacio para estar con la familia, amigos y gente que nos soporta.

No pido más de la próxima década, tiempo y espacio y para poder hacer cosas interesantes, y paz mental para poder llevarlas a cabo.

Dentro de unas horas, en España estaremos tomando las uvas al son de las 12 campanadas de la puerta del Sol, celebraremos la nochevieja y, tan solo unos días después veremos desfilar a los tres reyes magos antes de dejar miles de presentes a los más pequeños en una noche mágica. Y con ello terminarán las navidades y empezaremos, con fuerza, la década de los 20’s.

Feliz año nuevo

Una reflexión de diciembre

Acaba de empezar diciembre, este mes cerramos año y década, y me ha parecido una buena ocasión para compartir con vosotros una breve reflexión.

En los más de 10 años que llevo escribiendo este blog, he visto empresas y productos desaparecer, paradigmas tecnológicos que iban a revolucionar las cosas que luego no han revolucionado tanto, lenguajes, herramientas, métodos, y utilidades para aburrir, todo esto son, dicho de una manera simple, cosas, en las que personalmente he invertido mucho tiempo, y aunque he aprendido mucho por el camino, no dejan de ser cosas.

Por otra parte, he podido podido compartir experiencias por videoconferencia y escenarios con grandes profesionales a los que admiro mucho, he descubierto el formato open space y superar el miedo a salir a proponer temas para discutir, que a veces saliera, y a veces no, aprender de la experiencia de los demás, aportar un poco siempre que se pudiera y escuchar mucho rodeado de gente. Personas que van un paso más allá para compartir lo que saben, muchas veces de manera altruista y de su propio bolsillo. Estas experiencias me han enseñado mucho, pero más importante, he podido conocer a gente excepcional.

Estas situaciones en cierta manera contrastan con el día a día de nuestra profesión, que en ocasiones requiere y exige que nos pasemos largas horas en la soledad de nuestra pantalla, nuestro IDE, y aunque tenemos cientos de maneras de distraernos y perder el foco, no deja de ser un momento de soledad. El estrés y la ansiedad causados por el día a día del trabajo no hacen más que incrementar esta soledad, ya que nos vemos pasando más tiempo en la pantalla, más tiempo alejados de la gente y para colmo, expuestos a las redes sociales que nos recuerdan de manera constante todo lo que nos estamos perdiendo.

Esa gente, que es nuestra familia, nuestros amigos, nuestros compañeros del trabajo, los miembros de la comunidad a la que pertenecemos, los colegas de la facultad, la gente con la que entrenamos, etc., es importante. Son ellos los que nos sacan del pozo cuando el trabajo se complica, y los proyectos se atragantan, y son ellos los que están allí si las cosas van mal en el terreno personal.

Siempre tendremos trabajo, siempre será urgente, y siempre será lo más importante, y muchas veces será diferente, sin embargo, y es algo que todos experimentaremos según pasa la vida, esa gente a la que importamos, nos importa y nos apoya no va a estar para siempre, y de hecho nos queda mucho menos tiempo con ellos del que creemos.

Por ello, en estos últimos días de la década de los 2010, me gustaría que todos nos alejáramos un poco de las pantallas, de la soledad de nuestros proyectos, pongamos el móvil en no molestar y les dediquemos un poco más de tiempo a esas personas que nos soportan, que nos apoyan y que nos ayudan a avanzar, y estemos allí para ellos con una sonrisa, los brazos abiertos y voluntad de escuchar.

Espero volver a veros por aquí después del 25 de diciembre para compartir con vosotros mi resumen anual, y tal vez algo con más contenido técnico :)

Feliz Navidad.

Tmux, una aplicación para dominar nuestras consolas

La terminal de unix lleva décadas ofreciendo utilidades no solamente a desarrolladores y administradores de sistemas a nivel de servidor, sino también a entusiastas en entornos de escritorio.

El uso de herramientas como git, o nodejs, ha traído un uso mayor de la consola a los entornos locales, y también la necesidad, a veces, de estar conectados a terminales remotos vía SSH.

El problema de una conexión por SSH es que si tenemos un fallo de red o suspendemos nuestro ordenador, nuestra conexión se puede ver afectada, lo que causará que nuestra sesión termine, y con ella los comandos que estemos ejecutando.

Existen utilidades que no solamente nos permiten prevenir esta circunstancia sino que nos permiten tener una configuración en nuestra terminal remota que haga más sencilla la conexión. En el artículo de hoy hablaremos de tmux, una solución que nos permite controlar múltiples ventanas y mantener la configuración de las mismas.

Instalando tmux

La fuerza de tmux radica cuando lo instalamos de manera remota en un servidor al que accedamos con frecuencia. En mi caso particular, me suelo conectar vía SSH a hosts que emplean Amazon Linux en la nube de AWS y usamos yum como gestor de paquetes, con lo cual el comando es:

yum install tmux

Podemos también instalar tmux en local y tener una configuración de consolas personalizada. En el caso de Mac podemos instalar tmux vía homebrew:

brew install tmux

Si tenemos Windows y WSL tendremos acceso a una shell de bash, en la que podemos instalar tmux utilizando:

apt-get install tmux

Utilizando tmux

La manera más sencilla de utilizar tmux es como una capa por encima de la terminal.

tmux

Este comando inicia una sesión de tmux que permanecerá activa incluso si nuestra conexión se cierra o en el caso de que estemos ejecutando de manera local, si cerramos la ventana. Este comportamiento se mantiene tanto en local (Mac) como en una sesión SSH, no sé que pasaría en Windows

Si cerramos la ventana nuestra sesión de tmux seguirá funcionando, así que para salir de la misma podemos utilizar o bien Ctrl + d o bien escribir logouto exiten la consola de comandos.

Por defecto. las sesiones en tmux están numeradas, para volver a una sesión solamente necesitamos escribir tmux lsy a continuación tmux attach -t Ndonde N es el número de sesión. Por otra parte podemos darle nombre a nuestras sesiones, lo que hará que volver a ellas sea mucho más sencillo.

  • Creamos nuestra sesión contmux new -s desarrollo
  • Volvemos a la misma con tmux attach -t desarrollo

Múltiples pestañas, pantalla dividida y más

Una vez tengamos nuestra sesión abierta, podemos personalizarlo utilizando Ctrl + bque es el prefijo por defecto en tmux, una vez pulsado, los siguientes comandos nos pueden ayudar:

  • Dividir el panel de manera horizontal
  • %Dividir el panel de manera vertical
  • derecha/izquierda/arriba/abajoDesplazarse por los paneles
  • cCrear una nueva ventana
  • nCambiar a la ventana siguiente
  • pCambiar a la ventana anterior

En el siguiente ejemplo (ejecutado de manera local) se puede ver una sesión con dos ventanas y tres paneles.

Si cerramos la ventana y volvemos a la sesión se mantendrá abierta.

Tmux con iTerm (Mac)

Si utilizamos Mac con iTerm, este último tiene integración con Tmux, con lo cual podemos crear los paneles utilizando la manera nativa que estamos acostumbrados en iTerm, y podremos intercambiarlos con los controles nativos.

Para ello abriremos nuestra sesión con tmux -CC newo tmux -CC attach

Iterm, por defecto, abre nuevas pestañas de Tmux en ventanas, con lo cual para cambiar esa configuración podemos ir a Preferences > general > tmux > Open tmux windows as “Tabs in attaching window” como se ve en la imagen

Personalizando nuestra configuración

El último paso es tener nuestra configuración guardada de manera persistente de tal manera que “sobreviva” un reinicio del sistema o si queremos simplemente poder volver a una configuración estable.

Para ello, usemos el ejemplo que he descrito anteriormente en un script de bash:

#!/bin/sh
tmux new-session -d 'ping www.google.com'
tmux split-window -h 'top'
tmux select-pane -t 0
tmux split-window -v 'vim'
tmux new-window 'tail -f /var/log/system.log'
tmux -CC -2 attach-session -d

Este script lo podemos guardar como reset-session.sh y podemos llamarlo siempre que queramos restaurar la configuración de la sesión que teníamos anteriormente.

En resumen

Tmux es una herramienta muy poderosa que nos permite personalizar la configuración de nuestras ventanas, mantener procesos en ejecución dentro de una consola remota y guardar esta personalización para poder restaurar un espacio de trabajo a nuestro gusto.

Bibliografía

Tarugo4, yo estuve allí

Hace casi casi 4 años, el 25 de octubre de 2015, David nos hacía saber en su newsletter y en su blog que estaba montando una conferencia dedicada a la gente que, como yo, leía sus columnas semanales. Nacía entonces la #TarugoConf.

Cada año a partir de entonces veíamos como las redes se llenaban de comentarios en dos fechas clave, cuando salían las entradas a la venta (que eran reducidas por temas de aforo y mucha gente, incluido un servidor, se quedaba sin poder asistir) y en la fecha del evento, en el que los asistentes salían contentos e inspirados.

Tres ediciones después, la providencia me ha permitido asistir a mi primera Tarugo, y puedo aseguraros que Bonilla no defrauda.

La TarugoConf es un evento que combina tecnología, negocios y un montón de cosas más, con un track de charlas, comida “como para una boda” y muchos espacios y oportunidades para conocer a gente, para desvirtualizar aquellos a los que solamente has visto en redes o para recuperar el contacto con compañeros a los que le has perdido la pista.

En el track de charlas los temas en esta edición han sido:

  • Cómo potenciar la innovación en los equipos utilizando un montón de anécdotas de la industria de los helados.
  • Qué mecanismos podemos implementar desde un punto de vista técnico para mejorar la privacidad de nuestros usuarios en nuestros sistemas.
  • Cómo convertirnos en podcasters, qué técnicas utilizar, qué medios comprar, cómo conseguir audiencia y cómo incluso podríamos ganar dinero con ello.
  • Cómo montar un flujo de trabajo para científicos de datos, cómo integrarlos con el desarrollo de producto y sobre todo, pensar si necesitamos ese rol en nuestros equipos.
  • Cómo hacer productos que vendes a otras empresas, con especial hincapié en cómo incrementar la conversión entre un primer contacto y un contrato firmado.
  • Cómo crear mecanismos de entrega de valor, desde control de versiones a gestión de artefactos a entrega continua utilizando anécdotas de consultoría, administración pública y desarrollo de producto.
  • Cómo crear y mantener un estudio de videojuegos, utilizando anécdotas en el rol de estudio, publicador, editor, y todas las anteriores, y con especial interés en tener ambos lados del cerebro en un estudio, creativo y gestión.
  • Cómo hacer negocios en latinoamérica, qué tener en cuenta, qué mercados están creciendo, cómo conseguir presencia y cómo lograr que te paguen, entre otras.

Cada ponencia, de aproximadamente 45min + preguntas, ha sido tan interesante o más que la anterior, y pese a que hemos estado más de 8h en una sala de cine a nivel personal no se ha hecho largo. Los ponentes han hecho un excelente trabajo condensando estos temas, y todas y cada una de las charlas han tenido un componente práctico, y ha sido sencillo traernos deberes “a casa”.

Los voluntarios y la organización han estado todo el tiempo pendientes de los asistentes, poniendo todo el amor, las ganas y los focos de las cámaras en que todos estuviéramos pasando un buen rato, sintiéndonos como en casa.

Finalmente los patrocinadores han estado especialmente involucrados, con un nivel de interacción con los asistentes diferente, y más allá del típico stand. Un ejemplo de ello han sido los chicos de Libros.com una editorial que publica novelas, ensayo, manuales, y artes gráficas utilizando crowdfunding, y que estaban allí por una parte mostrando el resultado de sus campañas, y por otra parte (más interesante aún) buscando historias que publicar. Un equipo muy cercano del que espero hablar más en el futuro, mientras tanto, si tienes una historia que quieres compartir con ellos aquí te dejo el enlace

Como anécdota personal, he conocido en persona a la gran Nerea Luis, Doctora en IA, y cofundadora de T3chfest, con la que comparto, por casualidades de la vida, apellido, y nos hemos contado batallitas sobre el caos administrativo de un apellido que suena tanto, tanto, a nombre.

Enhorabuena a todo el Equipo Tarugo por un gran evento, por hacernos sentir en familia, por enseñarnos tanto y por inspirarnos.

Libro – The Checklist Manifesto

Hoy hablamos de un libro que me ha tenido enganchado durante varios días y varias horas de vuelo, un ensayo lleno de historias médicas, de aviación, construcción y cocina, sobre un mecanismo que comparte que mejora la seguridad, la eficiencia y, sobre todo, protege y salva vidas. una lista.

Hoy te cuento, querido lector, acerca de The Checklist Manifesto, de Atul Gawande.

Nuestra memoria falla, y no hay nada que podamos hacer al respecto

En nuestro día a día, la complejidad de nuestras obligaciones profesionales ha aumentado exponencialmente, y se espera que podamos mantener bajo control situaciones variables, variaciones, opciones e incertidumbre, y en medio del caos es normal, y común, olvidar cosas o pasarlas por alto.

La memoria tanto a corto como a largo plazo puede fallar, y falla. En una mesa de operaciones o en una cabina de un 747, esto tiene trágicas consecuencias.

La lista: alternativa simple y sofisticada

La manera de mitigar el error, comenta el autor, no es prestar más atención, más medios, más maquinaria o más tecnología, sino un enfoque más simple, tener una lista con puntos críticos, y utilizarla y revisarla de manera continua.

Una lista, en este contexto no es algo que se escribe en 5 minutos, no es un manual de instrucciones, no tiene como objetivo enseñar ni educar, y se basa en la suposición de que será utilizada por profesionales que conocen perfectamente su dominio.

El uso de esta lista puede ser, por una parte en un caso normal (despegar un avión) así como en situaciones excepcionales (motor en llamas). En ambos escenarios, tener una lista de acciones a realizar permite libertad a la persona para poder centrarse en la tarea a mano sin olvidar elementos críticos.

Es importante entonces definir qué es una mala lista. De acuerdo con el autor, una mala lista es poco precisa, demasiado larga y difícil de utilizar.

Por otra parte, una buena lista es práctica, precisa, eficiente, fácil de utilizar en situaciones complejas, y sobre todo, un recordatorio de los pasos críticos e importantes que se pueden pasar por alto independientemente de cuan experimentada sea la persona que las va a utilizar.

Creando nuestras listas

A lo largo del libro, el autor nos da algunas pistas para crear listas efectivas tras aprender de la mano de pilotos de Boeing, y de cómo lo puso en práctica en una mesa de operaciones.

Por una parte, queremos entender especificar qué tipo de lista necesitamos:

  • DO-CONFIRM: En este caso la lista se utiliza como punto de sincronización, las tareas se hacen “de memoria” y llegados a un punto específico (antes de comenzar la operación, antes de entrar en una pista de aterrizaje) se comprueban todos los puntos de manera rápida.
  • READ-DO: En este caso la lista se utiliza como una receta, una serie de pasos que hay que seguir en un orden específico. Un ejemplo de uso de esta lista sería el caso del motor en llamas.

Respecto a la cantidad de puntos , idealmente tendremos entre 5 y 9 elementos (7 más/menos 2), que se considera el límite de la memoria a corto plazo o memoria de trabajo aunque podemos adaptarlas a las necesidades de la misma.

El objetivo de limitar los puntos es que podamos revisar la lista en cuestión de segundos, de tal manera que no se interponga en nuestro trabajo, no olvidemos que una lista muy larga puede provocar que empecemos a “saltarnos” puntos de la misma.

Dichos puntos han de ser claros, específicos, solamente aquellos que consideremos críticos, con un lenguaje simple, y específico del contexto, como hemos mencionado antes, no estamos ante una herramienta de aprendizaje.

El documento ha de ser puesto en práctica para verificar que funciona en el mundo real. Los pilotos utilizan los simuladores de vuelo para ello.

Es necesario asegurarse que la lista funciona tanto en situaciones normales y en caso de una emergencia. En caso de que las listas no funcionen en un entorno de pruebas, se toman notas, se vuelve atrás, se mejoran, y se intenta una y otra vez.

Resumen

A lo largo de unas 200 páginas, el autor cuenta ejemplos de cómo las listas nos permiten no perder de vista puntos críticos del trabajo que hacemos sin limitar nuestra creatividad ni capacidad de reacción, más bien al contrario, establece un balance de libertad y disciplina que nos permite mejorar, ser predecibles y efectivos, especialmente en situaciones extremas.

De momento he empezado a experimentar creando y puliendo listas, cosas que revisar antes de dar por bueno un documento, diseño, análisis, o incluso antes de tener reuniones o de entrevistar a un candidato.

Y tú, para qué utilizas tus listas?

Offboarding

El pasado 1 de Julio, tras pasar cuatro años como parte de la familia Amazon Business, cambié de organización para empezar una nueva aventura como miembro del equipo de ingeniería de Kindle.

Cambiar de organización a nivel corporativo es algo suficientemente complejo que “casi” equivale a cambiar de empresa, con lo cual había expectativas que fijar, información que transferir, tareas que cerrar y procesos que documentar.

En este artículo veremos algunos elementos a tener en cuenta cuando cambiamos de equipos desde el punto de vista del técnico individual, algunos estos elementos serán aplicables también a cuando cambiamos de empresa.

Expectativas

Lo primero, una vez aclaramos con nuestro jefe de nuestra intención para cambiar de destino, es necesario fijar plazos para cerrar frentes abiertos y proyectos en curso.

Si estamos cambiando de empresa, lo habitual es que tengamos un plazo mínimo de notificación estipulado en el contrato, mientras que si estamos cambiando de equipo podemos ser más flexibles.

En general, basándome en mi experiencia, entre tres semanas y un mes debería ser tiempo suficiente para cerrar frentes abiertos y hacer transferencia de conocimientos, lo que nos lleva a…

Listar frentes abiertos

El siguiente paso es abrir una hoja de Excel, Google Spreadsheets, o un fichero de texto y comenzar a escribir una tabla con la información siguiente para todo lo que tengamos en la cabeza:

  • Área (o proyecto)
  • Tarea
  • Estado a fecha de hoy
  • Personas involucradas (aparte de nosotros)
  • Fecha tope
  • Estará completo antes de que dejemos el equipo?
  • Quién se puede hacer cargo cuando no estemos?
  • Qué necesitamos para que esté completo?

Aunque tengamos un equipo perfectamente conexionado con todas las tareas en Jira, TFS, GitLab, Github, Trello, etc. siempre habrá tareas que tenemos en la cabeza, ideas y frentes abiertos que no viven en el sistema de gestión de tareas.

Para aquellas tareas que estén asignadas a nosotros en el sistema, podemos repetir el ejercicio documentando el estado actual y el estado esperado cuando ya no estemos.

Es importante dejar a una persona o punto de contacto a cargo de estas tareas, para ello podemos sugerir alguien en nuestro equipo que tenga especial contexto sobre las mismas, de manera que el seguimiento no se interrumpa.

Notificar a personas involucradas

Tras listar los frentes abiertos y detectar las personas involucradas, es importante notificar a otras personas que trabajan con nosotros que no seguiremos en el equipo, especialmente si somos la persona de contacto de una o más iniciativas, y hacer las conexiones necesarias entre otros equipos y los nuevos interlocutores.

De esta manera nos aseguraremos que los proyectos sigan adelante y estableceremos expectativas claras para las personas que están fuera de nuestro equipo aunque colaboren con nosotros.

Documentar progreso

El siguiente paso, una vez aclarado qué vamos a poder poder terminar y qué no, es dedicar tiempo a documentar, especialmente los proyectos que hemos entregado más recientemente y aquellos que se van a mantener en curso cuando no estemos.

Como ejemplo de elementos que podemos documentar, tenemos:

  • Decisiones técnicas tomadas y por qué las hemos tomado.
  • Puesta en marcha en pruebas y producción de nuestros servicios.
  • Detalles sobre scripts y pequeñas automatizaciones que hayamos hecho.

Transferir conocimiento

Además de la documentación, es muy útil tener una o varias sesiones de transferencia de conocimiento con otros miembros del equipo que vayan a heredar nuestras responsabilidades.

Estas sesiones pueden cubrir, entre otros aspectos:

  • Visión general de los diferentes servicios que componen nuestro sistema
  • Ciclo de vida de peticiones (especialmente útil en una arquitectura de microservicios)
  • Tickets cerrados recientemente, especialmente aquellos de alta prioridad, y causas más comunes.

Estas sesiones, además, podemos grabarlas en vídeo de manera que queden como “documentación” para que otros miembros del equipo puedan recurrir a ellas en caso necesario.

Limpiar

Cambiar de equipo suele ser una buena oportunidad para hacer “borrón y cuenta nueva”, así que podemos aprovechar para renovar equipamiento si es posible.

En cualquier caso es una buena oportunidad para hacer copia de seguridad, y borrar repositorios locales de proyectos antiguos, siempre y cuando dejemos copias de nuestras ramas en repositorios remotos.

Re-asignar cuentas, permisos, credenciales, listas de correos…

Dependiendo del grado de automatización que tengamos, nuestro usuario puede ser administrador o dueño de ciertos recursos, por tanto será necesario re-asignar dichos recursos así como rotar claves en caso de que no tengamos un sistema automatizado. En caso contrario se podría perder información cuando nuestra salida se haga efectiva.

Es posible que tengamos acceso a sistemas específicos única y exclusivamente por pertenecer a ciertos equipos, y es importante asegurarnos que este acceso será revocado, ya que puede ser un vector de ataque desde nuestra cuenta del que nos olvidemos en el futuro.

De manera adicional, es importante dejar listas de distribución o canales de slack que dejen de ser relevantes para nosotros, ya que solamente agregaremos ruido y podemos dar la falsa impresión de que seguimos en el equipo.

Seamos accesibles

Incluso tras meses de trasferencia de conocimientos habrá cosas que no seamos capaz de transmitir, o problemas que surjan cuando no estemos, y para ello es importante mantenernos accesibles.

Si seguimos dentro de la empresa, habrá ocasiones en que alguien de nuestro antiguo equipo contactará con nosotros con dudas o preguntas, especialmente en las primeras semanas o meses, y es una oportunidad para seguir ayudando y apoyando al equipo.

Conclusiones

Los cambios siempre traen incertidumbre, cuando nosotros propiciamos un cambio generamos incertidumbre en la gente a nuestro alrededor pero también en nosotros mismos.

Construir un plan de transición nos ayudará a reducir y limitar esta incertidumbre tanto para nosotros como para nuestros compañeros.

Dejando claras las expectativas, los frentes abiertos, habiendo transferido el conocimiento, documentando proyectos, dejando los recursos con sus nuevos dueños y manteniéndonos accesibles, podremos enfrentar los nuevos retos que nos esperan tras cerrar una etapa profesional, hagámoslo bien.

El patrón BFF: Backend for Frontend

Esta semana he estado leyendo sobre Backend For Frontend o BFF, un patrón de arquitectura de microservicios dio a conocer al mundo uno de los ingenieros de SoundCloud en el año 2015, aunque sigue aplicándose a día de hoy.
En este artículo veremos el problema que tenemos en un entorno de microservicios y cómo el patrón BFF es una de las soluciones posibles.

El problema

Una aplicación web presenta diferentes niveles de complejidad en función de la necesidad. El ejemplo más básico es el de un único sistema que genera el contenido de lado del servidor, donde tanto el frontend como el backend forman parte del mismo, lo que se considera un monolito (por ejemplo, este blog).

Este sistema se puede hacer más complicado si convertimos este monolito en un conjunto de APIs REST unido a un código más complicado del lado del cliente (una Single Page Application o SPA) (o un estéreo-liso). Hasta este momento tenemos una única conexión entre cliente y servidor.

La complejidad puede aumentar mucho más por dos lugares diferentes. Por una parte, podemos necesitar soportar otros canales, como una aplicación móvil, una skill de Alexa, o una API para terceros. Por otra, el backend se puede dividir en diferentes servicios, cada uno con una API específica, a la que nos tendremos que adaptar.

Llegados a este punto, nos encontramos en una posición en el que los clientes (la aplicación móvil, la aplicación principal, la skill de alexa y un desarrollador independiente) dependen de una API común o de una serie de APIs independientes, con lo cual se genera un acoplamiento fuerte entre dos o más sistemas.

El resultado es que todos los clientes acceden a APIs que dan mucha más información de la que ellos necesitan, y no tienen una manera específica de controlar qué información utilizar y cómo leerla. Además, esto limita la capacidad de los desarrolladores de la API, ya que de repente cualquier cambio tiene que ser consensuado con todos los clientes, aumentando la probabilidad de generar regresiones.

La filosofía

La filosofía propuesta por BFF intenta simplificar la relación entre un cliente y su servidor, generando un punto de entrada para cada cliente. Esto significa que un cliente accede a una API exclusiva que soporta casos de uso específicos de cada cliente y que el cliente tiene total libertad para adecuar su API a sus propias necesidades.

En un patrón de microservicios, esto significa generar un servicio intermedio que de soporte única y exclusivamente a este tipo de cliente. Este servicio, desde el punto de vista de pertenencia, le pertenece al equipo del cliente. Volviendo a nuestro ejemplo, el equipo de la Skill de Alexa tendrá una API diferente al equipo de la app móvil, que el de la aplicación de escritorio.

La ventaja principal, que he comentado anteriormente, es que se simplifica el acoplamiento entre una aplicación y sus servicios de backend. Además, es más fácil que un servicio de backend evolucione, ya que las adaptaciones no necesitarán desplegar nuevos cambios en cliente, sino solamente en los adaptadores.

El ejemplo

Supongamos que queremos diseñar la siguiente iteración de Pokemon Go, tenemos una aplicación móvil en la que capturaremos los Pokemon, una web donde podemos ver detalles de nuestras capturas y una Skill de Alexa en la cual podemos saber en qué posición estamos del ranking.

En un desarrollo tradicional con un único endpoint, tendríamos una API REST en el cual todos los clientes efectuarán las llamadas necesarias, todos los clientes utilizarán el mismo protocolo y tipo de datos.

Este sistema convierte nuestra API rest en un punto de fallo para tres sistemas diferentes, con el añadido de que, salvo el sistema web, un fallo que rompa los clientes de iOS y los de la Skill de Alexa pueden tardar en corregirse, ya que depende de las reglas de cada marketplace.

Por otro lado, ¿que pasaría si cada cliente tuviera un servicio asociado? Esto provocaría un aumento considerable en la libertad de los diferentes equipos en desarrollar soluciones en el servidor para sus problemas específicos.

  • El equipo que gestiona la web podría decidir en utilizar GraphQL para generar solamente una petición, y utilizar código isomórfico para tener JavaScript en cliente y servidor.
  • El equipo que gestiona la Skill de Alexa podría utilizar una opción servirles en Lambda utilizando Python.
  • El equipo que utiliza la aplicación iOS, con el objetivo de ahorrar ancho de banda a los clientes, puede decidir montar un servicio a bajo nivel con un socket TCP.

Este cambio no afecta a la lógica de negocio, ya que estos servidores seguirán llamando a nuestro servicio común, que a su vez puede evolucionar de manera separada dividiéndolo en otros tantos servicios.

Esto permite además una evolución mucho más rápida de los sistemas, ya que en caso de un cambio importante, solamente será necesario actualizar los servicios intermedios, y las aplicaciones cliente pueden continuar funcionando.

Los inconvenientes

El principal problema de utilizar una API para cada tipo de cliente es la complejidad, de repente tener un servicio y tres aplicaciones cliente se convierte en tener tres servicios, tres aplicaciones cliente y un cuarto servicio por encima de todas ellas. Esta complejidad no está exenta de coste, lo cual puede repercutir en más hardware, más configuración y encarece el desarrollo.

Otro problema de esta aproximación es que requiere que los equipos de cliente tengan capacidad para generar su propio servicio de backend, lo que implica tener conocimientos de backend en un equipo frontend o un equipo mobile, lo cual no siempre es el caso.

El dilema de dogfooding

Dogfooding (o “eat your own dog food”) es el término que en ocasiones empleamos para utilizar las mismas herramientas y APIs a las que pueden acceder nuestros clientes externos, idealmente con el objetivo de no crear ciudadanos de primera y de segunda.

Sin embargo el peligro que tiene una API pública es el riesgo de romper a clientes externos con cambios que tengan sentido de manera interna pero no de manera externa, así que podríamos considerar la API pública como una API más, con una evolución diferente.

La decisión, to bff or not to bff?

La respuesta es, como siempre, depende. Si tenemos un sistema en el cual un tipo de cliente solamente va a utilizar un subconjunto de la API principal, puede ser buena idea crear un acceso solamente para este tipo de clientes. Ejemplo: Una skill de Alexa para agregar elementos a una lista de tareas, y un portal web para administrarlas.

Si, por el contrario, todos nuestros clientes van a utilizar los mismos métodos de nuestra API, y todos los clientes van a ser exactamente iguales en cuanto a funcionalidad, es posible que no necesitemos más que una API para gobernarlas a todas.

Echando la vista atrás recuerdo un ejemplo muy claro en el que tener un servicio genérico con el objetivo de soportar varios tipos de cliente condicionó muchísimo el diseño del primer y único cliente que se terminó desarrollando, agregando un montón de lógica al cliente de manera innecesaria para adaptar los datos que venían del servicio. Esto se podría haber evitado considerando que el servicio iba a tener un único cliente.

Resumen

BFF es un patrón de diseño de microservicios que nos permite considerar que el acceso a nuestro servicio se realiza desde clientes específicos con necesidades específicas, permite evolucionar las diferentes capas de la aplicación de manera paralela y elimina acoplamiento entre clientes diferentes con casos de uso específicos, siempre y cuando podamos asumir los costes de tener diferentes puntos de entrada a nuestra aplicación mantenidos por diferentes equipos.

Si quieres leer más del tema te recomiendo que eches un vistazo a los siguientes artículos:

Libro – Atomic Habits de James Clear

Hoy, querido lector, te traigo una (no tan breve) reseña de uno de los libros más interesantes que he leído últimamente sobre productividad, concretamente sobre los hábitos, desde un punto de vista fundamentalmente práctico.

El área de productividad lleva llamándome la atención desde hace muchos años, tanto que he leído e intentado poner en práctica muchos métodos, con mayor o menor éxito, y he documentado algunos de estos progresos en artículos como Tareas, Kanban, GTD y otras hierbas

Cuando hace unos meses me recomendaron Atomic Habits, no sabía que esperar. Me había leído (o más bien escuchado) The Power of Habit de Charles Duhigg un libro increíblemente detallado en los aspectos teóricos y físicos de la formación de hábitos aunque un tanto denso, así que otro libro sobre el tema me ponía el listón bastante bajo en cuanto a expectativas, aunque he de decir que las ha superado, con creces.

Nota importante: Este artículo cubre la edición en inglés de “Atomic Habits”, con lo cual la traducción de los conceptos explicados en el libro son propias y pueden no coincidir con la edición en castellano del mismo.

Las cuatro fases de un hábito

Tras una introducción en la que el autor habla de la relación entre identidad, resultados y hábitos, el autor descompone un hábito, en cuatro fases:

  • Cue (desencadenante): Lo que dispara la ejecución de una acción
  • Craving (antojo): Lo que genera la necesidad de llevar a cabo la acción
  • Response (respuesta): La ejecución de la acción.
  • Reward (recompensa): El resultado de la acción.

Las cuatro leyes de los hábitos

Una vez definidas las diferentes fases que componen un hábito y cómo se repiten constantemente a lo largo del día, el libro define el modelo que nos permitirá por una parte, incorporar hábitos positivos a nuestro día a día, así como interrumpir otros que resulten negativos, mediante el uso de cuatro “leyes” que define de la siguiente manera.

Si queremos agregar un hábito positivo a nuestra vida tenemos que conseguir:

  • Que sea obvio (desencadenante)
  • Que sea atractivo (antojo)
  • Que sea sencillo (respuesta)
  • Que sea satisfactorio (recompensa)

En el caso de querer eliminar un hábito que consideremos negativo, el proceso es el mismo, negando las premisas:

  • Que sea invisible (desencadenante)
  • Que sea poco o nada atractivo (antojo)
  • Que sea difícil (respuesta)
  • Que sea poco o nada satisfactorio (recompensa)

El resto del libro se dedica a expandir las definiciones de las cuatro leyes y qué pasos concretos podemos utilizar para implementarlas. Los capítulos son relativamente cortos, específicos y cuentan con un sumario al final de cada uno, así como un progreso en las diferentes leyes.

Ideas interesantes

El libro está lleno de ideas de implementación prácticas relacionadas con los hábitos, de las cuales me gustatría destacar algunas ideas que he sacado de pasajes que he subrayado:

  • Encadenar hábitos, crear un hábito justo a continuación de algo que ya hagamos de manera frecuente, o bien enlazar una acción que queremos hacer con una acción que necesitamos hacer.
  • Con el fin de crear un hábito, tener un entorno estable en el que todo tiene un lugar y un propósito hace que el entorno en sí mismo se convierta en el desencadenante del hábito y que posteriormente la acción a llevar a cabo sea más sencilla.
  • Podemos romper hábitos, pero es prácticamente imposible olvidarlos del todo, resistir la tentación es una estrategia poco eficiente, siendo más útil reducir la exposición al desencadenante (que sea invisible).
  • Es importante destacar la diferencia entre movimiento y acción, movimiento es pensar en escribir este artículo durante 3 meses, fijar un calendario, poner una lista de las ideas que discutir y tener la sensación de “progreso”, acción es sentarse durante 2 horas a escribir. Solamente la acción produce resultados.
  • La ley de los dos minutos nos permite fijar un objetivo ridículamente sencillo, con la idea de que empezar a trabajar en la acción sea fácil, y que no cueste trabajo seguir adelante.
  • Para llevar la cuenta de nuestros hábitos, podemos utilizar un registro, en el cual vamos anotando de manera inmediata y diaria los hábitos que cumplimos. Esto nos permite ser sinceros con nosotros mismos, ya que, habitualmente, pensamos que hacemos las cosas (bastante) mejor que como las hacemos realmente. Es importante que nuestra lista sea corta y concisa, ya que corremos el riesgo de querer llevar la cuenta de muchas cosas, y eso rompa el sistema.
  • Busca tu zona óptima de dificultad. Si algo es demasiado sencillo te resultará aburrido, si es demasiado complicado, te resultará inalcanzable, encuentra el punto medio para poder seguir progresando de tal manera que no te quedes atascado, ya que la mayor amenaza no es fallar, sino aburrirse.

Apéndices y extras

En la parte final del libro, podremos ver un resumen de todas las sugerencias, simplificadas para un acceso rápido, así como enlaces a los trackers, a listas paso a paso para mantener hábitos, y extras sobre hábitos en la paternidad o en el mundo de los negocios.

Conclusiones

Atomic Habits es un libro que no puedo dejar de recomendar si te gusta la ciencia, y sobre todo la práctica de la mejora continua a través de pequeños cambios que representan grandes resultados a lo largo del tiempo. El estilo práctico, unido a los ejemplos y detalles como resúmenes al final de cada capítulo y extras al principio y al final, hacen que la lectura sea rápida y entretenida.

Te recomiendo, además, que visites el blog del autor James Clear en el que define de manera monográfica muchos de los temas tratados en el libro, con lo cual si te gusta el libro te gustará el blog, y viceversa.

Atomic Habits está disponible en formato físico y ebook en Amazon y como audiolibro en Audible

Espero que te resulte tan interesante como a mí.

Creando un sistema basado en reglas en Java

Hace tiempo cuando intentaba aprender Scala, compré el libro Exercises for Programmers y últimamente he dedicado algo de tiempo a hacer uno de los ejercicios, que consiste en un sistema basado en reglas muy simple.

Los sistemas basados en reglas son un subconjunto de los sistemas expertos, que a su vez se engloban en el área de la inteligencia artificial. En el contexto de este artículo, simplificaremos los conceptos, quedándonos con un simple árbol de decisión, que nos permitirá llegar a una conclusión basándonos en las respuestas del usuario.

Podemos encontrar ejemplos de estos sistemas en asistentes paso-a-paso, en las centralitas telefónicas (“Para consultar el saldo, pulse 1”) y en los asistentes digitales como Alexa, Siri, Cortana o Google. Cuando escribimos un sistema de este tipo, nuestra lógica tendrá el siguiente aspecto:

sistema pregunta a.
si usuario responde si:
    sistema pregunta b.
    si usuario responde = "si"
        sistema responde c <- Respuesta final
si no
    sistema pregunta d
...

Esta información puede vivir en nuestro código fuente en formato de if, else anidados o puede formar parte de los metadatos de nuestro sistema. En el artículo de hoy diseñaremos uno de estos sistemas utilizando Java y la siempre útil consola de comandos.

Además de escribir nuestro sistema de reglas, en este artículo mencionaremos por encima los siguientes temas:

  • Tests unitarios con JUnit y AssertJ
  • Generación de Setters y builders con Lombok
  • Manejo de Ficheros yaml con snakeyaml
  • Inyección de dependencias e inversión de control
  • Creación de paquetes JAR con Gradle incluyendo dependencias

Los tests

Una práctica que intento seguir a la hora de hacer este tipo de ejercicios, es empezar por las pruebas al más puro estilo TDD, definiendo de manera inicial el estado al que queremos llegar.

Podemos emplear JUnit y AssertJ para ejecutar los tests, y agregar las referencias a Gradle es tan sencillo como utilizar las siguientes líneas:

testCompile group: ‘junit’, name: ‘junit’, version: ‘4.12’
testCompile(“org.assertj:assertj-core:3.11.1”)

Con ello podemos escribir nuestro primer test:

@Test
public void question() {
    assertThat(expertSystem.getMessage()).isEqualTo("Are you able to see any wifi network?");
}

Una vez pedido el estado inicial, hemos de comprobar que el motor pasa del primer estado al siguiente, como hemos en el siguiente test:

@Test
public void firstAnswerYes() {
    assertThat(expertSystem.getMessage()).isEqualTo("Are you able to see any wifi network?");
    expertSystem.answer(true);
    assertThat(expertSystem.getMessage()).isEqualTo("Is the network ID visible?");
    assertThat(expertSystem.isDone()).isFalse();

Finalmente, podemos comprobar que hemos llegado a un estado final con el siguiente test:

@Test
public void secondAnswerYesYesDone() {
    assertThat(expertSystem.getMessage()).isEqualTo(Are you able to see any wifi network?");
    expertSystem.answer(true);
    assertThat(expertSystem.getMessage()).isEqualTo("Is the network ID visible?");
    expertSystem.answer(true);
    assertThat(expertSystem.getMessage()).isEqualTo("Contact your network provider");
    assertThat(expertSystem.isDone()).isTrue();
}

Con estos tests, definimos un sistema de reglas que:

  • Recibe una respuesta binaria, que puede ser sí o no.
  • Proporciona el estado actual así como la información de si el estado actual es final o no.

El motor de reglas

Para este ejemplo, el motor de reglas no es más que un árbol binario con una clase muy sencilla que contiene dos hijos, “sí” y “no”, para cada rama:

@Getter
@Builder
class Stage {

    private String status;
    private Stage yes;
    private Stage no;

    boolean isEnd(){
        return yes == null && no == null;
    }
}

Para crear tanto la construcción de los objetos como los getters como el patrón builder podemos recurrir a Lombok, del que ya hemos hablado en otros artículos de este blog, y que podemos agregar a nuestro modelo de Gradle con las siguientes líneas:

compileOnly ‘org.projectlombok:lombok:1.18.8’
annotationProcessor ‘org.projectlombok:lombok:1.18.8’

A la hora de pasar de una etapa a otra, el motor de reglas simplemente decide qué hijo tiene que buscar:

private Stage current; //Aquí inicializaremos la etapa inicial

public String getMessage() {
    return current.getStatus();
}

public void answer(boolean answer) {
    if (answer){
        current = current.getYes();
    } else {
        current = current.getNo();
    }
}

public boolean isDone() {
    return current.isEnd();
}

Una comprobación que no forma parte del código es qué pasa si la etapa ya es final. Por otra parte se podría transformar bloque IF en un operador ternario, dando como resultado algo como current = answer ?? current.getYes() : current.getNo();

El almacenamiento

En el apartado anterior no hemos mencionado cómo inicializar las reglas. Podemos empezar por crear los objetos como parte del constructor, dando como resultado algo así:

Stage root = Stage.builder()
        .status(“Are you able to see any wifi network?”)
        .yes(Stage.builder()
                .status(“Is the network ID visible?”)
                .yes(Stage.builder()
                        .status(“Contact your network provider”)
                        .build())
                .build())
        .no(Stage.builder()
                .status(“Wireless network might be off. Reboot computer”)
                .build())
        .build();

Sin embargo, esta aproximación genera un fuerte acoplamiento entre el código y los datos, así que es una buena práctica sacar las reglas del código a un formato diferente, optando en este caso por YAML.

Al transformar nuestro árbol de Java a YAML tenemos como resultado la siguiente estructura, y este fichero lo podemos almacenar en la carpeta resources de nuestro proyecto:

text: "Are you able to see any wifi network?"
yes:
  text: "Is the network ID visible?"
  yes:
    text: "Contact your network provider"
  no:
    text: "Reboot the wireless router"
no:
  text: "Wireless network might be off. Reboot computer"

Para leer el fichero YAML podemos utilizar SnakeYaml, que podemos importar en Gradle con la siguiente línea:

compile group: ‘org.yaml’, name: ‘snakeyaml’, version: ‘1.8’

Finalmente, podemos cargar el fichero YAML en memoria de la siguiente manera.

class YamlLoader implements FileLoader<Stage> {

    public Stage loadFromFile() {
        Yaml yaml = new Yaml();
        InputStream inputStream = this.getClass()
                .getClassLoader()
                .getResourceAsStream("options.yaml");
        Map<Object, Object> obj = (Map<Object, Object>) yaml.load(inputStream);

        return getStage(obj);
    }

    private Stage getStage(Map<Object, Object> obj) {
        if (obj == null) {
            return null;
        }

        return Stage.builder()
                .status(obj.get("text").toString())
                .yes(getStage((Map<Object, Object>) obj.get(true)))
                .no(getStage((Map<Object, Object>) obj.get(false)))
                .build();
    }
}

Para no tener un acoplamiento entre nuestra clase ExpertSystemy YamlLoader, la segunda implementa una interfaz genérica llamada FileLoader que simplemente define un método, lo que nos da la posibilidad de agregar otros gestores de ficheros en el futuro como xml o JSON.

public interface FileLoader <T> {
    T loadFromFile();
}

Finalmente la conexión entre nuestra clase ExpertSystemy el gestor de ficheros se realiza en el constructor:

public ExpertSystem(FileLoader<Stage> fileLoader) {
    current = fileLoader.loadFromFile();
}

Este último paso no deja de ser inyección de dependencias e inversión de control. De esta manera, nuestra clase ExpertSystem es completamente independiente del formato en el que almacenemos nuestros datos, y podemos probarla de manera aislada, mientras mantenemos nuestra lógica de carga de YAML independiente de la lógica del motor de reglas.

La interacción

Para que nuestro código sea utilizable necesitamos, además de un algoritmo que funcione, una manera de interactuar con nuestro sistema. Para eso, volvemos a los mecanismos basados en System.outy System.in para escribir y leer por la consola.

public class UI {

    public static void main(String[] args) {
        ExpertSystem system = new ExpertSystem(new YamlLoader());

        Scanner scanner = new Scanner(in);

        while (!system.isDone()) {
            out.printf("%s %s ", system.getMessage(), Option.getOptions());
            system.answer(Option.parse(scanner.nextLine()));
        }

        scanner.close();
        out.println(system.getMessage());
    }
}

Finalmente, podemos extraer la gestión de la entrada a una clase específica llamada Option:

class Option {

    private static final String truthy = "yes";
    private static final String falsy = "no";

    static String getOptions() {
        return String.format("[%s/%s]:", truthy, falsy);
    }

    static boolean parse(String input) {
        if (input.toLowerCase().equals(truthy)) {
            return true;
        } else if (input.toLowerCase().equals(falsy)) {
            return false;
        }

        throw new IllegalArgumentException();
    }
}

Esta clase analizará la entrada que recibimos de la consola y generará un valor verdadero o falso, que luego podemos pasar posteriormente a nuestro motor.

Creando nuestro paquete jar

El último paso de nuestro sistema es empaquetarlo para pode distribuirlo. En nuestro caso lo que queremos es un fichero jar que se pueda ejecutar de manera independiente.

Para ello, hemos de modificar nuestro fichero Gradle para agregar ciertas directivas que, por una parte, establecen la clase principal de nuestro proyecto, y por otra parte, fuerzan a que se combinen las diferentes dependencias que tiene nuestra aplicación. Este paso se muestra a continuación:

jar {
    manifest {
        attributes "Main-Class": "net.rlbisbe.expert.UI"
    }

    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

Finalmente, solamente tenemos que ejecutar java -jar NuestroPaquete.jar, y podremos ver nuestro sistema en funcionamiento:

Recapitulando

A lo largo de este artículo, hemos visto cómo crear un simple sistema basado en reglas, cómo cargar dichas reglas de un fichero YAML, mientras repasábamos conceptos como inversión de control e inyección de dependencias, pruebas unitarias, y aprendíamos a manejar dependencias en Gradle.

No pierdas la oportunidad de echarle un ojo a Exercises for Programmers que tiene este y otros problemas para aprender nuevos lenguajes, probar maneras diferentes de hacer las cosas o practicar conocimientos.

Puedes encontrar el código fuente de este ejemplo en Github – Expert-System