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

Sobre cultura de trabajo en equipos remotos

El pasado jueves estuve en la primera sesión del grupo MADnagers in tech y el tema de conversación era “Gestionando equipos en remoto”, presentado por Pablo Carranza, Head of Engineering en Cabify.

Aunque tuve la mala suerte de llegar un poco tarde y perderme los primeros minutos de presentación, lo que pude ver me resultó realmente interesante, así que no quería perder la ocasión de compartir mis notas y aprendizajes de esta sesión.

Dos ritmos de trabajo en paralelo

Una de las ideas más interesantes que se comentó fue la de los dos ritmos de trabajo a los que nos enfrentamos en una organización, y que funcionan a la par:

El primero se refiere al aquí y ahora, las características, bugs, y problemas a los que se está enfrentando el equipo a fecha de hoy. Este ritmo es el que se suele ver diariamente en las standups, en los correos “urgentes” y en la cola de tickets que nos vienen de atención al cliente. El responsable de llevar este ritmo es el propio equipo, que tiene todo el contexto sobre el aquí y ahora, siendo la labor del líder del equipo la de desbloquear situaciones, pero no la de controlar cada tarea.

El segundo se refiere al futuro, aquí es donde están las nuevas peticiones, el estado de los proyectos que se ejecutarán más adelante, las nuevas iniciativas, las migraciones, y todo lo que no tenga el carácter de “Urgente”. En este caso el responsable de llevar este ritmo es el líder del equipo, de fijar el contexto y mantener la conversación sobre el futuro, especialmente a la hora de encontrar bloqueos que afecten al equipo

Uno de los puntos en los que más incidió Pablo fue en la necesidad de que tanto el presente como el futuro convivieran, idealmente, en el sistema de control de tareas, ya sea Jira, Github, Gitlab u otros.

Esto es debido a que el sistema de control de tareas permite mantener una conversación de manera asíncrona y pública y en diferentes hilos. Esto es especialmente importante en el caso de equipos remotos, ya que por una parte, no todos los miembros del equipo tienen que estar disponibles a la misma hora, y por otra, garantiza que en el futuro cualquier miembro del equipo pueda acceder a este historial, especialmente nuevos miembros.

Roadmaps permanentes y controlados

Otro punto destacado fue la gestión del Roadmap, en la que pasamos de un documento de Word compartido por email a un sistema controlado y versionado.

Un roadmap es importante en cuanto a que define la dirección a la que vamos, y por tanto es un documento que debería cambiar lentamente y de manera controlada. Si un roadmap está cambiando constantemente se convierte en un documento que no es fiable, y por tanto se le deja de presentar atención.

Es por ello que una idea que plantea Pablo es la de mantener el roadmap de manera controlada y controlar qué cambios se hacen al mismo. La manera más fácil de hacer esto es mantener el roadmap en un fichero markdown dentro de nuestro control de versiones, que las actualizaciones del mismo se realicen vía pull request, y que se pueda tener una conversación sobre la misma de manera pública y asíncrona.

Esto además nos permitiría mantener el histórico de donde estábamos hace 1 año, 6 meses, y ver si lo que queríamos hacer entonces lo queremos hacer ahora.

Si no está escrito, no pasó

En este punto, mencionaba dos ceremonias que suelen ocurrir cuando tenemos un equipo parcialmente remoto, las reuniones formales, como por ejemplo la standup, y las reuniones informales, como las conversaciones de pasillo.

Por lo general, salvo que exista una agenda definida y unos minutos tras la reunión, no se suele dejar constancia de que lo que se ha contado en una reunión, especialmente si la información solamente se comparte en ese momento y no queda en una tarea.

Esto es especialmente delicado en lo que respecta a las conversaciones de pasillo, ya que suelen ir acompañadas por una toma de decisiones que no suele quedar documentada, ni la decisión, ni las razones de la misma.

Pensando en este tema me ha venido a la memoria el año 2012, cuando formaba parte del equipo de Códice Software haciendo PlasticSCM, que durante las standups un miembro del equipo tomaba nota del estado que compartía cada miembro del equipo, y luego ese estado se actualizaba en una wiki de manera pública.

De esta manera, al final del sprint se podría comprobar cómo había sido el progreso del mismo, y habría un registro. Por otra parte, si alguien se incorporaba después de unos días de vacaciones, era tan sencillo como ir al registro del sprint, leer el estado y ponerse al día de manera asíncrona,

Cuidado con los Silos

Otro de los puntos comentados se refería a cómo el no compartir la información de manera pública puede acabar provocando silos de información, cuando solamente ciertas personas conocen el estado de un sistema porque lo diseñaron ellos, o peculiaridades de una integración que no están documentadas porque es conocimiento tribal.

Para ello es muy importante tomarle el pulso al equipo, ver cómo están hablando, cómo se están comunicando y encontrar los mejores canales para ello, wikis, sistemas de tareas, repositorios y otros mecanismos más allá de reuniones, chats o email.

Equipos remotos y la ley de Conway

La importancia de mantener unos niveles de comunicación adecuados en un equipo va más allá de que sea más sencillo seguir el rastro a tareas, de que el equipo no tenga que estar preocupado de lo que va a decir en la standup, o que las reuniones de sincronización se extiendan durante varias horas hasta que el estado quede claro.

De acuerdo con la ley de Conway, esto afecta directamente a cómo producimos el software en nuestras organizaciones:

Las organizaciones dedicadas al diseño de sistemas […] están abocadas a producir diseños que son copias de las estructuras de comunicación de dichas organizaciones

Melvin Conway

Por tanto, si formamos parte de equipos remotos y nuestra estructura de comunicación es pública y asíncrona acabaremos haciendo mejor software.

Conclusiones

  • Tenemos muchos sistemas a nuestra disposición para compartir el estado de nuestras tareas más allá de una reunión de 15 minutos en la que cada miembro del equipo tiene 30 segundos para hablar.
  • Compartir información de tal manera que no necesitemos a todos los miembros del equipo presentes a la misma vez nos permite ganar tiempo, ya que la información se mantiene en un punto común y de manera estable, especialmente a la hora de tomar decisiones, documentando las decisiones tomadas y las razones para las mismas.
  • Mantener la información públicamente accesible y simplificar canales de comunicación sencillos permite mitigar la aparición de silos de información, en las que solamente un subconjunto del equipo conozcan cierta información que todos deberían conocer.
  • Conseguir un sistema que permita que el estado esté fácilmente disponible, y que los canales de comunicación estén claros, no solamente afecta a la actitud del equipo, sino que tiene un impacto directo sobre el software que producimos.

Lecturas adicionales

Pablo escribió un artículo en su blog en el que habla de estos temas y los desarrolla con un gran nivel de detalle, además durante el evento mencionó el Remote Manifesto de Gitlab, y la teoría de las limitaciones (theory of constraints) que se hizo conocida en el ibro The Goal y que se ha llevado al campo de IT en el libro The Phoenix Project, que comenté el pasado año.

[Cloud Running – I] Creando un dashboard en QuickSight con los datos de Strava

A lo largo de los últimos meses he estado trabajando casi a diario utilizando QuickSight, una herramienta de AWS que nos permite visualizar datos de manera sencilla, completamente SAAS y con la capacidad de acceder a un montón de orígenes de datos, ah, es gratis como parte de la capa gratuita de AWS y tiene su interfaz localizada tanto en castellano como en otros idiomas.

QuickSight no es tan conocido como otras herramientas como Tableau o PowerBI, ya que está menos extendida y presenta una manera muy simple de trabajar con datos, así que quería aprovechar lo aprendido en estos últimos meses y compartirlo en el blog, ya que me parece una herramienta muy interesante sobre todo por la simplicidad de uso.

En este capítulo y a lo largo de esta serie que he llamado Cloud Running, veremos cómo podemos crear un análisis de QuickSight utilizando un conjunto de datos simple, revisando las limitaciones que podamos tener, creando campos calculados y generando nuestras dashboards, y mi plan es continuar la serie complicando el conjunto de datos, jugando con actualizaciones, y finalmente trabajando con orígenes de datos adicionales.

El resultado final de este artículo será el dashboard, o panel como lo denomina QuickSight en su traducción al castellano, que te muestro a continuación:

Subiendo nuestro conjunto de datos de ejemplo

Todo en QuickSight empieza por el conjunto de datos. Un conjunto de datos no deja de ser una información tabulada que analizaremos posteriormente, que puede ir desde ficheros separados por comas, bases de datos relacionales, o fuentes de datos utilizando APIs como Twitter, como podemos ver a continuación en el menú de Administrar datos -> Nuevo conjunto de datos:

Para este ejemplo usaremos un fichero separado por comas que tiene este aspecto:

Este fichero lo obtuve de Strava, que permite una opción de descargar toda nuestra información en un fichero ZIP como parte del proceso de eliminación de nuestra cuenta. Podemos obtener el fichero sin eliminar la cuenta, y es suficientemente completo como para usarlo en este ejemplo.

Una vez subimos nuestro fichero separado por comas a QuickSight, veremos la pantalla de edición de nuestro conjunto de datos:

En esta pantalla podemos cambiar el nombre de los campos, el tipo de dato, seleccionar el separador de nuestro conjunto de datos, así como generar campos calculados, que veremos más adelante.

Un apunte importante: Una de las claves de la rapidez de QuickSight es su motor en memoria SPICE, que permite cargar un conjunto de datos en memoria y acceder a él con gran rapidez, de modo que, al manipular nuestro conjunto de datos no necesitamos acceder a los datos originales, sino que estamos accediendo a una proyección de dichos datos. Esto significa que no siempre tendremos los datos más actualizados, aunque discutiremos actualización en el próximo artículo.

Una vez estemos satisfechos con nuestro conjunto de datos, el siguiente paso es crear un análisis, lo cual nos presenta una pantalla como la siguiente:

Para empezar a generar gráficos, tan solo tenemos que pulsar en los campos que queremos combinar, y el tipo de gráfico que queremos mostrar. Para crear gráficos adicionales, podemos hacer click en el botón + situado en la barra de herramientas:

Si tenemos seleccionada la opción de AutoGraph marcada por el rayo, QuickSight generará un tipo de gráfico adecuado a cada tipo de datos.

Por ejemplo, seleccionar un único campo como distance nos generará un campo de totales:

Una selección de type nos puede generar un gráfico de barras:

Y finalmente la combinación de los campos distance y date nos generaría una serie de tiempo:

Personalizando nuestros gráficos

Además de utilizar la función AutoGraph, podemos seleccionar el tipo de gráfico que queremos, así como los valores que queremos para las diferentes dimensiones, que varía en función del tipo de gráfico:

Tenemos además diferentes opciones de personalización, que podemos ver haciendo click en los diferentes desplegables con forma de V.

A la hora de personalizar las dimensiones, por ejemplo, en los campos de fecha podemos cambiar la granularidad de la agregación o el formato en el que se muestra la información. En el campo valor, podemos utilizar suma, media, contar, contar excluyendo duplicados, max y min, entre otros, así como personalizar el número de decimales y la escala en la que mostramos nuestros datos, teniendo miles, millones, miles de millones y billones, lo que permite mostrar el K que vemos en el gráfico original.

Además de las dimensiones podemos personalizar los gráficos, seleccionando Formato del elemento visual en el desplegable con forma de V. En el caso que nos ocupa, podemos personalizar valores como el intervalo a mostrar, qué hacer cuando faltan datos, el numero de líneas que tienen los ejes, o las etiquetas de los propios datos.

Enriqueciendo nuestros datos con campos calculados

Otra de las posibilidades que nos aporta QuickSight es el uso de campos calculados tanto a nivel de conjunto de datos como de análisis.

Importante: Las funciones que están a nivel de conjunto de datos son diferentes de las que encontramos a nivel de análisis!

Además de las operaciones aritméticas como suma, resta, multiplicación y división, tenemos un conjunto de funciones lógicas como ifelse, matemáticas como round, floor o ceil y de manejo de cadenas de caracteres como trim, replace, concat u otras.

Un ejemplo de estas funciones, ha sido el tiempo total en minutos, que he hecho con la siguiente fórmula simple: {elapsed_time} / 60 y el ritmo (en min/km), que he utilizado el campo calculado anteriormente: {elapsed time in minutes}/{distance}*1000

A nivel de análisis, el conjunto de funciones que podemos utilizar es diferente, ya que incluye, funciones que podemos aplicar al conjunto total, y no fila a fila, entre los que podemos encontrar count, avg, max, min, percentile así como funciones de manejo de fechas, entre otras.

Limitaciones

Una de las limitaciones con las que me he encontrado a la hora de hacer este ejemplo es el soporte limitado para campos de tipo tiempo. Si bien es cierto que podemos manipular fechas, en el ejemplo que estaba buscando, uno de los valores que quería conseguir era ritmo en minutos por kilómetro, utilizando formato de minutos y segundos, algo que en estos momentos no podemos conseguir en QuickSight.

Creando un dashboard o panel

Los análisis nos permiten editar los campos, moverlos y desplazarlos a nuestro antojo, y compartirlos con otros miembros de nuestro equipo para modificarlo. Sin embargo, habrá situaciones en las que queramos un modo de “solo lectura” para compartir con otros perfiles de nuestra empresa.
Para ello podemos publicar un dashboard o panel, donde podemos publicar uno nuevo o reemplazar existentes. Una vez publicado, lo podemos hacer disponible a todos los miembros de la cuenta o bien invitar solamente a personas específicas.

Otras características

QuickSight tiene más características de las que hemos visto en este artículo pero que se me quedan fuera de este, entre las que destacan:

  • Filtros, que nos permiten ver un subconjunto de datos en un gráfico, en un conjunto de gráficos o en todo el análisis.
  • Parámetros, que permiten modificar nuestro análisis utilizando una lista de valores predeterminados o dinámicos, y que podemos asociar a filtros y controles para modificar nuestro análisis de manera sencilla.
  • Acciones de URL, que permiten enlazar una página web externa utilizando un formato que especifiquemos, por ejemplo, podríamos enlazar el ID de actividad de Strava para que nos llevara directamente a la URL de la misma.
  • Historia en la cual podemos definir varias etapas del mismo análisis, útil cuando queremos tener varios tipos de filtros aplicados en cada una de las historias, y queremos hacer una narrativa de cómo han cambiado los números por trimestre fiscal, por ejemplo.

Conclusiones

QuickSight como hemos visto es una herramienta bastante versátil para análisis de datos, completamente online, y que nos permite crear conjuntos de datos, utilizar campos calculados a nivel de conjuntos de datos y de análisis, crear gráficos y personalizarlos a nuestro gusto, así como cómo guardar y compartir las vistas que creamos.

En el próximo artículo de la serie, siguiendo con la temática de Running, veremos qué pasa cuando tenemos nuevos datos a lo largo del tiempo, y cómo podemos hacer que estos cambios se vean reflejados en QuickSight.

Lecturas adicionales

Una manera diferente de hacer tests en Java con Specnaz

La popularización de lenguajes como Ruby y JavaScript de lado de servidor, ha generado en los últimos años nuevos frameworks de pruebas centrados en lo que se denomina pruebas de especificación, en la cual probamos nuestro código utilizando siempre los casos de uso de dominio, de una manera visual, herramientas como como RSpec, Mocha, o Jest, que siguen una estructura muy similar a la mostrada a continuación.

Supongamos que queremos probar una estructura de tipo Stack:

describe "A Stack"
    describe "pop"
        it "should get the item from the top of the stack"
            //CODE

        it "should get null if stack is empty"
            //CODE			

Esta manera de hacer pruebas contrasta con el estilo que podemos ver en lenguajes como Java en JUnit:

class StackTests

    void test_when_pop_get_item_from_top
        //CODE
    
    void test_when_pop_get_null_if_empty
        //CODE

Aunque son ejemplos muy sencillos, al aumentar la complejidad de nuestra base de código, aumentan también los casos de uso que manejamos, y por tanto el número de tests. Para ello, el estilo de las pruebas de especificación nos permiten agregar casos adicionales reduciendo duplicidad y mejorando la legibilidad.

En el artículo de hoy veremos un framework que nos permitirá hacer este tipo de pruebas en Java, llamado Specnaz y creado por Adam Ruka.

Para este ejemplo utilizaré la kata bowling definida aquí: http://kata-log.rocks/bowling-game-kata.

Nuestro primer test

Para nuestro primer test definimos la primera condición de nuestro juego, que es que un juego vacío devuelva 0 como primer resultado.

...
public class BowlingSpec extends SpecnazJUnit {
    {
        describes("A Game", it -> {
            Game game = new Game();
            it.should("show 0 as score when first created", 
                                () -> assertThat(game.getScore()).isEqualTo(0));
        });
    }
}

Nuestro objeto "Game" tendrá este aspecto inicialmente:

...
public class Game {
    public int getScore() {
        return 0;
    }
}

Inicializadores

Una de las cosas que podemos hacer en nuestros tests, es crear una inicialización antes de cada test, así como una limpieza, esto lo podemos conseguir utilizando el comando de beginsEach como se muestra en el ejemplo:

...
public class BowlingSpec extends SpecnazJUnit {
    {
        describes("A Game", it -> {
            Game game = new Game();
            it.beginsEach(game::reset);
            it.should("show 0 as score when first created", 
                                () -> assertThat(game.getScore()).isEqualTo(0));
        });
    }
}

En vez de crear una instancia nueva de Game, en este ejemplo creamos un método de inicialización dentro del objeto Game que reinicia el estado de la partida. Debido a que estamos en el contexto de una lambda, no podemos redefinir el valor de una variable externa, con lo cual ejecutar el constructor repetidamente no funcionaría

Creando ramas en nuestros tests

Una de las características más interesantes que nos aportan este tipo de tests es la posibilidad de crear ramas con las diferentes condiciones de prueba sobre las que ejecutamos nuestros tests. Veamos un ejemplo:

describes("A Game", it -> {
    ...
    it.describes("when throwing a spare", () -> {
        it.should("account for the number of pins knocked down by next roll", () -> {
            game.roll(4);
            game.roll(6);
            game.roll(4);
            game.roll(0);
            assertThat(game.getScore()).isEqualTo(18);
        });
    });
});

Dentro de cada grupo de "describes" podemos además definir nuestras propias secuencias de inicio y fin de cada test, creando un árbol de casos de uso y evitando repetición innecesaria.

Usando parámetros

En el caso de la kata bowling, una manera muy útil de agrupar los tests es utilizando parámetros, y para ello podemos utilizar una construcción de Specnaz llamada SpecnazParamsJUnit en el caso de que estemos utilizando JUnit como motor de ejecución de tests.

En este ejemplo podemos ver además cómo especificamos los parámetros, y cómo en la cabecera should podemos asignar valores a parámetros:

public class BowlingParamsSpec extends SpecnazParamsJUnit {
    {
        describes("A Parametrized Game", it -> {
            Game game = new Game();
            it.beginsEach(game::reset);

            it.should("properly calculate the gameplays of %1 equal %2", (List<Integer> rolls, Integer expected) -> {
                rolls.forEach(game::roll);
                assertThat(game.getScore()).isEqualTo(expected);
            }).provided(
                    p2(Arrays.asList(2, 3), 5),
                    p2(Arrays.asList(4, 6, 4, 0), 18),
                    p2(Arrays.asList(2, 4, 6, 3), 15),
                    p2(Arrays.asList(10, 3, 6), 28),
                    p2(Arrays.asList(10, 10, 10, 0, 0), 60),
                    p2(Arrays.asList(0, 0, 10, 10, 10), 60),
                    p2(Arrays.asList(10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10), 300)
            );
        });
    }
}

El resultado en nuestra ventana de tests será el siguiente:

should properly calculate the gameplays of [2, 3] equal 5
should properly calculate the gameplays of [4, 6, 4, 0] equal 18
should properly calculate the gameplays of [2, 4, 6, 3] equal 15
should properly calculate the gameplays of [10, 3, 6] equal 28
should properly calculate the gameplays of [10, 10, 10, 0, 0] equal 60
should properly calculate the gameplays of [0, 0, 10, 10, 10] equal 60
should properly calculate the gameplays of [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10] equal 300

Manejando excepciones

No es raro que tengamos que encontrarnos con situaciones más o menos excepcionales cuando creamos nuestros tests, y eso incluye ciertos casos de prueba. Para probar excepciones podemos recurrir a shouldThrow que nos permite controlar el tipo de excepción que lanzamos:

it.shouldThrow(IllegalArgumentException.class, "when trying to roll more than 10 bowls in a single roll", () -> {
   game.roll(11);
});

El resultado incluirá además el detalle del tipo de excepción que estamos intentando controlar en el mensaje que se muestra por la consola:

should throw IllegalArgumentException when trying to roll more than 10 bowls in a single roll

Tanto el ejemplo con parámetros como el ejemplo que acabamos de ver nos libran de cometer errores en la cabecera de los tests, ya que se define la excepción que estamos probando así como los parámetros, de tal manera que si cambiaran, cambiaría el nombre del test.

Conclusiones

Como hemos visto durante el artículo, Specnaz es un framework de pruebas de especificación que nos permite definir nuestras pruebas de una manera robusta, evitando duplicidades y permitiendo escribir con detalle qué estamos probando y bajo qué especificaciones.

Además de los ejemplos de este artículo, en su repositorio de github se pueden ver ejemplos de uso con herramientas como mockito para generar dobles de test y poder simular el comportamiento de otras clases, ya que en raras ocasiones probaremos código que no tenga dependencias.

Puedes aprender más detalles en los siguientes enlaces:

Creando diagramas de manera efectiva con el modelo C4

En nuestro día a día empleamos múltiples niveles de abstracción para referirnos a los sistemas de información que construimos, manipulamos o mantenemos, nos referimos a sistemas, aplicaciones, servicios, APIs, llamadas, funciones, almacenamiento, memoria, ficheros, eventos, etc.

Muchas de estas abstracciones las comentamos de manera informal, las describimos a través del código que escribimos y que ejecutamos, las describimos en prosa, o empleamos la herramienta favorita de los arquitectos y la más temida por los desarrolladores, los diagramas.

Un diagrama, ya sea de componentes, de secuencia, de interacción o de clases, no es más que otra abstracción en la que describimos como es o cómo pretendemos que sea nuestro sistema. El diagrama nos puede permitir pasar por ciertas capas de descubrimiento, descubrir o fijar los límites de nuestro servicio en comparación con otros, y es una herramienta que nos permite mantener una conversación.

Esta herramienta es crítica cuando tenemos que interactuar con otros equipos, o compañeros que pueden no tener todo el contexto. Es por ello que es importante tener en cuenta el público, el objetivo, y el nivel de abstracción que queremos mantener. al crear dichos diagramas y representar contextos

Una metodología para la representación de diagramas que he estado poniendo en práctica recientemente es el modelo C4 por Simon Brown, en el cual, siguiendo ciertas prácticas e iterando sobre nuestros diagramas, podemos diseñar nuestro sistema utilizando varios niveles de abstracción:

  • Contexto
  • Contenedor
  • Componente
  • Código

Pese a que el modelo define 4 capas, en este artículo hablaremos de las tres capas superiores, ya que la cuarta se asemeja bastante a diagramas a los que podamos estar más familiarizados, y en ocasiones no es necesario ni siquiera llegar a ellas.

El ejemplo

A la hora de escribir el artículo pensé en algo del estilo “lista de tareas” dada mi obsesión por las aplicaciones, metodologías y otros, pero al final me decanté por un sistema que me permitiera escribir artículos en un blog.

Los requisitos son los siguientes:

  • Un lector puede ver artículos publicados y escribir comentarios.
  • Un autor puede escribir artículos, editarlos y borrarlos
  • Un autor, además, recibirá una notificación cuando se cree un nuevo comentario.

Vayamos manos a la obra:

Nivel 0: Contexto

tbe-blog-page-3

A este nivel queremos definir de manera clara quienes son los actores que interactúan con nuestro sistema, qué sistemas tenemos, y una primera idea de cómo se relacionan entre ellos.

A este nivel podemos tener una conversación con un potencial usuario del sistema, o con nuestros compañeros de negocio, ya que los casos de uso generales se definen aquí.

Es también una oportunidad para destacar qué queda fuera del sistema, y hasta qué punto se pueden modificar esos sistemas. Podemos utilizar esquemas de colores para destacar qué sistemas podemos y cuales no podemos modificar.

Nivel 1: Contenedores

Tbe Blog-Page-4

En este caso hacemos zoom en cada uno de los sistemas, y lo separamos en contenedores que tienen una función lógica. En el caso de nuestro blog tenemos dos subsistemas diferentes, uno encargado de la edición de artículos y otro de la visualización, así como una API entre la que interactúan ambos sistemas.

A este nivel podemos tener conversaciones a nivel técnico con diferentes equipos involucrados en el proyecto, el nivel de abstracción es menor, y podemos tomar decisiones como cuantos subsistemas construimos y cómo se reparte el trabajo de los mismos.

Nivel 2: Componentes

Tbe Blog-Page-5

Este nivel es el más profundo al que llegaremos en este artículo, aquí podemos establecer una separación más clara, en el caso de la UI podemos separar las diferentes páginas que existirán, y en el caso de la API backend los diferentes componentes que podemos emplear, en el que cada componente puede ser una librería, un paquete, un proyecto o una unidad semántica de código.

En este nivel podemos tomar decisiones de arquitectura directamente a nivel de equipo, entender las diferentes relaciones entre los diferentes componentes y modularizar más, si fuese necesario.

Evolución

Una de las características más interesantes de este estilo de modelado es que es iterativo, una vez que empiezas y vas pasando por las diferentes capas descubres que estabas empleando el modelo erróneo de abstracción, y mueves “cajitas” entre las diferentes capas.

El primer diagrama que hagamos nunca será perfecto, pero el hecho de tener tres diagramas diferentes e iterar entre ellos nos permitirá descubrir nuestra arquitectura, encontrar límites y tener una mejor idea del alcance de los productos que vamos a construir.

Desde el punto de vista práctico, recomiendo utilizar una herramienta que nos permita tener los tres tipos de diagramas visibles a la vez, ya que nos veremos en la situación de estar cambiando componentes entre los diferentes niveles de abstracción.

Retrospección

Podemos utilizar estos diagramas no solamente como una manera de crear software, sino también de familiarizarnos con software existente. A la hora de enfrentarnos a un nuevo proyecto, entender el sistema en el que nos encontramos nos permite mitigar el factor ”Pulpo en garaje” y ser más productivos desde el principio.

Conclusiones

En general los diagramas son otra herramienta que podemos utilizar tanto para descubrir, explorar o enterarnos de donde nos hemos metido, no son el fin, ni mucho menos, sino un medio para construir mejores sistemas. Metodologías como C4 nos permiten crear mejores diagramas y con ello, mejores sistemas.

Más información sobre el modelo C4 en la web de Simon Brown: The C4 model for software architecture

Imagen por Kaleidico vía Unsplash

Libro: ¿Cuando? La ciencia de encontrar el momento preciso

Soy de esas personas que, además de tener libros en casa que no han empezado, tengo muchos que empiezo y dejo por la mitad. En este mes de marzo he intentado ponerme al día en los libros que tengo empezados, algunos de ellos he tenido que volver a empezar desde el principio pero otros los he retomado por donde estaba.

Uno de los libros que he retomado es ¿Cuando?, de Daniel H. Pink (When: The Scientific Secrets of Perfect Timing en su versión en inglés).

Es un libro que habla de muchas cosas, pero sobre todo es un libro que habla del tiempo, desde la manera en la que somos productivos a lo largo del día, la diferencia entre búhos y alondras, pasando por los principios, los intermedios y los finales, hasta temas como el concepto del tiempo y del futuro, que no está presente de manera tan fuerte en todos los lenguajes y modifica no solamente la manera de interactuar, sino la manera de ver el mundo.

El libro se divide en tres bloques. Cada bloque, además, consta de una parte que podríamos denominar teórica o divulgativa, y una parte más práctica que Daniel denomina “Manual del Hacker del Tiempo” con consejos prácticos para poner en uso lo enseñado en el apartado anterior.

  • El día: En ella habla de cómo definimos nuestro día, cómo y cuando dormimos, cómo algunos somos de levantarnos pronto y otros de quedarnos hasta tarde, cómo afecta eso a nuestras decisiones, y cuando tomar decisiones importantes.
  • Comienzos, finales y mitades: En este bloque habla de diferentes tipos de comienzo, la importante de volver a empezar en algunos momentos de nuestra vida, la importancia de los finales, de por qué hacemos locuras o cosas intensas en el último año de cada década o cómo varían las relaciones entre la edad adulta y la vejez.
  • Sincronizar y pensar: Finalmente, usando como ejemplos a los dabbawalas, los miembros de un coro, y de un equipo de remo, habla de la importancia y la necesidad de mantener sincronía con aquello que marca el tiempo (que puede ser una persona, un reloj, una situación), sincronía con el grupo y finalmente, lo que denomina sincronía del corazón, es decir, la razón última de por qué hacemos las cosas, en el coro puede ser por motivos religiosos, en el remo por el esfuerzo conjunto, y en el caso de los dabbawalas, por la importancia de lo que están transportando, comida hecha en casa.

Un libro interesante, que te puede hacer pensar y reflexionar, siendo mi parte favorita la de los comienzos, finales y mitades. Todo lo que hacemos, inexorablemente tiene un principio, una mitad, y un final, como también lo tiene este artículo que comparto contigo, querido lector.

Si sientes curiosidad, tienes el libro disponible aquí: ¿Cuándo?: La ciencia de encontrar el momento preciso o si lo prefieres en versión original: When: The Scientific Secrets of Perfect Timing (English Edition)

Libro: The End of Procrastination

Procrastinar
Del lat.procrastināre.
1. tr. Diferir, aplazar.

RAE

Una de las cosas que intento hacer siempre que estoy en un aeropuerto es pasar por la sección de libros de las tiendas de Duty Free, si veo algo interesante en un idioma que entiendo y me puedo beneficiar de algún cambio de moneda, no lo dudo y compro un ejemplar, aunque tenga una pila infinita de libros por leer, con la errónea suposición de que leeré el libro mientras vuelo.

Así, casi dos meses después de su compra, te traigo “The End of Procrastination”, un libro corto (apenas 240 páginas de contenido) y pequeño que nos trae algunos trucos sobre cómo combatir la tendencia que tenemos algunos de postergar cosas, especialmente si son importantes o aburridas.

En un formato diferente a otros libros (cuadrado para ser exactos) y lleno de ayudas visuales, el libro nos provee con varias herramientas para intentar superarnos poco a poco.

Partiendo de un análisis personal, utilizando métodos como SWOT o DAFO para ver cuales son nuestras fortalezas y debilidades, una lista de lo que creemos que puedan ser nuestros mayores logros, así como una visión personal, podemos tener una idea más realista de donde estamos y a donde queremos llegar, siendo el principal objetivo limitar el espectro de opciones a nuestro alcance a aquellas que nos ayuden a lograr esa visión, ya que está demostrado que tener demasiadas opciones bloquea nuestra capacidad de elegir, y ante la frustración de no poder elegir, elegimos no hacer nada.

A partir de ahí, el libro pasa a temas más de nuestro día a día, como mantener actualizada una lista de hábitos, planificar las tareas diarias de manera visual, encadenando unas con otras y agregando marcadores de importancia, maneras de organizar aquellas tareas que no requieren acción inmediata, cómo tener listas de ideas en las cuales actuar a futuro, y cómo salir de nuestra zona de confort para poder hacer más.

Finalmente, el libro pasa a temas más complejos, como qué pasa cuando nos vemos en una situación de bloqueo, en el cual nos vemos atados a un presente o a una situación pasada negativa y no podemos salir de ahí, mencionando cómo tenemos el control sobre la manera en la que respondemos a estímulos, por mucho que puedan ser negativos, o cómo mantener una lista de cosas positivas que han pasado durante el día (otros autores lo mencionan como las tres gratitudes)

Personalmente me ha gustado el formato, aunque, tras haberlo intentado, no esté del todo convencido del formato de organización de tareas diarias, para ello me quedo con el método de Cal Newport que recomienda tanto en su blog Deep Habits: The Importance of Planning Every Minute of Your Work Day como en su libro Deep work, que ya comenté en este blog en 2016.

Como estas, muchas más herramientas y muchos más dibujos en The End of Procrastination: How to stop postponing and live a fulfilled life

Espero que te resulte interesante (y a diferencia de mi, tardes menos de dos meses en terminarlo).

De vuelta de WeCodeFest 2019

Este año he vuelto a Valladolid a aprender y compartir con compañeros de batallas en un evento con charlas, talleres y debates durante dos días siguiendo un formato mixto de agenda cerrada + open space.

Durante el evento tuve tanto la oportunidad de escuchar y comentar en varios foros que iban entre el uso de frameworks, el trato con clientes complicados, los procesos de onboarding… , así como facilitar dos sesiones, una relacionada con productividad y distracciones, y la otra relacionada con libros, eventos y charlas que nos han marcado o han cambiado nuestra manera de ver problemas.

Esta fue fue una ocasión más para volver a ver a los compañeros de Códice Software, creadores de PlasticSCM, y la casa que me acogió cuando salí de la carrera y donde realmente aprendí a construir software, a hacer tests y a descubrir la diferencia entre programa y producto. Después de más de 10 años siguen luchando contra viento y marea por hacer el mejor sistema de control de versiones del mundo.

A continuación resumo algunas ideas que me han parecido interesantes de las sesiones a las que he asistido:

Microservicios

Me llevo deberes, concretamente este artículo: the Twelve-Factor App que da una definición de qué constituye un microservicio. Durante la conversación se debatió además el hecho de utilizar microservicios como una manera de organizar equipos, y aislar funcionalidad para intentar mejorar problemas de comunicación entre equipos.

Motivación

Me llevo varios conceptos relacionados con motivación intrínseca, qué es lo que nos lleva a hacer lo que hacemos y a mantenerlo, que va en línea con lo que he estado leyendo últimamente y de lo que espero escribir pronto, y echar un vistazo a este libro Drive: de Daniel H. Pink.

Productividad y distracciones

Entre los puntos que discutimos en esta sesión me gustaría destacar.

  • La necesidad de proteger nuestra concentración (auriculares con cancelación de ruido, sonido de ambiente, ambientes silenciosos si es posible) y la de nuestros compañeros, (manda una pregunta por chat, y cuando él pueda contestará, y así el compañero controla cuanto quiere ser interrumpido).
  • El uso de técnicas como revisar el correo en momentos puntuales del día, desconectar notificaciones, cerrar Slack o usar técnicas como pomodoro para tener momentos de no molestar, que podemos combinar con herramientas como Cuckoo para que el equipo sea consciente de si otros compañeros están ocupados en ese momento.
  • Ls emociones que genera la música y cómo afecta a nuestra capacidad de concentración, y cómo herramientas como Noisli pueden generar ruidos “de ambiente” o directamente ruido blanco pueden ser más útiles que canciones, especialmente canciones con letra. Dichas emociones, por otro lado nos pueden ayudar a desconectar, relajarnos o directamente “sacarnos de la caja”.
  • El hecho de cuán interesante o aburrida sea la tarea constituye un factor importante a la hora de que nuestra mente esté buscando activamente distraerse, y que el aburrimiento provoque no solo que nos distraigamos sino que distraigamos a otros.

Libros que nos han marcado

En esta sesión hablamos de diversos tipos de fuentes de inspiración:

  • Libros de teoría y arquitectura de software o de gestión de equipos de desarrollo, entre los que están Extreme Programming, Scrum from the trences, Refactoring, Clean Code, Clean Architecture, Design Patterns, POSA, Documenting Software Architecture, The Pragmatic Programmer…
  • Libros y ejercicios prácticos como Learn You a Haskell for Great Good!, Go by Example o las Ruby Koans que son ejercicios prácticos que te obligan a terminar un código para aprender a usar el lenguaje.
  • Podcasts como Software Engineering Daily o Agile in 3 Minutes

Y ahora qué?

Seguir leyendo, seguir escribiendo y tener siempre presente una frase compartida en la sesión sobre motivación de equipo que decía: todo lo que has aprendido es inútil si no lo usas, y estéril si no lo compartes.

De momento, comparto, con la intención de usar los conocimientos aprendidos.

¡Gracias a la organización por hacer este evento posible!

18. Echando la vista atrás

Hace más de 7 meses desde mi última entrada en este blog, y no ha pasado mes en el que me diga “debería escribir más”, y siempre he encontrado excusas interesantes para no escribir, pero sobre todo, y la más importante, es que he tenido relativamente poco que compartir. Pero no podía dejar de hacer balance un año más de cosas que han pasado y poner un la vista en lo que queda por venir, así que aquí va mi retrospectiva.

En el ámbito profesional ha sido verdaderamente intenso, análisis de requisitos, diseño de arquitecturas, alineamientos con equipos de todas partes del mundo (a horas intempestivas tanto para los que trabajamos en GMT+1 como para los de otras zonas horarias), muchísimo código en Java 8, JavaScript y Kotlin, incontables líneas de test unitarios, de integración, de carga, varias horas de presentaciones ante compañeros, unas sesenta horas entre aviones y aeropuertos entre España, USA y el Reino Unido, muchos litros de café y de tinta tomando notas.

Siguiendo con el gremio pero fuera de “horas de oficina”, este año me perdí la BilboStack, con entrada, vuelo y hotel comprados :(, (este año lo intentaremos otra vez) aunque sí que me pude dejar caer por la MindCamp, a la Pamplona SW Craftmanship, a WeCode y LechazoConf en Valladolid, y a DotNet 2018, donde tuve la oportunidad de volver a ver a algunos amigos y compañeros de batallas. Entre otros eventos memorables, pude ver en directo a Martin Fowler hablando, entre otras cosas, de la importancia de la entrega continua, el valor de los tests, y cómo se podía implementar entrega continua en productos existentes (este habría sido un buen candidato para escribir del tema).

Algunos de los que me leéis sabréis que tengo la suerte de compartir profesión y pasión por la tecnología con mi madre, y que en algunos eventos yo me presento como “el hijo de Ana” y en otros ella se presenta como “la madre de Rober”. Este año he visto con el orgullo que solo un hijo puede ver como Microsoft le reconocían sus méritos a la comunidad al nombrarla Most Valuable Professional (MVP).

Para aquellos que no os suene, es un reconocimiento que entrega Microsoft a profesionales que hagan aportaciones significativas a la comunidad, como eventos, ayuda en los foros, artículos en blogs o revistas, contribuciones de código a proyectos Open Source… Ana lleva desde hace más de quince años formando parte de diversas comunidades relacionadas con tecnologías Microsoft, desde FoxPro, SQL y ahora Power BI. Como testigo de esa evolución, y de su capacidad de reinventarse, es todo un reconocimiento a tantos años de trabajo y dedicación a la comunidad.

En el ámbito deportivo, este año ha habido obligaciones profesionales y familiares que me han brindado una excelente excusa para no hacer más deporte, aunque he hecho un esfuerzo por acabar el año haciendo más kilómetros. De acuerdo con Endomondo en 2017 corrí entre calle y cinta unos 249 km, este año 267, un poco más que el año anterior, pero menos de lo que habría querido. Este año sin embargo me ha traído un éxito en parte inesperado, que ha sido un récord personal de 58:32 en la San Silvestre Vallecana el 31 de diciembre, superando la barrera de una hora que llevaba un par de años intentando conseguir.

Volviendo al blog, he escrito cuatro artículos, dos relacionados con AWS en mi intención de aprender para examinarme de Solutions Architect, un tercero como revisión del libro “The Phonenix Project” y el resumen de 2017. Es el segundo año consecutivo que escribo menos de un artículo al mes, lejos de aquel año 2014 en el que este blog cosechó 60 entradas, más de una semanal.

Finalmente, respecto a los objetivos fijados el pasado año, este año no he sido capaz de cumplir ninguno de ellos, así que listarlos parece un poco repetitivo.

Dicho lo cual, este año voy a listar no tanto objetivos específicos sino ciertos hábitos que estoy intentando incorporar en mi vida diaria.

  1. Conseguir concentrarme en bloques de, al menos, 15 minutos: Tras leer técnicas como Pomodoro, que hablan de fijar bloques para tareas de unos 25 minutos, o libros como Deep Work donde recomiendan bloques más largos de varias horas, creo que 2019 será un año para poner estos métodos en práctica, Leí recientemente este artículo How to Multitask Without Breaking Your Brain – Member Feature Stories – Medium y me llamó mucho la atención la idea de mantener la concentración durante al menos 15 minutos antes de cambiar de actividad, llevo unos días usándolo y es sorprendentemente poderoso.

  2. Correr cada semana: Había pensado originalmente en fijar algo así como “correr 500 km, pero el truco está en buscar el hábito de correr semanalmente, y que no sea algo puntual antes de cada carrera. Idealmente quiero estirar la cantidad de kilómetros que hago en cada sesión y reducir el ritmo cardiaco, para poder preparar mayores distancias sin que el cuerpo sufra demasiado.

  3. Mejorar mi organización: Me encantan las listas de tareas y los diferentes sistemas de organización, mi favorito sigue siendo GTD ya que me permite tenerlo todo en un único lugar, aunque en 2018 he vuelto a utilizar Bullet Journal para tomar notas en papel de reuniones, ideas, tareas que van surgiendo y otras. En este año quiero agregar el hábito de la revisión semanal que propone GTD para mantener tareas y proyectos al día.

  4. Desconectar activamente: Buscar o potenciar hobbies para mantener ocupado el cerebro cuando no estoy trabajando. Montar legos, tocar el piano, pintar, escribir, correr, o todas las anteriores.

  5. Agregar a mi rutina diaria más tiempo para leer: La combinación de Audible + Correr es increíblemente motivadora para ponerme al día con libros de acción como la saga de “The Gray Man” de Mark Greaney, aunque la literatura técnica, ya sea relacionada con el software, el trabajo corporativo o el mundo de los negocios, es más conveniente leerlas más que escucharlas. En un mundo donde hay cientos de artículos en medium de cualquier tema, sigo prefiriendo la estructura y el orden de un buen libro (en papel o en Kindle), por ello, me gustaría dedicar unos 15 minutos al día para leer. Habrá días que pueda dedicar más, habrá días que pueda dedicar menos. Además como motivación adicional, quiero escribir en el blog acerca de los libros “de trabajo” que lea.

  6. Buscar activamente nuevas oportunidades para aprender y mantener conocimiento: Inscribirme en un examen de certificación para buscar una excusa para estudiar, asistir a un evento de una tecnología que no conozca, hacer un pet-project que involucre algún concepto relacionado con IA, construir mejores interfaces aprendiendo de mis compañeros de UX, aprender a escribir documentos técnicos pidiendo ayuda a compañeros más experimentados…, hay muchas maneras de seguir aprendiendo, mantener nuestros conocimientos y mejorar en lo que hacemos.

  7. Respirar: Vivimos en un mundo frenético, con múltiples estímulos que vienen en forma de e-mail, mensajería instantánea, nuestro jefe, nuestros compañeros, la familia, amigos, y obligaciones que muchas veces requieren una respuesta inmediata. En mi caso he vivido más de una vez cómo no tomar una bocanada de aire y soltarlo antes de responder ha dado como resultado una respuesta tosca, agresiva, defensiva o simplemente equivocada por no pararme a pensar en la pregunta. Para ello este 2019 pienso respirar más, sobre todo antes de hablar.

2019 se presenta como un año cargado de retos personales, profesionales y deportivos. Espero poder compartir parte de lo aprendido en este blog que lleva siendo mi casa en las nubes desde hace ya 10 años.

Feliz año nuevo.