<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Javi Blog</title><link href="https://javiblog.com/" rel="alternate"/><link href="https://javiblog.com/feeds/all.atom.xml" rel="self"/><id>https://javiblog.com/</id><updated>2025-07-08T23:20:00+02:00</updated><entry><title>Mi historia: Cómo la RCP me dio una segunda oportunidad</title><link href="https://javiblog.com/2025/mi-historia-rcp-segunda-oportunidad.html" rel="alternate"/><published>2025-01-19T18:18:00+01:00</published><updated>2025-07-08T23:20:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2025-01-19:/2025/mi-historia-rcp-segunda-oportunidad.html</id><summary type="html">&lt;p&gt;En mayo de 2024 mi corazón se detuvo mientras salía un rato en bici 💔. No recuerdo ese momento, pero sé que gracias a una persona que inició una rápida reanimación cardiopulmonar pude salvar mi vida y recuperarme por completo.&lt;/p&gt;</summary><content type="html">&lt;p&gt;En mayo de 2024 mi corazón se detuvo mientras salía un rato en bici 💔. No recuerdo ese momento, pero sé que gracias a una persona que inició una rápida &lt;a href="https://es.wikipedia.org/wiki/Reanimaci%C3%B3n_cardiopulmonar"&gt;reanimación cardiopulmonar&lt;/a&gt; (RCP) pude salvar mi vida y recuperarme por completo.&lt;/p&gt;
&lt;p&gt;Desafortunadamente, las paradas cardíacas son más comunes de lo que pensamos y pueden ocurrirle a cualquiera de tu entorno. Y lo importante es actuar con rapidez y efectividad.&lt;/p&gt;
&lt;p&gt;La RCP es una técnica que puede marcar la diferencia entre la vida y la muerte. Cada minuto que pasa sin recibir RCP reduce las posibilidades de supervivencia y aumenta el riesgo de secuelas graves. En mi caso, gracias a esa rápida actuación, mis opciones para recuperarme aumentaron considerablemente.&lt;/p&gt;
&lt;p&gt;Ser testigo de una parada cardíaca puede ser una experiencia traumática, pero saber cómo actuar puede transformar una situación desesperada en una oportunidad para salvar una vida.&lt;/p&gt;
&lt;p&gt;Motivado por esta experiencia, decidí actualizar mis conocimientos en RCP y aprender a utilizar los desfibriladores externos automáticos que se encuentran en muchos lugares públicos. Considero que todos deberíamos estar preparados para ayudar a otros en una situación de emergencia.&lt;/p&gt;
&lt;p&gt;Espero no tener la mala suerte de encontrarme en esa situación, pero dado el caso estaré preparado.&lt;/p&gt;
&lt;h4&gt;APRENDE CÓMO HACER UNA RCP EFECTIVA Y EL USO DEL DESA&lt;/h4&gt;
&lt;p&gt;Sé que no es un tema del que se hable mucho, pero creo firmemente que la formación en RCP debería ser más accesible y ampliamente difundida. Al aprender esta técnica básica, no solo estás preparado para salvar la vida de alguien, sino que también te estás dando a ti mismo conocimientos para mayor tranquilidad de tu entorno cercano.&lt;/p&gt;
&lt;p&gt;El aparativo verde que econtramos ya en muchos sitios (DES o DESA) es realmente muy fácil de usar, nano es peligroso ni para el accidentado ni el que lo manipula, y es capaz de indicar paso a paso lo que debes hacer en todo momento.&lt;/p&gt;
&lt;p&gt;Si aún no has realizado un curso de RCP, te animo a que lo hagas. Encontrarás muchas opciones disponibles en línea y en centros de formación y asociaciones cercanos a ti. ¡Cada persona capacitada puede marcar la diferencia!&lt;/p&gt;
&lt;p&gt;Os comparto un vídeo donde otra persona explica su historia:&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/WBrGPc8JILw?si=a9kdJzKP4Xtd-SyF" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;div style="text-align:right;"&gt;
❤️
&lt;/div&gt;</content><category term="2025"/><category term="rcp"/><category term="formación"/><category term="corazón"/><category term="vida"/></entry><entry><title>Lecturas junio de 2023</title><link href="https://javiblog.com/lecturas/lecturas-2023-junio.html" rel="alternate"/><published>2023-06-25T00:00:00+02:00</published><updated>2023-06-25T00:00:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2023-06-25:/lecturas/lecturas-2023-junio.html</id><summary type="html">&lt;p&gt;Selección de algunos temas y libros interesantes leídos durante junio de 2023.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos temas y libros interesantes leídos durante este mes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Serving Files in Python: How FastAPI failed us!&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://medium.com/@alsadi/secret-sauce-is-zero-copy-single-context-switching-b749bd614dca" target="_blank"&gt;
https://medium.com/@alsadi/secret-sauce-is-zero-copy-single-context-switching-b749bd614dca
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;¡Nuestra materia no es cuántica!&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.astronoo.com/es/articulos/nuestra-materia-no-es-cuantica.html" target="_blank"&gt;
https://www.astronoo.com/es/articulos/nuestra-materia-no-es-cuantica.html
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;¿Gran Hermano o anarquía? El futuro que viene antes de que termine el siglo XXI&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.yorokobu.es/gran-hermano-o-anarquia/" target="_blank"&gt;
https://www.yorokobu.es/gran-hermano-o-anarquia/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Jugar con datos a tenis&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.titonet.com/estrategia-digital/jugar-con-datos-a-tenis.html" target="_blank"&gt;
https://www.titonet.com/estrategia-digital/jugar-con-datos-a-tenis.html
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;La sociedad datificada&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ethic.es/2022/11/la-sociedad-dataficada-big-data/" target="_blank"&gt;
https://ethic.es/2022/11/la-sociedad-dataficada-big-data/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;LIBRO: El project manager del futuro: Claves para una gestión eficaz y humana de proyectos IT&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.goodreads.com/book/show/158088164-el-project-manager-del-futuro" target="_blank"&gt;
https://www.goodreads.com/book/show/158088164-el-project-manager-del-futuro
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;LIBRO: Las ideas fundamentales del Universo: Espacio, tiempo y movimiento&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.goodreads.com/book/show/123514358-las-ideas-fundamentales-del-universo" target="_blank"&gt;
https://www.goodreads.com/book/show/123514358-las-ideas-fundamentales-del-universo
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="/category/lecturas.html"&gt;Lecturas pasadas&lt;/a&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="lecturas"/><category term="kafka"/><category term="python"/><category term="fastapi"/><category term="asyncio"/><category term="eficiencia"/><category term="cuántica"/><category term="datos"/><category term="descentralización"/><category term="web3"/><category term="anarquía"/><category term="física"/><category term="gestión de proyectos"/></entry><entry><title>Lecturas julio de 2021 - semana 25</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-26.html" rel="alternate"/><published>2021-07-05T00:00:00+02:00</published><updated>2021-07-05T00:00:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-07-05:/lecturas/lecturas-2021-semana-26.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;What Color is Your Function?&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/" target="_blank"&gt;
https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Swoole: Is it Node in PHP or am I wrong?&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://tsh.io/blog/swoole-is-it-node-in-php-or-am-i-wrong/" target="_blank"&gt;
https://tsh.io/blog/swoole-is-it-node-in-php-or-am-i-wrong/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A Look at the New PHP 8.1 Fibers Feature&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://betterprogramming.pub/a-look-at-the-new-php-8-1-fibers-feature-979489399918" target="_blank"&gt;
https://betterprogramming.pub/a-look-at-the-new-php-8-1-fibers-feature-979489399918
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fibers in PHP: A new opportunity for async PHP?&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://clue.engineering/2021/fibers-in-php" target="_blank"&gt;
https://clue.engineering/2021/fibers-in-php
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Continuation-passing style (CPS)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://es.wikipedia.org/wiki/Continuation-passing_style" target="_blank"&gt;
https://es.wikipedia.org/wiki/Continuation-passing_style
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Asynchronous PHP — Multiprocessing, Multithreading &amp;amp; Coroutines&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://divinglaravel.com/asynchronous-php" target="_blank"&gt;
https://divinglaravel.com/asynchronous-php
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-25.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2023-junio.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="php"/><category term="algoritmos"/><category term="programación"/><category term="asíncrona"/><category term="fibras"/><category term="hilos"/><category term="corrutinas"/></entry><entry><title>Lecturas junio de 2021 - semana 25</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-25.html" rel="alternate"/><published>2021-06-28T00:00:00+02:00</published><updated>2021-06-28T00:00:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-06-28:/lecturas/lecturas-2021-semana-25.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PHP Performance: Additional CPU cores vs Faster CPU cores&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://haydenjames.io/php-performance-additional-cpu-cores-vs-faster-cpu-cores/" target="_blank"&gt;
https://haydenjames.io/php-performance-additional-cpu-cores-vs-faster-cpu-cores/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Firefox 87 trims HTTP Referrers by default to protect user privacy&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://blog.mozilla.org/security/2021/03/22/firefox-87-trims-http-referrers-by-default-to-protect-user-privacy/" target="_blank"&gt;
https://blog.mozilla.org/security/2021/03/22/firefox-87-trims-http-referrers-by-default-to-protect-user-privacy/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-24.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-26.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="php"/><category term="eficiencia"/><category term="microprocesadores"/><category term="privacidad"/><category term="protocolos"/></entry><entry><title>Programación asíncrona, hilos y bloqueos</title><link href="https://javiblog.com/2021/programacion-asincrona-hilos-bloqueos.html" rel="alternate"/><published>2021-06-25T14:02:00+02:00</published><updated>2021-07-03T14:02:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-06-25:/2021/programacion-asincrona-hilos-bloqueos.html</id><summary type="html">&lt;p&gt;Quiero conocer mejor como funciona la asincronía internamente en los hilos, y principalmente con el reto más importante que resuelve, las operaciones de E/S (Entrada/Salida).&lt;/p&gt;</summary><content type="html">&lt;p&gt;Una de las grandes ventajas de la asincronía es poder aprovechar mucho más eficientemente los recursos de la CPU. Esto es así porque los algoritmos pueden ejecutarse de forma concurrente y coordinada en diferentes hilos, permitiendo que un proceso no tenga que bloquearse necesariamente esperando el resultado de una operación que ha delegado.&lt;/p&gt;
&lt;p&gt;Voy a centrarme en uno de los que más impacto tiene sobre el rendimiento, el bloqueo de hilos por operaciones de entrada y salida (E/S o I/O en inglés).&lt;/p&gt;
&lt;p&gt;Con el auge de los micro-servicios, el cloud y otros recursos vía internet, el reto ya no es el acceso a disco o a la base de datos en la red local, sino el acceso desde nuestras aplicaciones a todos esos recursos aún más lentos.&lt;/p&gt;
&lt;p&gt;En programación tradicional síncrona, cuándo el código llega a un punto en el debe realizar esta operación de E/S, el hilo que lo ejecuta se bloquea, esperando una respuesta o un timeout del recurso. Como comentaba en la &lt;a href="/2021/hilos-threads-concurrencia-programacion-asincrona.html"&gt;gestión de hilos&lt;/a&gt; esto es costoso de gestionar a nivel de kernel, ya que ha de desalojar el hilo de código y alojar el siguiente.  &lt;/p&gt;
&lt;p&gt;Con la programación asíncrona se nos abre nuevas posibilidades para aprovechar mejor los recursos como atender más peticiones, lanzar otras peticiones en paralelo, refrescar información en pantalla, etc.&lt;/p&gt;
&lt;h4&gt;One-thread-per-request (un hilo por petición)&lt;/h4&gt;
&lt;p&gt;Por ejemplo, en el desarrollo de un servicio que atienden a un número concurrente de clientes, la mayoría de los lenguajes suelen emplear este modelo para la gestión de recursos, donde lanzamos un nuevo hilo para cada petición a nuestra aplicación.&lt;/p&gt;
&lt;p&gt;Funciona bien cuando tenemos poca carga o esta es muy estable, pero su rendimiento cae rápidamente en entornos de mucha carga, por el exceso de trabajo de la gestión de hilos y el consumo de memoria que supone, ya que muchos de esos hilos se encuentran bloqueados.  &lt;/p&gt;
&lt;p&gt;Seguro que habéis visto alguna vez el error &lt;strong&gt;&lt;em&gt;503 Server busy&lt;/em&gt;&lt;/strong&gt;, y es que el servicio ya no puede atender más peticiones hasta que no se desatasque.&lt;/p&gt;
&lt;h2&gt;Dos modelos para la implementación de la asincronía&lt;/h2&gt;
&lt;p&gt;Vamos a ver dos modelos para implementar la programación asíncrona y que aprovecha las ventajas de los &lt;a href="/2021/hilos-threads-concurrencia-programacion-asincrona.html"&gt;lightweight threads&lt;/a&gt;, donde el intercambio de hilos es mucho más rápido y más liviano en el microprocesador.&lt;/p&gt;
&lt;p&gt;Estos modelos gestionan sus bloqueos dentro del espacio de usuario (user-level) antes que ocurran y sean llevados al kernel.&lt;/p&gt;
&lt;h4&gt;1. Thread based&lt;/h4&gt;
&lt;p&gt;También llamados &lt;em&gt;work-stealing&lt;/em&gt; permiten que los hilos puedan delegar las operaciones de E/S a un grupo de hilos especializados (&lt;em&gt;worker-threads&lt;/em&gt;), quienes completan la tarea de forma independiente. Al terminar suelen invocar a una función &lt;em&gt;callback&lt;/em&gt; establecida por el hilo invocador.  &lt;/p&gt;
&lt;p&gt;Cuando el hilo delega esa operación este puede continuar su ejecución &lt;strong&gt;de forma asíncrona&lt;/strong&gt; sin que el proceso se bloquee, permitiendo un control de cómo ha de comportarse después de la llamada hasta recibir la respuesta, como seguir haciendo más operaciones, atender nuevas peticiones o ceder el turno al siguiente hilo del proceso.&lt;/p&gt;
&lt;p&gt;Los hilos delegados que ejecutan las acciones de E/S terminan finalmente bloqueados, pero la diferencia es que el bloqueo solo se produce en ese grupo de hilos y no en los hilos solicitantes. El rendimiento del proceso aumenta de forma importante, pues es capaz de continuar su ejecución en lugar de estar detenido en espera de resultados.&lt;/p&gt;
&lt;p&gt;El reto lo tenemos ahora en cómo retornar el control al hilo invocador desde el hilo delegado. Hay varias respuestas posibles: el resultado esperado, un error desde la operación remota, o bien un &lt;em&gt;timeout&lt;/em&gt; porque que el recurso no ha respondido.&lt;/p&gt;
&lt;p&gt;El método habitual son las conocidas funciones de &lt;em&gt;callback&lt;/em&gt; donde el hilo finaliza devolviendo el control al primer hilo junto con un posible resultado como parámetro. Algunos lenguajes utilizan para construir este escenario implementaciones como &lt;em&gt;Promises&lt;/em&gt; o &lt;em&gt;Futures&lt;/em&gt;. También es posible registrar diferentes &lt;em&gt;callbacks&lt;/em&gt; en función de si es una respuesta correcta o un error, por ejemplo &lt;em&gt;onSuccess&lt;/em&gt; o &lt;em&gt;onError&lt;/em&gt;, etc.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Problemillas con este esquema&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Para este modelo suele planificarse una configuración previa de cómo inicializar el pool de worker-threads. En una carga estable y conocida es sencillo, pero para una carga indeterminada puede suponer o un desperdicio de recursos (si inicializamos de más) o problemas de recursos (si inicializamos de menos).&lt;/p&gt;
&lt;p&gt;Por otro lado, el bloqueo de hilos sigue produciéndose dentro del proceso, aunque sean en otro grupo de hilos, teniendo que gestionarse aún ese esquema de bloqueos BIO (&lt;em&gt;Blocked I/O&lt;/em&gt;) Para un gran volumen puede suponer un más que significativo uso de recursos.&lt;/p&gt;
&lt;p&gt;Por ejemplo, en los famosos comparadores de servicios, digamos seguros, cada petición lanza a su vez 20 peticiones a diferentes compañías externas para recoger información para comparar. Una petición lanzaría 21 hilos, 1000 peticiones en un intervalo de tiempo serían 21.000 hilos. Se puede ver aquí el drama de la gestión de esta cantidad de hilos, en muchos casos bloqueados esperando respuesta.&lt;/p&gt;
&lt;p&gt;Una forma de crecer en recursos es ampliar horizontalmente los servidores repartiendo esas 1.000 peticiones. Pero tenemos otra opción mucho más eficiente, NIO (&lt;em&gt;Non-blocking I/O&lt;/em&gt;), &lt;em&gt;Event based&lt;/em&gt;, o &lt;em&gt;Reactive programming&lt;/em&gt;.&lt;/p&gt;
&lt;div style="text-align:center"&gt;
&lt;img src="/images/2021/bio_nio.jpg" alt="I/O vs Non blocking I/O"&gt;
&lt;/div&gt;

&lt;p&gt;El objetivo con &lt;em&gt;non-blocking I/O&lt;/em&gt; es evitar el crecimiento de una gran cantidad de hilos bloqueados.  &lt;/p&gt;
&lt;h4&gt;2. Event based&lt;/h4&gt;
&lt;p&gt;En este modelo las operaciones de E/S se van a tratar como eventos dentro de la aplicación. La aplicación que necesita lanzar esta operación ya no necesitará crear un grupo de hilos separados para esto y su consiguiente gestión.&lt;/p&gt;
&lt;p&gt;El sistema operativo suele ofrecer servicios para que las aplicaciones deleguen de forma asíncrona sus operaciones de E/S. Por ejemplo, en el caso de derivados de unix y según la distribución tenemos por ejemplo &lt;em&gt;epoll&lt;/em&gt;. Estos toman la operación junto con un &lt;em&gt;callback&lt;/em&gt;, y cuando obtiene el resultado interrumpe al hilo invocador y este último recupera la respuesta para continuar.&lt;/p&gt;
&lt;div style="text-align:center"&gt;
&lt;img src="/images/2021/async_aio_diagram.png" alt="Modelo asíncrono de E/S"&gt;
&lt;/div&gt;

&lt;p&gt;El hilo que registra esta operación no se bloquea y puede continuar su proceso. El sistema operativo puede ser mucho más eficiente que si se implementa esto a nivel de aplicaciones. Las aplicaciones por tanto no desperdician recursos para lidiar con todo esto, y tienen así la posibilidad de trabajar con una mayor carga con un código mucho más simple.&lt;/p&gt;
&lt;p&gt;Nodejs utiliza este modelo basado en eventos en su implementación &lt;em&gt;event loop&lt;/em&gt;. Utiliza un hilo único para gestionar una cola de peticiones e internamente gestiona la E/S utilizando los servicios de epoll del kernel, aunque hay otros como kqueue.&lt;/p&gt;
&lt;p&gt;En esta ocasión no he querido profundizar mucho más en el artículo, porque para lo que buscaba conocer me pareció suficiente. Espero que sea útil. Y lo dicho, si hay errores o es confuso agradezco que me contactéis.&lt;/p&gt;</content><category term="2021"/><category term="desarrollo"/><category term="programación"/><category term="asíncrona"/><category term="eficiencia"/><category term="paradigmas"/><category term="hilos"/><category term="concurrencia"/><category term="paralelismo"/></entry><entry><title>Lecturas junio de 2021 - semana 24</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-24.html" rel="alternate"/><published>2021-06-21T00:00:00+02:00</published><updated>2021-06-21T00:00:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-06-21:/lecturas/lecturas-2021-semana-24.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Criptoeconomía: Bitcoin&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.sumapositiva.com/p/bitcoin" target="_blank"&gt; 
https://www.sumapositiva.com/p/bitcoin
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;La Era de los Datos (i): definiciones básicas&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.titonet.com/estrategia-digital/la-era-de-los-datos-i-definiciones-basicas.html" target="_blank"&gt; 
https://www.titonet.com/estrategia-digital/la-era-de-los-datos-i-definiciones-basicas.html
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-21.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-25.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="datos"/><category term="blockchain"/><category term="crypto"/><category term="bitcoin"/></entry><entry><title>Lecturas mayo de 2021 - semana 21</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-21.html" rel="alternate"/><published>2021-05-30T23:53:00+02:00</published><updated>2021-05-30T23:53:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-05-30:/lecturas/lecturas-2021-semana-21.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CHAR(1) to boolean transformation while migrating to PostgreSQL&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.migops.com/blog/2021/04/25/char1-to-boolean-datatype-transformation-while-migrating-to-postgresql" target="_blank"&gt; 
https://www.migops.com/blog/2021/04/25/char1-to-boolean-datatype-transformation-while-migrating-to-postgresql
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Le pire piège dans lequel tombent les développeurs&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.jesuisundev.com/piege-developpeurs/" target="_blank"&gt; 
https://www.jesuisundev.com/piege-developpeurs/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-18.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-24.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="postgresql"/><category term="programadores"/></entry><entry><title>Lecturas mayo de 2021 - semana 18</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-18.html" rel="alternate"/><published>2021-05-09T23:03:00+02:00</published><updated>2021-05-09T23:03:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-05-09:/lecturas/lecturas-2021-semana-18.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PostgreSQL at low level: stay curious!&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://erthalion.info/2019/12/06/postgresql-stay-curious/" target="_blank"&gt; 
https://erthalion.info/2019/12/06/postgresql-stay-curious/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Evolution of tree data structures for indexing: more exciting than it sounds&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://erthalion.info/2020/11/28/evolution-of-btree-index-am/" target="_blank"&gt; 
https://erthalion.info/2020/11/28/evolution-of-btree-index-am/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dijkstra: El programador humilde&lt;/strong&gt;&lt;br&gt;
&lt;a href="http://nummolt.blogspot.com/2019/08/el-programador-humilde.html" target="_blank"&gt; 
http://nummolt.blogspot.com/2019/08/el-programador-humilde.html
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-17.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-21.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="programación"/><category term="programadores"/><category term="postgresql"/><category term="data"/><category term="arquitectura"/></entry><entry><title>Programadores humildes, martillos, clavos y Dijkstra</title><link href="https://javiblog.com/2021/programadores-martillos-clavos-dijkstra.html" rel="alternate"/><published>2021-05-09T22:00:00+02:00</published><updated>2023-05-27T11:45:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-05-09:/2021/programadores-martillos-clavos-dijkstra.html</id><summary type="html">&lt;p&gt;Hoy he reservado tiempo para leer el discurso de Dijkstra "The humble programmer" (El programador humilde) de 1972. Hay un párrafo que me ha recordado aquello de que para un martillo todo son clavos o ¿cómo nuestras herramientas terminan moldeando nuestros desarrollos?&lt;/p&gt;</summary><content type="html">&lt;p&gt;Hoy he reservado tiempo para leer el discurso de Dijkstra: "The humble programmer" (El programador humilde). Quiero compartir esta breve reflexión porque hay un párrafo que me ha recordado aquello de que para un martillo todo son clavos o ¿cómo nuestras herramientas terminan moldeando nuestros desarrollos?&lt;/p&gt;
&lt;p&gt;¿Cuántas veces hemos llevado al límite nuestra recién aprendida herramienta &lt;em&gt;martillo.io&lt;/em&gt;? Encajando desarrollos que fácilmente podrían haberse llevado a cabo con técnicas y tecnologías más adecuadas. Podemos hablar incluso del uso de frameworks, arquitecturas y metodologías como martillos; también infraestructuras diseñadas con martillo, ..., y seguro que podemos hablar de más casos similares y en otras profesiones.&lt;/p&gt;
&lt;p&gt;Todo esto parte de uno de los argumentos de los seis que lista, para hacer notar que nuestro objetivo no es hacer programas sino construir soluciones que obtengan el comportamiento deseado. Este quinto argumento ha sido la base de esta breve reflexión.&lt;/p&gt;
&lt;p&gt;Quien tenga la curiosidad del texto completo al final encontrarás el enlace.&lt;/p&gt;
&lt;div style="text-align:center"&gt;
&lt;img src="/images/2021/edsger_dijkstra.jpg" alt="Fotografía de Edsger Dijkstra"&gt;
&lt;br&gt;&lt;small&gt;Edsger W. Dijkstra&lt;/small&gt;
&lt;/div&gt;

&lt;h3&gt;El programador humilde&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;(...)&lt;/p&gt;
&lt;p&gt;El quinto argumento tiene que ver con la influencia de la herramienta que estamos tratando de usar sobre nuestros propios hábitos de pensamiento. Observo una tradición cultural, que probablemente tiene sus raíces en el Renacimiento, de ignorar esta influencia, considerar la mente humana como el maestro supremo y autónomo de sus artefactos.&lt;/p&gt;
&lt;p&gt;Pero si empiezo a analizar los hábitos de pensamiento de mí mismo y de mis semejantes, llego, me guste o no, a una conclusión completamente diferente, a saber: Que las herramientas que estamos tratando de usar y el lenguaje o la notación que estamos usando para expresar o registrar nuestros pensamientos, ¡son los principales factores que determinan lo que podemos pensar o expresar!&lt;/p&gt;
&lt;p&gt;El análisis de la influencia que los lenguajes de programación tienen en los hábitos de pensamiento de sus usuarios, y el reconocimiento de que, por ahora, la capacidad intelectual es, con mucho, nuestro recurso más escaso, juntos nos dan una nueva colección de criterios para comparar los méritos relativos de los distintos lenguajes de programación. El programador competente es plenamente consciente del tamaño estrictamente limitado de su propio cráneo; por lo tanto, aborda la tarea de programación con total humildad y, entre otras cosas, huye de los trucos ingeniosos como de la peste.&lt;/p&gt;
&lt;p&gt;En el caso de un lenguaje de programación conversacional bien conocido, me han dicho desde varios lados que tan pronto como una comunidad de programación está equipada con un terminal para él, ocurre un fenómeno específico que incluso tiene un nombre bien establecido: se llama "las frases de una sola línea". Toma una de dos formas diferentes: un programador coloca un programa de una línea en el escritorio de otro y con orgullo dice lo que hace y agrega la pregunta "¿Puedes codificar esto con menos símbolos?", ¡Como si tuviera alguna relevancia conceptual! - o simplemente preguntar "¡Adivina qué hace!". De esta observación debemos concluir que este lenguaje como herramienta es una invitación abierta a trucos ingeniosos, y aunque exactamente esta pudiera ser la exposición pública de algunos de los recursos disponibles de aquellos a quienes les gusta mostrar cuán inteligentes son, lo siento, pero debo considerar esto como una de las cosas más condenatorias que se pueden decir sobre un lenguaje de programación.&lt;/p&gt;
&lt;p&gt;Otra lección que deberíamos haber aprendido del pasado reciente es que el desarrollo de lenguajes de programación “más ricos” o “más poderosos” fue un error en el sentido de que estas monstruosidades barrocas, estos conglomerados de idiosincrasias, son realmente inmanejables, tanto mecánica como mentalmente. Veo un gran futuro para lenguajes de programación muy sistemáticos y muy modestos. Cuando digo "modesto", quiero decir que, por ejemplo, no solo la "cláusula for" de ALGOL 60, sino incluso el "bucle DO" de FORTRAN podrían verse expulsados ​​por ser demasiado barrocos.&lt;/p&gt;
&lt;p&gt;He realizado un pequeño experimento de programación con voluntarios realmente experimentados, pero algo bastante inesperado apareció. Ninguno de mis voluntarios encontró la solución obvia y más elegante. Tras un análisis más detallado, esto resultó tener una fuente común: su noción de repetición estaba tan estrechamente relacionada con la idea de una variable controlada asociada que se fuera incrementando, que se bloquearon mentalmente sin poder ver lo obvio. Sus soluciones fueron menos eficientes, innecesariamente difíciles de entender, y les llevó mucho tiempo encontrarlas. Fue una experiencia reveladora pero también impactante para mí.&lt;/p&gt;
&lt;p&gt;Finalmente, en un aspecto, uno espera que los lenguajes de programación del mañana difieran mucho de lo que estamos acostumbrados hasta ahora: y en un grado mucho mayor que hasta ahora, deberían invitarnos a reflexionar en la estructura de lo que escribimos, en todas las abstracciones necesarias para enfrentar conceptualmente la complejidad de lo que estamos diseñando.&lt;/p&gt;
&lt;p&gt;Hasta aquí en cuanto a la mayor adecuación de nuestras herramientas futuras, ha sido la base del quinto argumento.&lt;/p&gt;
&lt;p&gt;Como comentario adicional, me gustaría insertar una advertencia para aquellos que identifican la dificultad de la tarea de programación con la lucha contra las deficiencias de nuestras herramientas actuales, porque podrían concluir que, una vez que nuestras herramientas sean mucho más adecuadas, la programación ya no ser un problema. La programación seguirá siendo muy difícil, porque una vez que nos hayamos liberado de la circunstancia engorrosa actual, nos encontraremos libres para abordar los problemas que ahora están más allá de nuestra capacidad de programación.&lt;/p&gt;
&lt;p&gt;(...)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Créditos&lt;/h3&gt;
&lt;p&gt;ACM Turing Lecture 1972&lt;br&gt;
(EWD340) The Humble Programmer by Edsger W. Dijkstra&lt;br&gt;
&lt;a href="https://www.cs.utexas.edu/~EWD/transcriptions/EWD03xx/EWD340.html"&gt;https://www.cs.utexas.edu/~EWD/transcriptions/EWD03xx/EWD340.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Fuente traducción: &lt;a href="http://nummolt.blogspot.com/2019/08/el-programador-humilde.html" target="_blank"&gt;http://nummolt.blogspot.com/2019/08/el-programador-humilde.html&lt;/a&gt;&lt;/p&gt;</content><category term="2021"/><category term="programación"/><category term="programadores"/></entry><entry><title>Lecturas abril de 2021 - semana 17</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-17.html" rel="alternate"/><published>2021-05-02T23:58:00+02:00</published><updated>2021-05-02T23:58:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-05-02:/lecturas/lecturas-2021-semana-17.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;What really happened at Basecamp&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.platformer.news/p/-what-really-happened-at-basecamp" target="_blank"&gt; 
https://www.platformer.news/p/-what-really-happened-at-basecamp
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Webflux: EventLoop vs Thread Per Request Model&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://dzone.com/articles/spring-webflux-eventloop-vs-thread-per-request-mod" target="_blank"&gt; 
https://dzone.com/articles/spring-webflux-eventloop-vs-thread-per-request-mod
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Practical SQL for Data Analysis: What you can do without Pandas&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://hakibenita.com/sql-for-data-analysis" target="_blank"&gt; 
https://hakibenita.com/sql-for-data-analysis
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-16.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-18.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="cultura"/><category term="equipos"/><category term="desarrollo"/><category term="pandas"/><category term="eficiencia"/><category term="sql"/><category term="data"/></entry><entry><title>Hilos, concurrencia y programación asíncrona</title><link href="https://javiblog.com/2021/hilos-threads-concurrencia-programacion-asincrona.html" rel="alternate"/><published>2021-04-25T19:27:00+02:00</published><updated>2021-07-03T13:05:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-04-25:/2021/hilos-threads-concurrencia-programacion-asincrona.html</id><summary type="html">&lt;p&gt;En mi “aproximación profunda” sobre la programación asíncrona, he querido estudiar la base de esa asincronía. Así que en última instancia me he visto envuelto en comprender el funcionamiento sobre la gestión de los hilos. Mi objetivo es poder explicar los conceptos que me he encontrado sobre los hilos y cómo funcionan.&lt;/p&gt;</summary><content type="html">&lt;p&gt;En mi “aproximación profunda” sobre la programación asíncrona, he querido estudiar la base de esa asincronía. Así que en última instancia me he visto envuelto en comprender el funcionamiento sobre la gestión de los hilos. Mi objetivo en este artículo es tratar de explicar algunos conceptos que me he encontrado sobre los hilos y cómo funcionan.&lt;/p&gt;
&lt;p&gt;Empiezo definiendo un hilo como &lt;strong&gt;una secuencia de código a ejecutar&lt;/strong&gt;. Cada hilo es seleccionado y llevado por turnos hacia el procesador iniciando así su ejecución. Esto se hace con un algoritmo planificador (scheduler) que será normalmente gestionado desde el sistema operativo (kernel).&lt;/p&gt;
&lt;p&gt;Voy a ver algunas diferencias de los planificadores sobre cuando es delegado al sistema operativo (kernel-level), o cuando el planificador es un servicio proporcionado por el lenguaje o una librería, y que se ejecuta a nivel de usuario (user-level).&lt;/p&gt;
&lt;p&gt;Pero un hilo también puede ser visto desde el punto de vista de un microprocesador, y como me fascina el funcionamiento de los micros he arañado un poco más para entrar a ver cómo es por dentro este asunto con el siguiente apartado.&lt;/p&gt;
&lt;h3&gt;El microprocesador y la concurrencia, y cómo es el multithreading&lt;/h3&gt;
&lt;p&gt;En un microprocesador también existe el concepto de &lt;strong&gt;hilos de ejecución&lt;/strong&gt;. El micro no conoce el todo de un programa, solo se limita a ejecutar secuencias de código con un contexto que se inicializa en sus registros, básicamente para el acceso a memoria y comienzo de la ejecución.&lt;/p&gt;
&lt;p&gt;Un micro con un núcleo sólo podrá ejecutar un único flujo de código (hilo), en cambio tenemos procesadores multi-núcleo pueden tener paralelismo real con varios flujos de código en ejecución (multi-hilo). Normalmente cada hilo tiene su propio direccionamiento, espacio de memoria, registros, etc., pero no siempre es así como veremos luego.&lt;/p&gt;
&lt;p&gt;El sistema operativo es quién se encarga de repartir esos flujos de ejecución en los núcleos disponibles, gestionando la concurrencia de los procesos en una cola vía prioridades, estados, etc.&lt;/p&gt;
&lt;p&gt;El &lt;strong&gt;multithreading&lt;/strong&gt; de una CPU (HyperThreading en Intel, SMT en AMD, etc.) permite que un mismo núcleo pueda ejecutar 2 hilos independientes, pero con la particularidad de que esos dos hilos deben pertenecer al mismo proceso. Esto es así porque ambos hilos deben compartir el mismo contexto de ejecución como la cache, el espacio direccionamiento virtual, etc., aunque no sus registros.&lt;/p&gt;
&lt;div style="text-align:center"&gt;
&lt;img src="/images/2021/multithreading.svg" style="width:60%" alt="Esquema microprocesador con multithreading"&gt;
&lt;/div&gt;

&lt;p&gt;Hasta aquí el fascinante mundo del microprocesador, pero luego veremos qué ventajas tiene eso de compartir el contexto entre hilos pertenecientes a un mismo proceso.&lt;/p&gt;
&lt;h3&gt;Procesos, hilos y fibras&lt;/h3&gt;
&lt;p&gt;En un ordenador pueden funcionar en paralelo muchos procesos correspondientes a unas cuantas aplicaciones y servicios del sistema operativo. Los procesos se pueden dividir en hilos de ejecución, un proceso con un único hilo es el caso más simple. La clave para la gestión de la concurrencia y la prioridad entre las aplicaciones estará en cómo y cuándo se hace el relevo entre los diferentes hilos en el procesador.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2021/process_threads.jpg" alt="Esquema sobre como entornos entre procesos e hilos"&gt;
&lt;/div&gt;

&lt;p&gt;Tenemos dos estrategias básicas para estos relevos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://es.wikipedia.org/wiki/Multitarea_apropiativa"&gt;Preemptive multitasking&lt;/a&gt;, normalmente gestionado por el sistema operativo (kernel-level) y que en un tiempo predefinido, interrumpe al hilo para poner el siguiente sin tener en cuenta lo que está ejecutándose en ese momento.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://es.wikipedia.org/wiki/Multitarea_cooperativa"&gt;Cooperative multitasking&lt;/a&gt;, el relevo lo lleva a cabo un planificador que está dentro del entorno de ejecución del propio proceso, vía librerías propias del lenguaje o facilitadas por el sistema operativo. Suele ser ejecutado a nivel de usuario (user-level), y donde se tiene la posibilidad de que un hilo pueda ceder su turno a otro hilo vía código. Las corrutinas son los casos más claros de esto último.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esta estrategia cooperativa es una de las bases de la programación asíncrona. Aquí somos nosotros los que podemos controlar la concurrencia entre los hilos, ya sea directamente con sentencias deliberadas de paso de turno, o indirectamente delegando la gestión de los turnos al compilador o intérprete, que conoce bien la estructura de la aplicación.&lt;/p&gt;
&lt;p&gt;La cooperación entre hilos nos permite optimizar mejor los recursos y prioridades, porque conocemos mejor que el sistema operativo cómo deben bloquearse y cuándo ceder el turno entre los hilos en ejecución.&lt;/p&gt;
&lt;h6&gt;Procesos (process)&lt;/h6&gt;
&lt;p&gt;Cuando lanzamos una aplicación, o un comando, o levantamos un servicio, a nivel del sistema operativo creamos un proceso (realmente a veces es un poco más complejo). El proceso se mantiene en ejecución hasta su finalización, pasando para el sistema operativo entre los estados de:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Listo para ejecución (otros procesos tienen la prioridad)&lt;/li&gt;
&lt;li&gt;Suspendido (por ejemplo esperando el final de una operación de E/S)&lt;/li&gt;
&lt;li&gt;En ejecución (le toca el turno de procesador)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Agrupa todo el código y los recursos necesarios como los apuntadores a ficheros, sockets, variables globales, espacio de memoria asignado, etc. Un proceso puede estar compuesto por varios hilos de ejecución concurrente, y muy importante, todos los hilos comparten el direccionamiento virtual y todos los recursos globales del proceso.&lt;/p&gt;
&lt;p&gt;A partir de aquí vamos a ver al proceso como secuencias de hilos que son gestionados por el planificador del sistema operativo, que dirige la ejecución concurrente intercambiando los hilos disponibles. El momento de cambio ocurre principalmente por que se bloquea el hilo esperando un recurso de E/S o bien se le acaba el tiempo asignado (preemptive multitasking), se sustituye por el siguiente de la cola.&lt;/p&gt;
&lt;p&gt;CEl desalojo de un proceso por otro es relativamente costoso porque supone guardar la tabla de direccionamiento (TLB), guardar el estado del proceso, su espacio de variables y recursos, invalidación de la cache del procesador, etc., y cargar todo lo anterior del siguiente proceso. Vamos, como desenchufar y recoger todo de la mesa porque viene otro a trabajar ahí.&lt;/p&gt;
&lt;p&gt;Un motivo por el cual un sistema puede degradarse de forma significativa es cuando muchos procesos se bloquean y son suspendidos debido al acceso a recursos (ficheros o recursos de red). Esto provoca que tengan que ser desalojados y posteriormente recuperados, teniendo que dedicar el procesador demasiado tiempo con los cambios de contexto.&lt;/p&gt;
&lt;p&gt;Una operación de cambio de un proceso puede llegar a consumir hasta &lt;a href="http://ithare.com/infographics-operation-costs-in-cpu-clock-cycles/"&gt;10&lt;sup&gt;6&lt;/sup&gt; ciclos de procesador&lt;/a&gt; y también supone un significativo gasto de memoria donde mantener todo el contexto de los procesos.&lt;/p&gt;
&lt;h6&gt;Hilos (threads)&lt;/h6&gt;
&lt;p&gt;Cuando un proceso se divide en diferentes hilos de código, todos se ejecutan de forma concurrente. Esta división tiene ventajas como que una operación bloqueante en uno de los hilos (como un acceso a un recurso) no tenga necesariamente que suspender el proceso completo.&lt;/p&gt;
&lt;p&gt;También son especialmente útiles cuando un servicio lanza hilos (estática o dinámicamente) para atender a muchos clientes de forma independiente y concurrente para cada hilo. Estos comparten el código, sus variables y recursos globales, aunque no directamente su información local.&lt;/p&gt;
&lt;p&gt;Otra ventaja de los hilos se da cuando el planificador desaloja un hilo por otro que también pertenece a un mismo proceso, es mucho menos costoso porque todos los hilos comparten toda la información del proceso, salvo la pila, registros y las variables locales del hilo si existieran. Un kernel moderno puede tener todo esto en cuenta y el cambio de contexto así es mucho más simple y rápido. En el ejemplo anterior de la mesa, me vale con llevarme mis cosas personales y dejar que el siguiente utilice el mismo ordenador, flexo, etc. pero abriendo su propia aplicación, el cambio es más rápido.&lt;/p&gt;
&lt;p&gt;Vamos a diferenciar los &lt;em&gt;kernel threads&lt;/em&gt;, &lt;em&gt;user threads&lt;/em&gt; y &lt;em&gt;fibers&lt;/em&gt; (fibras), estrategias para lidiar con la concurrencia y sobre todo con los costosos bloqueos de los hilos.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;kernel threads&lt;/strong&gt;&lt;br&gt;
El sistema operativo puede ofrecer un servicio nativo de gestión de hilos que se ejecuta a nivel del kernel. El proceso crea y delega la gestión de la ejecución de los hilos al kernel. El funcionamiento es el que ya hemos visto para procesos. El sistema operativo puede aprovechar la ventaja de conocer qué hilos pertenecen a un mismo proceso para intercambios más eficientes de hilos, y también la posibilidad de aprovechar el multithread si está disponible.&lt;/p&gt;
&lt;p&gt;Pero cuando el kernel interrumpe al hilo, no sabe en qué momento lo hace, se le acaba su tiempo y es desalojado. Por ejemplo cuando un hilo a punto de finalizar es desalojado y debe esperar a su próximo turno para terminar sus últimas instrucciones.&lt;/p&gt;
&lt;p&gt;Esto es importante tenerlo en cuenta para cuando veamos el siguiente tipo de planificación basado en &lt;em&gt;cooperative multitask&lt;/em&gt; y las ventajas que supone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;user threads&lt;/strong&gt;&lt;br&gt;
En estos casos no delegamos la gestión de los hilos directamente al sistema operativo, sino que disponemos de un planificador (&lt;a href="https://en.wikipedia.org/wiki/Runtime_library"&gt;runtime&lt;/a&gt;) en una capa por encima del kernel que decide que hilo del proceso dispone de acceso al procesador. Se denominan user threads porque ese planificador se ejecuta en el espacio de usuario (user-level).&lt;/p&gt;
&lt;p&gt;La concurrencia de los hilos se pueden implementar de muchas formas, e incluso de forma híbrida usando los propios recursos del sistema operativo. Por ejemplo tenemos el concepto de los &lt;a href="https://en.wikipedia.org/wiki/Green_threads"&gt;green threads o virtual threads&lt;/a&gt;, que no utiliza el sistema nativo del kernel para gestionar los hilos. En su lugar se utiliza un runtime o una máquina virtual del propio compilador / intérprete del lenguaje, tenemos por ejemplo la JVM de java.&lt;/p&gt;
&lt;p&gt;Con este tipo de planificador el intercambio de hilos puede ser ajustado al máximo en función de lo que deba conservar como contexto entre los hilos involucrados. No es lo mismo una función invariante, una corrutina, un generador, etc. Así se permite al planificador utilizar la máxima eficiencia para desalojar el hilo anterior y alojar el siguiente. Esto significa por ejemplo que quizás no deba guardar y recuperar todos los registros del procesador para ese cambio de hilo.&lt;/p&gt;
&lt;p&gt;Se suele utilizar la concurrencia cooperativa entre hilos, y es especialmente útil para la programación asíncrona. Piensa como los &lt;em&gt;async&lt;/em&gt;, &lt;em&gt;away&lt;/em&gt;, &lt;em&gt;yield&lt;/em&gt;, etc., hacen posible esa concurrencia cooperativa anticipando cuando un hilo se bloquea o pasa el turno de ejecución a otro hilo.&lt;/p&gt;
&lt;p&gt;Aún así las operaciones de E/S siguen suponiendo un reto, pero existen estrategias que permiten trasladar los bloqueos a otros hilos o procesos especializados a los que se delega esta ejecución, evitando el bloqueo del hilo principal que simplemente continua o es detenido de una forma más ordenada en favor de otros hilos. Podemos intuir aquí cómo pueden funcionar las &lt;em&gt;Promises&lt;/em&gt;, &lt;em&gt;Futures&lt;/em&gt;, ...&lt;/p&gt;
&lt;p&gt;Para el sistema operativo los user threads son un hilo más que está ejecutando, todo lo que hace el planificador del lenguaje dentro de ese hilo cambiando flujos de código es completamente transparente para el kernel. Los sistemas operativos más modernos incluso ofrecen recursos para hacer todo esto de forma híbrida entre planificador del runtime junto con el kernel para mejorar la eficiencia y la seguridad.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;fibers (fibras)&lt;/strong&gt;&lt;br&gt;
Dentro de los user threads y de la concurrencia cooperativa tenemos un tipo de hilos muy especializados donde suele emplearse el concepto de fibra (fiber). Son flujos de código que de forma cooperativa van pasándose el control entre ellos y el intercambio de hilos es notablemente más ligero a nivel de ciclos de procesador.&lt;/p&gt;
&lt;p&gt;Son gestionados íntegramente dentro del espacio del lenguaje, creando, inicializando y lanzando las fibras necesarias. Las fibras no son una subdivisión de los hilos, más bien podemos verlos como una especialización más eficiente de hilos que se crean y que cooperan entre ellos.&lt;/p&gt;
&lt;p&gt;Se asemejan mucho al concepto de corrutinas y son fragmentos de código que no suelen finalizar, se suspende y reanuda bajo demanda y puede ir acompañadas por una transmisión de datos, guardar estados previos o compartir datos entre ejecuciones.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2021/coroutine.jpg" alt="Esquema funcionamiento de llamadas a una corrutina con yield y resume"&gt;&lt;br&gt;
&lt;sub&gt;Fuente: http://www.cs.us.es/~fsancho/?e=234&lt;/sub&gt;
&lt;/div&gt;

&lt;p&gt;Con las fibras podemos ver claramente como funcionan a bajo nivel los generadores, iteradores, listas infinitas, etc.&lt;/p&gt;
&lt;hr&gt;

&lt;p&gt;Espero haber sido claro y preciso en las explicaciones. Pero si no ha sido así, por favor, no dudes en ponerte en contacto conmigo.&lt;/p&gt;</content><category term="2021"/><category term="desarrollo"/><category term="programación"/><category term="asíncrona"/><category term="arquitectura"/><category term="eficiencia"/><category term="paradigmas"/><category term="microprocesador"/><category term="hilos"/><category term="fibras"/><category term="paralelismo"/></entry><entry><title>Lecturas abril de 2021 - semana 16</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-16.html" rel="alternate"/><published>2021-04-25T13:03:00+02:00</published><updated>2021-04-25T13:03:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-04-25:/lecturas/lecturas-2021-semana-16.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Asynchronous Programming with Thread Pools&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://kislayverma.com/programming/asynchronous-programming-with-thread-pools-2/" target="_blank"&gt; 
https://kislayverma.com/programming/asynchronous-programming-with-thread-pools-2/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Event-Based Asynchronous Programming&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://kislayverma.com/programming/event-based-asynchronous-programming/" target="_blank"&gt; 
https://kislayverma.com/programming/event-based-asynchronous-programming/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;12 hábitos del pensador sistémico&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.polymatas.com/habitos-pensador-sistemico/" target="_blank"&gt; 
https://www.polymatas.com/habitos-pensador-sistemico/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-14.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-17.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="complejidad"/><category term="microservicios"/><category term="eficiencia"/><category term="desarrollo"/></entry><entry><title>Lecturas abril de 2021 - semana 14</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-14.html" rel="alternate"/><published>2021-04-11T23:53:00+02:00</published><updated>2021-04-11T23:53:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-04-11:/lecturas/lecturas-2021-semana-14.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;El arduo camino hacia el pensamiento complejo&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.polymatas.com/camino-pensamiento-complejo/" target="_blank"&gt; 
https://www.polymatas.com/camino-pensamiento-complejo/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Independence, autonomy, and too many small teams&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://kislayverma.com/organizations/independence-autonomy-and-too-many-small-teams/" target="_blank"&gt; 
https://kislayverma.com/organizations/independence-autonomy-and-too-many-small-teams/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Overcoming IO overhead in micro-services&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://kislayverma.com/programming/overcoming-io-overhead-in-micro-services/" target="_blank"&gt; 
https://kislayverma.com/programming/overcoming-io-overhead-in-micro-services/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-13.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-16.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="complejidad"/><category term="equipos"/><category term="microservicios"/><category term="eficiencia"/><category term="negocio"/><category term="desarrollo"/></entry><entry><title>Lecturas marzo de 2021 - semana 13</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-13.html" rel="alternate"/><published>2021-04-05T20:42:00+02:00</published><updated>2021-04-05T20:42:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-04-05:/lecturas/lecturas-2021-semana-13.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;La orquestación como una función estratégica clave en la empresa&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://singularsolving.com/orquestacion-estrategica/" target="_blank"&gt; 
https://singularsolving.com/orquestacion-estrategica/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Una introducción a los sistemas complejos&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.polymatas.com/introduccion-sistemas-complejos/" target="_blank"&gt; 
https://www.polymatas.com/introduccion-sistemas-complejos/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Feynman Learning Technique&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://fs.blog/2021/02/feynman-learning-technique/" target="_blank"&gt; 
https://fs.blog/2021/02/feynman-learning-technique/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Una internet más saludable es posible&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://2020.internethealthreport.org/es-sinopsis-del-informe/" target="_blank"&gt; 
https://2020.internethealthreport.org/es-sinopsis-del-informe/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-12.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-14.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="aprender"/><category term="equipos"/><category term="privacidad"/><category term="complejidad"/></entry><entry><title>Lecturas marzo de 2021 - semana 12</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-12.html" rel="alternate"/><published>2021-03-29T19:22:00+02:00</published><updated>2021-03-29T19:22:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-03-29:/lecturas/lecturas-2021-semana-12.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data at Basecamp with Jane Yang&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.speedwins.tech/posts/jane-yang-from-basecamp" target="_blank"&gt; 
https://www.speedwins.tech/posts/jane-yang-from-basecamp
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;C’est la faute du développeur&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.jesuisundev.com/la-faute-du-developpeur/" target="_blank"&gt; 
https://www.jesuisundev.com/la-faute-du-developpeur/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fastest Way to Load Data Into PostgreSQL Using Python&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://hakibenita.com/fast-load-data-python-postgresql" target="_blank"&gt; 
https://hakibenita.com/fast-load-data-python-postgresql
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Engineering for Performance: Ghost Queries&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://blog.appsignal.com/2021/03/23/engineering-for-performance-ghost-queries.html" target="_blank"&gt; 
https://blog.appsignal.com/2021/03/23/engineering-for-performance-ghost-queries.html
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-11.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-13.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="data"/><category term="desarrollo"/><category term="metodologías"/><category term="programadores"/><category term="csv"/><category term="postgresql"/><category term="python"/><category term="ingeniería"/><category term="rendimiento"/></entry><entry><title>Lecturas marzo de 2021 - semana 11</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-11.html" rel="alternate"/><published>2021-03-22T07:47:00+01:00</published><updated>2021-03-22T07:47:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-03-22:/lecturas/lecturas-2021-semana-11.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Por qué la sobrecarga cognitiva arruina tu aprendizaje&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.polymatas.com/la-sobrecarga-cognitiva-arruina-tu-aprendizaje/" target="_blank"&gt; 
https://www.polymatas.com/la-sobrecarga-cognitiva-arruina-tu-aprendizaje/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stop Obsessing Over Development Velocity, Focus on This Instead&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://itamargilad.com/velocity-vs-impact/" target="_blank"&gt; 
https://itamargilad.com/velocity-vs-impact/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wikipedia data engineering practices with Nuria Ruiz&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.speedwins.tech/posts/some-words-with-nuria-ruiz" target="_blank"&gt; 
https://www.speedwins.tech/posts/some-words-with-nuria-ruiz
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;El pensamiento de segundo orden es tan escaso como necesario&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.polymatas.com/pensamiento-segundo-orden/" target="_blank"&gt; 
https://www.polymatas.com/pensamiento-segundo-orden/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-10.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp; 
&lt;a href="/lecturas/lecturas-2021-semana-12.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="cognitivo"/><category term="metodologías"/><category term="productividad"/><category term="aprender"/><category term="arquitectura"/><category term="métricas"/><category term="data"/></entry><entry><title>Lecturas marzo de 2021 - semana 10</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-10.html" rel="alternate"/><published>2021-03-14T20:35:00+01:00</published><updated>2021-03-14T20:35:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-03-14:/lecturas/lecturas-2021-semana-10.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Why is MongoDB’s SSPL Bad For You?&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://www.percona.com/blog/2020/06/16/why-is-mongodbs-sspl-bad-for-you/" target="_blank"&gt;
https://www.percona.com/blog/2020/06/16/why-is-mongodbs-sspl-bad-for-you/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Why SSPL is Bad For You, Part 2 (+ elastic)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.percona.com/blog/2021/02/02/why-sspl-is-bad-for-you-part-2/" target="_blank"&gt; 
https://www.percona.com/blog/2021/02/02/why-sspl-is-bad-for-you-part-2/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Out of Control (paradigms, refactoring, control flow, data, code)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://kevlinhenney.medium.com/out-of-control-97ed6efa2818" target="_blank"&gt; 
https://kevlinhenney.medium.com/out-of-control-97ed6efa2818
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Large-scale filtering of data provides serendipitous surprises&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://queue.acm.org/detail.cfm?id=3446917" target="_blank"&gt; 
https://queue.acm.org/detail.cfm?id=3446917
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-2021-semana-7.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-11.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="mongodb"/><category term="elastic"/><category term="licencias"/><category term="open source"/><category term="code"/><category term="paradigmas"/><category term="data"/></entry><entry><title>Lecturas febrero de 2021 - semana 7</title><link href="https://javiblog.com/lecturas/lecturas-2021-semana-7.html" rel="alternate"/><published>2021-02-22T23:07:00+01:00</published><updated>2021-02-22T23:07:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-02-22:/lecturas/lecturas-2021-semana-7.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;When dev goes DevOps&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://www.jesuisundev.com/en/when-dev-goes-devops/" target="_blank"&gt;
https://www.jesuisundev.com/en/when-dev-goes-devops/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;L’incroyable ego des développeurs&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.jesuisundev.com/ego-des-developpeurs/" target="_blank"&gt; 
https://www.jesuisundev.com/ego-des-developpeurs/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Minimally Invasive (and More Accurate) Analytics: GoAccess and Athena/SQL&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://brandur.org/minimal-analytics" target="_blank"&gt; 
https://brandur.org/minimal-analytics
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Why did I create my own database?&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://tiagosilvapereira3.medium.com/why-did-i-create-my-own-database-85efbb2a8bc8" target="_blank"&gt; 
https://tiagosilvapereira3.medium.com/why-did-i-create-my-own-database-85efbb2a8bc8
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Idempotent Receiver&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://martinfowler.com/articles/patterns-of-distributed-systems/idempotent-receiver.html" target="_blank"&gt; 
https://martinfowler.com/articles/patterns-of-distributed-systems/idempotent-receiver.html
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Raft Consensus Algorithm&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://raft.github.io/" target="_blank"&gt; 
https://raft.github.io/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-febrero-2021-semana-6.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-10.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="desarrollo"/><category term="programadores"/><category term="devops"/><category term="data"/><category term="algoritmos"/></entry><entry><title>Lecturas febrero de 2021 - semana 6</title><link href="https://javiblog.com/lecturas/lecturas-febrero-2021-semana-6.html" rel="alternate"/><published>2021-02-14T18:47:00+01:00</published><updated>2021-02-14T18:47:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-02-14:/lecturas/lecturas-febrero-2021-semana-6.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Why I Built Litestream&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://litestream.io/blog/why-i-built-litestream/" target="_blank"&gt;
https://litestream.io/blog/why-i-built-litestream/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Managing developer identities in autonomous teams&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://kislayverma.com/organizations/managing-developer-identities-in-autonomous-teams/" target="_blank"&gt; 
https://kislayverma.com/organizations/managing-developer-identities-in-autonomous-teams/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-febrero-2021-semana-5.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-2021-semana-7.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="equipos"/><category term="desarrollo"/><category term="sqlite"/><category term="eficiencia"/></entry><entry><title>Lecturas febrero de 2021 - semana 5</title><link href="https://javiblog.com/lecturas/lecturas-febrero-2021-semana-5.html" rel="alternate"/><published>2021-02-09T13:47:00+01:00</published><updated>2021-02-09T13:47:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-02-09:/lecturas/lecturas-febrero-2021-semana-5.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Quality at Airbnb - Part 1&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://medium.com/airbnb-engineering/data-quality-at-airbnb-e582465f3ef7" target="_blank"&gt;
https://medium.com/airbnb-engineering/data-quality-at-airbnb-e582465f3ef7
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Quality at Airbnb - Part 2&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://medium.com/airbnb-engineering/data-quality-at-airbnb-870d03080469" target="_blank"&gt;
https://medium.com/airbnb-engineering/data-quality-at-airbnb-870d03080469
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;¿Qué son los “unit economics” en una startup y por qué son importantes?&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.kewlona.es/2021/01/unit-economics-en-una-startup/" target="_blank"&gt; 
https://www.kewlona.es/2021/01/unit-economics-en-una-startup/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-enero-2021-semana-4.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-febrero-2021-semana-6.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="data"/><category term="métricas"/><category term="negocio"/></entry><entry><title>Lecturas enero de 2021 - semana 4</title><link href="https://javiblog.com/lecturas/lecturas-enero-2021-semana-4.html" rel="alternate"/><published>2021-02-02T07:52:00+01:00</published><updated>2021-02-02T07:52:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-02-02:/lecturas/lecturas-enero-2021-semana-4.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;
&lt;p&gt;El orden no es importante.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Construcción de un datalake in house&lt;/strong&gt; &lt;br&gt;
&lt;a href="http://dondeestaavinashcuandoselenecesita.com/2021/01/como-construir-data-lake.html" target="_blank"&gt;
http://dondeestaavinashcuandoselenecesita.com/2021/01/como-construir-data-lake.html
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Charlando sobre slicing vertical&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://danilat.com/weblog/2021/01/27/product-slicing-lean-coffee" target="_blank"&gt;
https://danilat.com/weblog/2021/01/27/product-slicing-lean-coffee
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;4 Types of Comprehensions In Python&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://towardsdatascience.com/4-types-of-comprehensions-in-python-2fbeafdf2fda" target="_blank"&gt;
https://towardsdatascience.com/4-types-of-comprehensions-in-python-2fbeafdf2fda
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Python Lists vs Sets&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://towardsdatascience.com/python-lists-vs-sets-39bd6b5745e1" target="_blank"&gt; 
https://towardsdatascience.com/python-lists-vs-sets-39bd6b5745e1
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-enero-2021-semana-2.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-febrero-2021-semana-5.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="data"/><category term="producto"/><category term="agile"/><category term="python"/><category term="desarrollo"/></entry><entry><title>Lecturas enero de 2021 - semana 2</title><link href="https://javiblog.com/lecturas/lecturas-enero-2021-semana-2.html" rel="alternate"/><published>2021-01-18T21:12:00+01:00</published><updated>2021-01-18T21:12:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-01-18:/lecturas/lecturas-enero-2021-semana-2.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;
&lt;p&gt;El orden no es importante.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;How we processed 12 trillion rows during Black Friday&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://blog.tinybird.co/2020/12/21/how-we-setup-real-time-analytics-service-to-process-12-trillion-rows-during-black-friday/" target="_blank"&gt;
https://blog.tinybird.co/2020/12/21/how-we-setup-real-time-analytics-service-to-process-12-trillion-rows-during-black-friday/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Re-Introducing Hash Indexes in PostgreSQL&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://hakibenita.com/postgresql-hash-index" target="_blank"&gt;
https://hakibenita.com/postgresql-hash-index
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Some SQL Tricks of an Application DBA&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://hakibenita.com/sql-tricks-application-dba" target="_blank"&gt;
https://hakibenita.com/sql-tricks-application-dba
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Introducing Ray: a debugging tool for pragmatic developers&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://freek.dev/1868-introducing-ray-a-debugging-tool-for-pragmatic-developers" target="_blank"&gt;
https://freek.dev/1868-introducing-ray-a-debugging-tool-for-pragmatic-developers
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Microservices — architecture nihilism in minimalism's clothes&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://vlfig.me/posts/microservices" target="_blank"&gt; 
https://vlfig.me/posts/microservices
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-enero-2021-semana-1.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-enero-2021-semana-4.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="data"/><category term="analítica"/><category term="index"/><category term="postgresql"/><category term="sql"/><category term="debug"/><category term="microservicios"/><category term="arquitectura"/></entry><entry><title>Lecturas enero de 2021 - semana 1</title><link href="https://javiblog.com/lecturas/lecturas-enero-2021-semana-1.html" rel="alternate"/><published>2021-01-11T11:12:00+01:00</published><updated>2021-01-11T14:15:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-01-11:/lecturas/lecturas-enero-2021-semana-1.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;
&lt;p&gt;El orden no es importante.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Porqué gestionar es patear culos&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://lapastillaroja.net/2021/01/porque-gestionar-es-patear-culos/" target="_blank"&gt;
https://lapastillaroja.net/2021/01/porque-gestionar-es-patear-culos/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;La innovación cae en las manos equivocadas: no son los datos, son las personas&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://blogs.elconfidencial.com/tecnologia/tribuna/2021-01-01/digitalizacion-innovacion-kpmg-dee-hock-simon-sinek_2891776/" target="_blank"&gt;
https://blogs.elconfidencial.com/tecnologia/tribuna/2021-01-01/digitalizacion-innovacion-kpmg-dee-hock-simon-sinek_2891776/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;What I’ve Learned in 45 Years in the Software Industry&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.bti360.com/what-ive-learned-in-45-years-in-the-software-industry/" target="_blank"&gt;
https://www.bti360.com/what-ive-learned-in-45-years-in-the-software-industry/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;El role de un engineering manager: One on Ones&lt;/strong&gt;
&lt;br&gt;&lt;a href="https://medium.com/@flopezluis/el-role-del-engineering-manager-one-on-ones-eb23bc24686a" target="_blank"&gt;
https://medium.com/@flopezluis/el-role-del-engineering-manager-one-on-ones-eb23bc24686a
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;El role de un engineering manager: Gestionando el bajo rendimiento&lt;/strong&gt;
&lt;br&gt;&lt;a href="https://medium.com/@flopezluis/el-rol-del-engineering-manager-gestionando-el-bajo-rendimiento-cd3968dd69a5" target="_blank"&gt;
https://medium.com/@flopezluis/el-rol-del-engineering-manager-gestionando-el-bajo-rendimiento-cd3968dd69a5
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;El mayor cambio al convertirte en manager&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ivanmalagon.com/el-mayor-cambio-al-convertirte-en-manager" target="_blank"&gt; 
https://ivanmalagon.com/el-mayor-cambio-al-convertirte-en-manager
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-diciembre-2020-semana-53.html"&gt;&amp;lt;&amp;lt; Semana anterior&lt;/a&gt; &amp;nbsp;
&lt;a href="/lecturas/lecturas-enero-2021-semana-2.html"&gt;Semana siguiente &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="gestión"/><category term="data"/><category term="desarrollo"/><category term="negocio"/><category term="productividad"/></entry><entry><title>Lecturas diciembre de 2020 - semana 53</title><link href="https://javiblog.com/lecturas/lecturas-diciembre-2020-semana-53.html" rel="alternate"/><published>2021-01-04T11:44:00+01:00</published><updated>2021-01-04T11:44:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2021-01-04:/lecturas/lecturas-diciembre-2020-semana-53.html</id><summary type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada que comparto.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Selección de algunos artículos interesantes leídos durante la semana pasada.&lt;/p&gt;
&lt;p&gt;El orden no es importante.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PHP: Sunsetting Faker library&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://marmelab.com/blog/2020/10/21/sunsetting-faker.html" target="_blank"&gt;
https://marmelab.com/blog/2020/10/21/sunsetting-faker.html
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;What is Microsoft doing with Linux? Everything you need to know about its plans for open source&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.techrepublic.com/article/what-is-microsoft-doing-with-linux-everything-you-need-to-know-about-its-plans-for-open-source/" target="_blank"&gt;
https://www.techrepublic.com/article/what-is-microsoft-doing-with-linux-everything-you-need-to-know-about-its-plans-for-open-source/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;What Is Encryption at Rest, and Why Is It Important for Your Business?&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://brightlineit.com/encryption-at-rest-important-business/" target="_blank"&gt;
https://brightlineit.com/encryption-at-rest-important-business/
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Using JSONB in PostgreSQL: How to Effectively Store and Index JSON Data in PostgreSQL&lt;/strong&gt;
&lt;br&gt;&lt;a href="https://dzone.com/articles/using-jsonb-in-postgresql-how-to-effectively-store" target="_blank"&gt;
https://dzone.com/articles/using-jsonb-in-postgresql-how-to-effectively-store
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bye bye Mongo, Hello Postgres&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.theguardian.com/info/2018/nov/30/bye-bye-mongo-hello-postgres" target="_blank"&gt; 
https://www.theguardian.com/info/2018/nov/30/bye-bye-mongo-hello-postgres
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="/lecturas/lecturas-enero-2021-semana-1.html"&gt;Siguiente semana &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content><category term="lecturas"/><category term="testing"/><category term="microsoft"/><category term="linux"/><category term="data"/><category term="ramsonware"/><category term="negocio"/><category term="postgresql"/><category term="mongo"/><category term="json"/></entry><entry><title>Lectura del libro "The DevOps Handbook"</title><link href="https://javiblog.com/2020/libro-the-devops-handbook-introduccion.html" rel="alternate"/><published>2020-11-01T00:01:00+01:00</published><updated>2021-02-14T17:21:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2020-11-01:/2020/libro-the-devops-handbook-introduccion.html</id><summary type="html">&lt;p&gt;Después de la lectura de libro, considero que debería ser uno de los libros de cabecera de cualquiera que trabaje en el mundo del desarrollo de software, ya sea front, back, junior, senior, arquitecto o apagafuegos. Especialmente este último. Cualquier organización que le suene bien el término "value-driven" debería también tomar en cuenta los principios DevOps.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;The Devops Handbook (1/4)&lt;/h1&gt;
&lt;p&gt;Autores: Gene Kim, Jez Humble, Patrick Debois, &amp;amp; John Willis&lt;/p&gt;
&lt;p&gt;Estuve leyendo durante varias semanas el libro &lt;a href="https://itrevolution.com/book/the-devops-handbook/"&gt;The DevOps Handbook&lt;/a&gt;. Considero que debería ser uno de los libros de cabecera de cualquiera que trabaje en el mundo del desarrollo de software, ya sea front, back, junior, senior, arquitecto o apagafuegos. Especialmente este último. Cualquier organización IT que le suene bien el término "value-driven" debería tomar muy en cuenta los principios DevOps.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2020/devops_jandbook.jpg" alt="Portada del libro"&gt;
&lt;/div&gt;

&lt;p&gt;Como se define en la wikipedia, DevOps es un conjunto de prácticas que combina el desarrollo del software y a las operaciones de IT para su despliegue y puesta en marcha. El libro entra a fondo en los detalles fundacionales que trataré de explicar en siguientes posts.&lt;/p&gt;
&lt;p&gt;Para empezar, no es un perfil, ni es el nuevo título para un rol de operaciones, se trata de construir (de forma iterativa) una arquitectura de trabajo para que el desarrollo de software sea cada vez más ágil, fiable y seguro. Pasando del miedo a mover una especie de bomba en cada despliegue, a la seguridad de un entorno extremadamente robusto y amigable. Así como disponer de herramientas que facilitan el aprendizaje y la experimentación de todo lo que pasa en nuestro sistema.&lt;/p&gt;
&lt;p&gt;En resumen implementar un &lt;em&gt;pipeline&lt;/em&gt; de trabajo utilizando la automatización del trabajo repetitivo y eliminación de procesos que aportan muy poco, desde el desarrollo hasta producción, a través de testing continuo y monitorización. Participando en este &lt;em&gt;pipeline&lt;/em&gt; todos los actores implicados en el proceso.&lt;/p&gt;
&lt;p&gt;Una analogía que podemos ver en &lt;a href="https://www.youtube.com/watch?v=RRy_73ivcms" target="_blank"&gt;este vídeo de youtube&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;DevOps se ha basado en los &lt;a href="https://es.wikipedia.org/wiki/Lean_manufacturing"&gt;Principios Lean&lt;/a&gt;, la &lt;a href="https://es.wikipedia.org/wiki/Teor%C3%ADa_de_las_limitaciones"&gt;Teoría de las Limitaciones&lt;/a&gt;, el &lt;a href="https://es.wikipedia.org/wiki/Sistema_de_producci%C3%B3n_Toyota"&gt;Sistema de Producción de Toyota&lt;/a&gt;, entre otras fuentes relativas al aprendizaje, ingeniería de resiliencia, &lt;a href="https://bluered.es/blog/porque-google-esta-obsesionado-con-la-seguridad-psicologica-en-el-trabajo-y-como-favorecerla-en-tu-empresa"&gt;seguridad psicológica en el trabajo&lt;/a&gt;, etc.&lt;/p&gt;
&lt;p&gt;Una cadena de valor (término fundamental en DevOps) es sencillo de ver en los procesos una fábrica. En DevOps, una cadena de valor (tecnológica) consiste en convertir una hipótesis de negocio en un sistema tecnológico que entrega valor real al cliente de forma sistemática.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2020/devops_chain.png" alt="Esquema de la cadena de valor en DevOps"&gt;
&lt;br&gt;&lt;small&gt;Fuente: winwire.com&lt;/small&gt;
&lt;/div&gt;

&lt;p&gt;Existe en muchas empresas un enfrentamiento tradicional de objetivos entre Desarrollo que pretende entregar nuevo software (valor), y Operaciones que quiere tener los entornos lo más estables y seguros posible (mantener). Existe así una frontera de facto entre lo que ocurre en desarrollo y lo que ocurre en producción, donde ni unos ni otros disponen de la visión completa de ese valor que se pretende entregar. Sin un buen alineamiento de incentivos y metas, &lt;em&gt;cada equipo se centrará en sus propias metas&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;Objetivo&lt;/h4&gt;
&lt;p&gt;El objetivo principal es reducir el tiempo de entrega de valor desde que se decide hasta que ya está a disposición del cliente, también llamado “lead time”. Esto se consigue orquestando un flujo del trabajo de desarrollo eficiente y muy automatizado, con una información inmediata de lo que está ocurriendo con nuestro código y disponiendo de un entorno robusto donde poder extraer fácilmente información y resultados de experimentación, aprendiendo así con los mínimos riesgos posibles.&lt;/p&gt;
&lt;p&gt;La meta es conseguir un flujo altamente eficiente para el desarrollo: testing, despliegue y feedback inmediato del nuevo despliegue, permitiendo corregir o mejorar gracias al nuevo conocimiento adquirido de la observación en producción. Entendible rápidamente gracias a que el &lt;em&gt;lead time&lt;/em&gt; es a corto plazo y no de meses o años. Un código escrito hace meses y que se despliega hoy es mucho más difícil de corregir las intenciones que uno reciente.&lt;/p&gt;
&lt;p&gt;Una compañía con una implementación DevOps fuerte tendrá un equipo técnico de alto rendimiento, más satisfechos con su trabajo, con menos miedos ya que el entorno es más robusto y es más fácil de detectar problemas, y será rápido de arreglar en caso de que las cosas no vayan del todo bien. Los costes de los errores son mucho más asumibles gracias a una alta velocidad de resolución y un entorno más amigable para recolectar información y aprendizajes.&lt;/p&gt;
&lt;h4&gt;Estructura del libro&lt;/h4&gt;
&lt;p&gt;El libro se divide en 3 caminos (the three ways) que hay que recorrer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/2020/devops-principio-de-flow.html"&gt;Primer camino: &lt;strong&gt;Principio de Flow&lt;/strong&gt;&lt;/a&gt;
  &lt;br&gt;Acelerar la entrega de valor al cliente.&lt;/li&gt;
&lt;li&gt;&lt;a href="/2020/devops-principio-de-feedback.html"&gt;Segundo camino: &lt;strong&gt;Principio de Feedback&lt;/strong&gt;&lt;/a&gt;
  &lt;br&gt;Nos permite crear sistemas de trabajo cada vez más seguros.&lt;/li&gt;
&lt;li&gt;&lt;a href="/2020/devops-principio-de-continual-learning.html"&gt;Tercer camino: &lt;strong&gt;Principio de Aprendizaje Continuo y Experimentación&lt;/strong&gt;&lt;/a&gt;
  &lt;br&gt;Fomentar una cultura de alta confianza y un enfoque científico para la mejora de los procesos.&lt;/li&gt;
&lt;/ul&gt;</content><category term="2020"/><category term="desarrollo"/><category term="devops"/><category term="metodologías"/><category term="cultura"/><category term="equipos"/><category term="libros"/></entry><entry><title>The DevOps Handbook: Principio de Continual Learning</title><link href="https://javiblog.com/2020/devops-principio-de-continual-learning.html" rel="alternate"/><published>2020-10-25T09:29:00+01:00</published><updated>2020-10-25T09:29:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2020-10-25:/2020/devops-principio-de-continual-learning.html</id><summary type="html">&lt;p&gt;Las organizaciones deben propiciar un entorno seguro a sus trabajadores donde experimentar, extraer aprendizajes y compartirlos. Solo así podemos mejorar de forma continuada nuestro flujo de trabajo.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;The DevOps Handbook: Principio de Aprendizaje continuo y Experimentación (4/4)&lt;/h1&gt;
&lt;p&gt;Última parte del libro &lt;a href="/2020/libro-the-devops-handbook-introduccion.html"&gt;The DevOps Handbook&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El último principio nos indica el camino para mejorar como desarrolladores y como equipos mediante la creación de una cultura que lo propicie. Estructuras extremadamente rígidas y caminos muy marcados pueden impedir descubrir nuevo conocimiento y mejoras. Una cultura del miedo basada en temer castigos o reprimendas públicas incide directamente en la &lt;a href="https://bluered.es/blog/porque-google-esta-obsesionado-con-la-seguridad-psicologica-en-el-trabajo-y-como-favorecerla-en-tu-empresa"&gt;seguridad psicológica&lt;/a&gt; del equipo, pues paraliza la experimentación o encontrar otras maneras de hacer las cosas.&lt;/p&gt;
&lt;p&gt;Por el contrario en equipos de alto rendimiento, con altas dosis de libertad y seguridad para la búsqueda de otros enfoques, les permiten encontrar nuevos caminos que nos llevan a mejorar los resultados de nuestra cadena de valor. Los errores deben ser vistos como una inversión controlada, destinos intermedios para alcanzar la excelencia individual y de equipo.&lt;/p&gt;
&lt;p&gt;Nuestro entorno de trabajo debe estar diseñado de forma que los errores sean fácilmente asumidos y corregidos en nuestro flujo (Flow), rápidamente detectado y entendida su naturaleza (Feedback) y extracción de aprendizaje del &lt;em&gt;accidente&lt;/em&gt; (Continual Learning and Experimentation)
Lo contrario impide salirse de los caminos marcados porque quizá los errores son costosos de solucionar en nuestro flujo de trabajo (no Flow), difícil de detectar y comprender las implicaciones del error (no Feedback) y evitar todo lo posible aventurarse a terrenos fuera del camino (no Learning &amp;amp; Experimentation)&lt;/p&gt;
&lt;p&gt;El camino del Aprendizaje y Experimentación no es gratuito, debemos reservar tiempo para ello. Debe ser una actividad definida y planificada donde el aprendizaje del resultado (positivo o negativo), sea un aprendizaje no solo individual si no que se transmita a toda la organización, permitiendo nuevos avances gracias al conocimiento extraído.&lt;/p&gt;
&lt;p&gt;En entornos estables es incluso muy útil provocar errores o problemas ficticios para entender como se comporta nuestro sistema y nuestra organización, probando cómo reaccionamos y posteriormente qué debemos cambiar para incrementar nuestra resiliencia.&lt;/p&gt;
&lt;h4&gt;Entorno de seguridad psicológica y abierto al aprendizaje&lt;/h4&gt;
&lt;p&gt;Un entorno poco seguro en una empresa de tecnología es devastador dada la naturaleza de entornos complejos que suelen llevar entre manos. En organizaciones poco propicias a una cultura de seguridad suelen esconderse los problemas y huir hacia delante, hasta que la situación se vuelve insostenible haciendo mucho más costosas y dramáticas las soluciones de los problemas y futuros cambios (deuda técnica).&lt;/p&gt;
&lt;p&gt;Ron Westrum categoriza tres tipo de organizaciones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Organizaciones patológicas&lt;/strong&gt;: Altas dosis de miedo y amenazas. La información no se comprarte y se esconden los problemas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Organizaciones burocráticas&lt;/strong&gt;: Muchas reglas y procesos, a menudo internos por departamentos o equipos. Los fallos son achacados a incumplimientos de dichas reglas o procesos que no animan a salir del camino.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Organizaciones generadoras&lt;/strong&gt;: Organizaciones que activamente buscan nuevos caminos y formas de hacer las cosas, compartiendo los aprendizajes y responsabilidades de los errores y aciertos.&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Patológicas&lt;/th&gt;
&lt;th&gt;Burocráticas&lt;/th&gt;
&lt;th&gt;Generadoras&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Orientada al poder&lt;/td&gt;
&lt;td&gt;Orientada a las reglas&lt;/td&gt;
&lt;td&gt;Orientada a resultados&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Información escondida&lt;/td&gt;
&lt;td&gt;Información ignorada&lt;/td&gt;
&lt;td&gt;Información buscada&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Baja cooperación&lt;/td&gt;
&lt;td&gt;Moderada cooperación&lt;/td&gt;
&lt;td&gt;Alta cooperación&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Responsabilidades eludidas&lt;/td&gt;
&lt;td&gt;Responsabilidades compartimentadas&lt;/td&gt;
&lt;td&gt;Riesgos y responsabilidades compartidos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mensajeros despreciados&lt;/td&gt;
&lt;td&gt;Mensajeros rechazados&lt;/td&gt;
&lt;td&gt;Mensajeros entrenados&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desalentando puentes entre equipos&lt;/td&gt;
&lt;td&gt;Tolerado puentes entre equipos&lt;/td&gt;
&lt;td&gt;Alentando puentes entre equipos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Culpabilización de los errores&lt;/td&gt;
&lt;td&gt;Judicialización de los errores&lt;/td&gt;
&lt;td&gt;Investigación de errores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Novedad arruinada&lt;/td&gt;
&lt;td&gt;Novedad que lleva a problemas&lt;/td&gt;
&lt;td&gt;Novedad implementada&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4&gt;Reservar tiempo para la mejora del trabajo diario&lt;/h4&gt;
&lt;p&gt;Si no tenemos espacio para mejorar nuestro trabajo y procesos, no será posible progresar y evitar errores. Incluso puede ir degradándose con el tiempo. Mike Orzen, autor de &lt;a href="https://mikeorzen.com/lean-it/"&gt;&lt;strong&gt;Lean IT&lt;/strong&gt;&lt;/a&gt; dice que "&lt;em&gt;Incluso más importante que nuestro trabajo diario es la mejora de nuestro trabajo diario&lt;/em&gt;".&lt;/p&gt;
&lt;p&gt;No disponer de tiempo para &lt;em&gt;pagar&lt;/em&gt; nuestras deudas técnicas ni tiempo para probar alternativas, pone en peligro y empobrece respectivamente nuestro trabajo diario.&lt;/p&gt;
&lt;h4&gt;Transformar descubrimientos locales en mejoras globales&lt;/h4&gt;
&lt;p&gt;Cuando nuevos aprendizajes emergen en nuestro trabajo deben existir mecanismos y espacios que permitan que el nuevo conocimiento adquirido fluya a todo el equipo y a la organización.&lt;/p&gt;
&lt;p&gt;Ejemplos: fomentar los post-mortem después de un problema importante encontrado, o incentivar la experimentación y compartir públicamente los resultados con la organización.&lt;/p&gt;
&lt;p&gt;Uno de los mecanismos es disponer de repositorios accesibles en la organización donde encontrar toda la información de los post-mortem, experimentos, código, librerías compartidas, etc. Incluso totalmente públicas.&lt;/p&gt;
&lt;h4&gt;Líderes que refuerzan la cultura del aprendizaje y experimentación&lt;/h4&gt;
&lt;p&gt;Los líderes deben allanar el camino para que el equipo pueda mejorar su trabajo diario, facilitando un entorno que permita todo lo comentado anteriormente. Deben permitir que los cambios ocurran, en pequeños incrementos y siempre con la complicidad del equipo y la organización.&lt;/p&gt;
&lt;p&gt;Otro de sus papeles como líderes es ayudar a los compañeros estilo &lt;em&gt;coaching&lt;/em&gt; mediante la tutorización de los experimentos, hipótesis, alternativas, etc. No tanto para evitar errores sino para incentivar ofreciendo seguridad arropando el emprendimiento del experimento, y ayudar a elegir las batallas correctas.&lt;/p&gt;</content><category term="2020"/><category term="desarrollo"/><category term="devops"/><category term="metodologías"/><category term="cultura"/><category term="equipos"/><category term="libros"/></entry><entry><title>The DevOps Handbook: Principio de Feedback</title><link href="https://javiblog.com/2020/devops-principio-de-feedback.html" rel="alternate"/><published>2020-10-17T20:53:00+02:00</published><updated>2021-02-11T21:53:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2020-10-17:/2020/devops-principio-de-feedback.html</id><summary type="html">&lt;p&gt;Este principio nos habla de la necesidad de tener un buen sistema de información y herramientas que nos den &lt;em&gt;feedback&lt;/em&gt; inmediato de todo lo que está ocurriendo en nuestro flujo de trabajo y en nuestro sistema (PARTE 3).&lt;/p&gt;</summary><content type="html">&lt;h1&gt;The DevOps Handbook: Principio de Feedback (3/4)&lt;/h1&gt;
&lt;p&gt;Tercera parte del libro &lt;a href="/2020/libro-the-devops-handbook-introduccion.html"&gt;The DevOps Handbook&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Este principio nos habla de la necesidad de tener un buen sistema de información y herramientas que nos den &lt;em&gt;feedback&lt;/em&gt; inmediato de todo lo que está ocurriendo en nuestra &lt;a href="/2020/devops-principio-de-flow.html"&gt;cadena de valor&lt;/a&gt; y nuestro sistema. Con estos datos podremos reaccionar rápido y mitigar las posibles consecuencias de un error durante nuestro trabajo. También la oportunidad de aprender cómo se desenvuelve nuestro sistema y evitar cometer los mismos errores.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2020/devops_lifecycle.png" alt="Esquema DevOps feedback"&gt;
&lt;/div&gt;

&lt;p&gt;Esta información debe obtenerse fácilmente, ser rápida, precisa y frecuente para no llegar demasiado tarde o darnos pereza en la búsqueda. Idealmente nuestro cliente ni debe enterarse de nuestros problemas con el despliegue de una nueva funcionalidad. El peor escenario es que tenga que ser él quien nos alerte de que nuestra cosa no funciona, con las consecuencias que eso conlleva.&lt;/p&gt;
&lt;p&gt;Si detectamos en fases tempranas el problema, más sencillo y barato será arreglarlo. Cuanta más granularidad y relación tengamos entre toda la información recopilada, más directa, rápida y precisa será la solución que haya que aplicar, y menores las consecuencias del error que haya que reparar.&lt;/p&gt;
&lt;p&gt;El feedback no solo es a nivel de errores técnicos o de diseño, sino también información de cómo está funcionando nuestro flujo de trabajo. Una información clave por ejemplo es detectar un cuello de botella o fallos en un punto concreto, si no se resuelve rápidamente hará que toda la cadena se resienta. Y cuanto más tardemos más complicado será solucionarlo pues habrá ido avanzando por todo el flujo.&lt;/p&gt;
&lt;h4&gt;Trabajar con seguridad en sistemas complejos&lt;/h4&gt;
&lt;p&gt;Una de las características típicas de los sistemas con los que trabajamos es que suelen ser complejos. Con tantos componentes y todos los posibles caminos que pueden tomar, los fallos se vuelven inevitables por dicha complejidad. Es difícil para alguien conocer el detalle suficiente para poder prever todos los posibles puntos de fallo. Esto hace que los errores sean desgraciadamente habituales, especialmente en el momento de los cambios.&lt;/p&gt;
&lt;p&gt;Un buen diseño de una telemetría de las aplicaciones y de los sistemas es fundamental, si nos permite alertas tempranas de los problemas hará que podamos trabajar con mucha mayor confianza y seguridad.&lt;/p&gt;
&lt;h4&gt;Ver los problemas a medida que ocurren&lt;/h4&gt;
&lt;p&gt;Tenemos que poder validar nuestras decisiones de implementación o diseño lo más pronto posible. Esto solo ocurre si disponemos de ese &lt;em&gt;feedback&lt;/em&gt; inmediato y automatizado del sistema. Debemos construir un flujo bidireccional entre nuestro trabajo y la información obtenida al integrarlo, actuando con la nueva información en mejorar de iterativamente el trabajo hasta obtener el resultado esperado.&lt;/p&gt;
&lt;p&gt;En contraposición tenemos el &lt;em&gt;waterfall&lt;/em&gt; en el cual después de muchas semanas o meses de trabajo, en la primera integración los problemas son más difíciles de abordar por su tamaño y por el tiempo que hace que se decidieron e implementaron las cosas, haciendo todo mucho más costoso.&lt;/p&gt;
&lt;p&gt;Es también importante tener una alta calidad en la información obtenida en todas las fases de nuestro flujo de trabajo, los defectos y desviaciones del objetivo se encuentran así fácil y rápidamente. Solo con información completa y fiable podremos realmente aprender y conseguir mejorar nuestro trabajo.&lt;/p&gt;
&lt;h4&gt;Parada de emergencia&lt;/h4&gt;
&lt;p&gt;Cuando algo va mal y aparecen errores o problemas importantes en nuestro &lt;em&gt;value stream&lt;/em&gt;, debemos parar y ponernos todos a investigar las causas y aplicar las mejoras necesarias para solventarlo. Esto permite un aprendizaje global inmediato del problema, sus implicaciones y posibles relaciones con otros procesos, y lo que es fundamental es que se aborda en sus fases más tempranas y el problema no va avanzando por la cadena.&lt;/p&gt;
&lt;p&gt;Es un error, por ejemplo, aparcar una solución (deuda técnica) hasta un momento en el que ya es más complicado solucionar, donde se han integrado encima más cosas y donde el tiempo ha hecho mella en nuestro entendimiento del problema. Si lo dejamos pasar solo conseguiremos tener más adelante nuevas tareas y más complicadas.&lt;/p&gt;
&lt;p&gt;Un ejemplo podemos verlo con la integración continua cuando rompemos los tests, si la solución no es obvia todo el equipo debe ponerse a trabajar codo con codo con el responsable de la rotura para solucionar el problema, permitiendo que emerja un nuevo aprendizaje, sobre todo para el responsable del error. Una parada necesaria de la cadena de trabajo para que luego todo vuelva a continuar con el ritmo esperado.&lt;/p&gt;
&lt;p&gt;Aunque parezca poco intuitivo, detectar problemas importantes en fases tempranas y parar la maquinaria para resolver problemas es la manera más efectiva y barata de que los errores no vayan creciendo de manera incontrolada y oscura, así como una buena oportunidad para aprender cómo funciona realmente nuestro sistema.&lt;/p&gt;
&lt;h4&gt;Trabajar la calidad en la misma fuente&lt;/h4&gt;
&lt;p&gt;De poco sirve que solo un equipo de calidad revise nuestro trabajo semanas después, a la vuelta posiblemente hayamos olvidado información importante que nos permita entender el porqué se tomaron dichas decisiones. En su lugar debemos proporcionar todas las herramientas necesarias para comprobar la calidad del trabajo en el mismo sitio donde se produce.&lt;/p&gt;
&lt;p&gt;Por ejemplo con tests automáticos profundos y feedaback inmediato de las pruebas que revisan que el nuevo código es correcto, se integra correctamente, es eficiente y no tiene problemas de seguridad. Con esta información el programador tiene la certeza de que su cambio no tiene implicaciones negativas, y si las tiene entonces consigue nuevo conocimiento del por qué para futuras decisiones. La inmediatez del feedback permite que los cambios que deba hacer sean minutos después, no dentro de varios días o semanas.&lt;/p&gt;
&lt;p&gt;De poco sirve acabar una tarea sin tener completa certeza de que funcionará correctamente en un sistema más grande. Solo podríamos asegurar con tests unitarios y parciales que la nueva funcionalidad cumple con la salida esperada, pero poco más. También tiene poca utilidad preparar un elaborado informe de pruebas o documentación de implementación que otro equipo leerá tiempo después ya desfasado, y que posiblemente no haya tenido en cuenta otras funcionalidades adicionales que desconoce.&lt;/p&gt;
&lt;p&gt;Es muy importante que el equipo conozca la motivación de una funcionalidad y no solo un resultado esperado, así el trabajo será mucho más certero y menos idas y vueltas tendrá la integración de los componentes, mejores pruebas de la funcionalidad por parte del desarrollador o integrador, y no meras pruebas del código. Soluciones hay muchas pero correctas para el negocio serán menos.&lt;/p&gt;</content><category term="2020"/><category term="desarrollo"/><category term="devops"/><category term="metodologías"/><category term="cultura"/><category term="equipos"/><category term="libros"/></entry><entry><title>Posibilidades de la función COUNT de SQL</title><link href="https://javiblog.com/2020/posibilidades-funcion-count-sql.html" rel="alternate"/><published>2020-10-17T10:32:00+02:00</published><updated>2021-01-05T12:04:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2020-10-17:/2020/posibilidades-funcion-count-sql.html</id><summary type="html">&lt;p&gt;El uso más típico de la función de agregación COUNT es count(*) donde ponemos en las condiciones del WHERE qué es lo que queremos contar. Pero la sintaxis permite hacer mucho más y suele ser más eficiente que traer todos los datos y hacerlo desde nuestro propio código.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Cosas que se pueden hacer con la función SQL COUNT()&lt;/h1&gt;
&lt;p&gt;El uso más típico de la función de agregación COUNT es &lt;code&gt;count(*)&lt;/code&gt; donde ponemos en las condiciones del &lt;em&gt;WHERE&lt;/em&gt; qué es lo que queremos contar y listo. Pero la sintaxis de &lt;em&gt;COUNT&lt;/em&gt; y &lt;em&gt;SQL&lt;/em&gt; permiten hacer muchas más cosas y además suele ser más eficiente que traer todos los datos y hacerlo desde nuestro propio código.&lt;/p&gt;
&lt;p&gt;La sintaxis de los ejemplos mostrados aquí es para MySQL pero es similar con PostgreSQL, Oracle, MSQL, etc.&lt;/p&gt;
&lt;h5&gt;Contar todas filas de una query&lt;/h5&gt;
&lt;p&gt;Esta es la más común, contar las filas devueltas por una sentencia SQL:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h5&gt;Agrupando por una o varias columnas&lt;/h5&gt;
&lt;p&gt;También bastante común agrupar por columnas y devolver la cuenta de cada una:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;GROUP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Agrupa cada uno de los valores distintos de &lt;em&gt;price&lt;/em&gt; y nos muestra cuantos hay de cada valor.&lt;/p&gt;
&lt;h5&gt;Teniendo en cuenta una columna&lt;/h5&gt;
&lt;p&gt;Veamos la siguiente variante donde cambiamos el &lt;code&gt;*&lt;/code&gt; (que se refiere a todas las filas) por un campo concreto:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este caso lo que hará es devolvernos la cuenta de todas las filas cuyo campo &lt;em&gt;price&lt;/em&gt; no sea &lt;em&gt;null&lt;/em&gt; (el 0 no es nulo). Similar a:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h5&gt;Cuantos elementos distintos hay en una columna&lt;/h5&gt;
&lt;p&gt;Obtención del número de valores diferentes de una columna.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;DISTINCT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Agrupa todos los elementos &lt;em&gt;price&lt;/em&gt; distintos y que no sean nulos, contamos así el número de elementos diferentes de la columna. También es posible añadir una expresión en lugar de un campo como veremos a continuación.&lt;/p&gt;
&lt;h5&gt;Contar con expresiones&lt;/h5&gt;
&lt;p&gt;La función COUNT permite no solo campos sino también añadir expresiones con &lt;code&gt;IF&lt;/code&gt;, &lt;code&gt;IFNULL&lt;/code&gt; y &lt;code&gt;CASE&lt;/code&gt;. Vamos con un ejemplo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;declared&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;new&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Como sabemos, COUNT cuenta elementos no nulos, lo que hacemos con la expresión es anular lo que no cumple nuestra condición y contará solo resultados cuya condición devuelve un valor no nulo. De forma análoga se puede reescribir como:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;declared&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;new&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ELSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;declared&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;new&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Pero una de las ventajas de utilizar expresiones en COUNT (u otras funciones de agregación que permiten expresiones) es poder calcular diferentes resultados en una misma query, y si tiene un índice asociado aprovecharnos de las ventajas que esto conlleva. Por ejemplo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;declared&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;new&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nuevos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;declared&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;used&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;usados&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;declared&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;broken&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rotos&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Suponiendo que tenemos un índice sobre el campo &lt;em&gt;declared&lt;/em&gt; aprovecharemos una respuesta más eficiente de la base de datos en lugar de obtener millones de productos y recorrer nosotros mismos los resultados para clasificar los diferentes valores; o evitando lanzar 3 queries diferentes. Si no existe índice asociado la base de datos tendrá que leer toda la tabla para calcular el resultado.&lt;/p&gt;
&lt;p&gt;Otro ejemplo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;declared&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;new&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nuevos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;activos&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Aquí estamos utilizando dos campos diferentes, y en el caso de MySQL que solo utiliza un índice, tendría que hacer un fullscan de la tabla para obtener los resultados, salvo que tengamos un índice compuesto sobre esos dos campos en cuyo caso sí obtendríamos las ventajas de utilizar un índice para esos dos &lt;code&gt;COUNT&lt;/code&gt;.&lt;/p&gt;
&lt;h5&gt;Otras funciones de agregación y más expresiones&lt;/h5&gt;
&lt;p&gt;En SQL tenemos otras funciones de agregación como son AVG, MAX, MIN, SUM, STD, etc. que también pueden hacer uso de las expresiones que hemos visto para COUNT. Un ejemplo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;en_venta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nulos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;precio_max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;precio_medio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;suma_total&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;NOTA: Para AVG los valores nulos no se tienen en cuenta para la media, en el ejemplo anterior se utiliza NULL para ello y la expresión descarta así precios 0 o negativos. Si utilizáramos un 0 en lugar de NULL (como el caso de SUM), esos 0 se tendrían en cuenta en el cálculo de la media.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Conclusión&lt;/h3&gt;
&lt;p&gt;Suele ser útil delegar a la base de datos muchos de los cálculos, evitamos el tráfico de datos entre la base de datos y la aplicación si realmente solo queremos obtener una estadística. Si además tenemos una correcta estrategia de índices aprovecharemos la eficiencia de la base de datos para realizar este trabajo.&lt;/p&gt;</content><category term="2020"/><category term="desarrollo"/><category term="sql"/><category term="mysql"/></entry><entry><title>The DevOps Handbook: Principio de Flow</title><link href="https://javiblog.com/2020/devops-principio-de-flow.html" rel="alternate"/><published>2020-10-03T20:01:00+02:00</published><updated>2021-02-11T19:41:00+01:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2020-10-03:/2020/devops-principio-de-flow.html</id><summary type="html">&lt;p&gt;Al igual que una optimizada cadena de montaje en una fábrica, hay que crear una cadena de valor para que fluya eficientemente desde el inicio del desarrollo hasta la entrega real del valor al cliente. Tenemos que trabajar de forma continua toda nuestra &lt;em&gt;value stream&lt;/em&gt; para que sea lo más rápida y fiable posible (PARTE 2).&lt;/p&gt;</summary><content type="html">&lt;h1&gt;The DevOps Handbook: Principio de Flow (2/4)&lt;/h1&gt;
&lt;p&gt;Segunda parte del libro &lt;a href="/2020/libro-the-devops-handbook-introduccion.html"&gt;The DevOps Handbook&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Una de las claves que veremos en este principio es la &lt;strong&gt;reducción del tiempo&lt;/strong&gt; para desplegar cambios o nuevas funcionalidades, reduciendo la complejidad y el tiempo necesario para disponer de un incremento de valor en producción, el &lt;strong&gt;lead time&lt;/strong&gt;. Pequeños incrementos donde toda la cadena trabaja con un único objetivo global, no en diferentes objetivos aislados según el equipo.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2020/value_stream_cloudbee.jpg" alt="Esquema Value Stream Customer"&gt;
&lt;br&gt;&lt;small&gt;Fuente: cloudbees.com&lt;/small&gt;
&lt;/div&gt;

&lt;p&gt;Las claves de este principio son las siguientes:&lt;/p&gt;
&lt;h4&gt;Hacer el trabajo visible&lt;/h4&gt;
&lt;p&gt;Una clara diferencia entre el trabajo de una fábrica y el nuestro es que en la fábrica el flujo trabajo es visible y en cierta manera previsible. Para ver como fluye el trabajo en nuestra &lt;em&gt;value stream&lt;/em&gt; debemos conseguir algo similar. Solo así podremos ver qué lleva más tiempo, dónde se bloquea o la cantidad de trabajo pendiente.&lt;/p&gt;
&lt;p&gt;Ejemplos pueden ser los tableros kanban o de sprint planning, o las múltiples re-implementaciones de tableros que nos permiten visualizar y medir en qué punto se encuentra el trabajo.&lt;/p&gt;
&lt;p&gt;Sólo de esta manera los &lt;em&gt;stakeholders&lt;/em&gt; pueden ser capaces de conocer el volumen, las dificultades o priorizar mejor en función del trabajo pendiente. También podremos así proponer mejoras en los puntos más problemáticos, como hacer mejoras en nuestra cadena de trabajo o dar más apoyo donde realmente es necesario.&lt;/p&gt;
&lt;h4&gt;Limitar el trabajo en curso (WIP)&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;WIP: Work In Progress&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;En los equipos de desarrollo es común la llegada urgencias como errores, necesidades imperiosas, ocurrencias. Imaginemos el coste en el caso de una fábrica cuya cadena de producción se interrumpa de esa forma.&lt;/p&gt;
&lt;p&gt;En el caso de tecnología el coste de las urgencias suele ser muy poco visible y además por desgracia ya presuponemos los retrasos de los proyectos software. Pero, ¿y si conseguimos eliminar de la ecuación los retrasos por trabajo no planificado?&lt;/p&gt;
&lt;p&gt;Debemos evitar la existencia del trabajo en paralelo, cada cambio de contexto supone un esfuerzo y un tiempo perdido, que por desgracia también resta energía porque tenemos que lidiar con el &lt;em&gt;multitasking&lt;/em&gt; para volver una y otra vez al trabajo principal.&lt;/p&gt;
&lt;h4&gt;Reducir el tamaño del trabajo&lt;/h4&gt;
&lt;p&gt;Otra de las claves para un flujo suave y ágil es reducir el tamaño del bloque de trabajo. En lugar de disponer un gran bloque que lleva meses desarrollar, es mucho más eficiente pequeños bloques de días o pocas semanas hasta ponerlo en producción.&lt;/p&gt;
&lt;p&gt;Una de las claves &lt;strong&gt;Lean&lt;/strong&gt; en reducir los tiempos de entrega y el aumento de la calidad, y se consigue disminuyendo el tamaño los bloques de trabajo. Grandes bloques pueden provocar una mayor presión sobre los trabajos en curso (WIP), una pérdida de calidad del resultado y unos tiempos de entrega muy altos.&lt;/p&gt;
&lt;p&gt;Un ejemplo para el nuestro caso, trabajar con bloques pequeños donde podremos codificar, testear y desplegar de una forma rápida, y recibir información de su integración en producción de forma rápida. Esto nos permite resolver de forma casi inmediata cualquier incidencia o deuda técnica, ya que tenemos fresco el contexto de trabajo. El incremento de calidad así es más que notable.&lt;/p&gt;
&lt;h4&gt;Reducir el número de pasos (transferencia entre equipos)&lt;/h4&gt;
&lt;p&gt;Cada vez que se transfiere trabajo de un equipo a otro se requiere comunicación, reuniones, coordinación, verificaciones, etc., en resumen, se añade tiempo extra y cierta pérdida de información entre las transferencias.&lt;/p&gt;
&lt;p&gt;En nuestra cadena de trabajo podemos reducir el número de transferencias automatizando procesos del flujo de trabajo, y reorganizando los equipos para permitir mayor autonomía en la entrega de valor al cliente desde su inicio hasta el final.&lt;/p&gt;
&lt;h4&gt;Identificar limitaciones de nuestro flujo y resolver de forma continua&lt;/h4&gt;
&lt;p&gt;Cuando en nuestra cadena de trabajo existe una limitación importante, debemos abordar una solución para resolver esa restricción. Algunos casos de nuestro flujo de trabajo con el desarrollo pueden ser:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Disponer de un entorno de trabajo automatizado &lt;em&gt;self-service&lt;/em&gt;&lt;/strong&gt;, donde no tendremos que dedicar tiempo para configurarnos uno, o depender de que alguien nos provea de dicho entorno para trabajar, testear, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatizar el despliegue del código&lt;/strong&gt;, donde están automatizados todos y cada uno de los pasos que hay que seguir para poner nuestro código en producción, en un tiempo mínimo y con una seguridad controlada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatización de tests&lt;/strong&gt;, en lugar de tener flujos de tests manuales propios o delegar todo a equipos dedicados, automatizar la gran mayoría de ellos para que puedan ser ejecutados bajo demanda o durante los despliegues.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Arquitectura desacoplada&lt;/strong&gt;, proveer de mayor autonomía para completar los cambios, eliminando dependencias que no aportan valor y mejorando también la productividad del desarrollador.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Eliminar dificultades y pérdidas de tiempo de la cadena de valor&lt;/h4&gt;
&lt;p&gt;Esto es otro de los principios Lean: eliminar actividades que no mejoran el resultado de ninguna manera.&lt;/p&gt;
&lt;p&gt;En el caso del desarrollo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Trabajo parcialmente acabado&lt;/strong&gt;, debemos evitar llenar nuestro WIP de tareas inacabadas que solo hacen ruido pero que no aportan nada. Se vuelven obsoletas y pierden valor con el tiempo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extra-procesos&lt;/strong&gt;, tareas o actividades que no añaden nada al resultado, como pueden ser documentación no necesaria, revisiones o aprobaciones que no aportan nada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extra-funcionalidades&lt;/strong&gt;, añadir mayor complejidad y esfuerzo en requerimientos no solicitados que luego requerirán de revisiones, testing o mantenimiento.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multitasking&lt;/strong&gt;, añadir varias tareas a una misma persona, que como ya hemos visto antes supone una pérdida de tiempo con los cambios de contexto y de calidad por la pérdida de foco.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Esperas&lt;/strong&gt;, evitar retrasos por paradas que impiden un flujo continuo, esto puede incentivar el &lt;em&gt;multitasking&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Movimiento&lt;/strong&gt;, trasladar trabajo entre personas o equipos requiere de tiempo de comunicación y esfuerzo de transferencia de información. Evitar el traspaso de tareas hace ganar tiempo y eficacia.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Información defectuosa&lt;/strong&gt;, información incorrecta, parcial o compleja genera derroche de tiempo en solucionar posteriormente errores, que cuanto más tarde se detecten más tiempo conlleva.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trabajo manual o no habitual&lt;/strong&gt;, todo proceso que no puede automatizarse o se realiza forma no habitual, suele significar pérdida de tiempo y riesgos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trabajo heroico&lt;/strong&gt;, cuando un flujo de trabajo está bien establecido no es normal que haya actos de trabajo extraordinarios para llevar adelante una puesta en producción. Esto resta energía y entusiasmo al equipo, especialmente cuando se vuelven habituales.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Ley de Conway&lt;/h3&gt;
&lt;p&gt;Formulado en 1967 por un programador llamado Melvin Conway:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Esto nos viene a indicar que según las estructuras de los equipos así podría ser el diseño de nuestras aplicaciones, como ejemplo nos ilustra como un equipo hizo un compilador que se ejecutaba en una fase, mientras otro equipo hizo lo propio en dos fases porque tenían su equipo dividido en dos grupos.&lt;/p&gt;
&lt;p&gt;Es posible que si diseñamos un proceso basado en cómo se hace actualmente, por ejemplo si tratamos de automatizar el trabajo manual de un almacén, si trasladamos el conocimiento tal cual, nuestro diseño será tan eficiente o ineficiente como el procedimiento original.&lt;/p&gt;</content><category term="2020"/><category term="desarrollo"/><category term="devops"/><category term="metodologías"/><category term="cultura"/><category term="equipos"/><category term="libros"/></entry><entry><title>Reflexión y un ejercicio de claridad</title><link href="https://javiblog.com/2020/reflexion-ejercicio-claridad.html" rel="alternate"/><published>2020-08-19T12:13:00+02:00</published><updated>2020-10-17T15:35:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2020-08-19:/2020/reflexion-ejercicio-claridad.html</id><summary type="html">&lt;p&gt;Una reflexión personal en voz alta para ordenar mis ideas y encontrar claridad en lo que quiero hacer.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Llevo semanas con algo dando vueltas por mi cabeza y necesito escribirlo y explicarlo para ordenar mis ideas.&lt;/p&gt;
&lt;p&gt;En mi trabajo actual hay cambios importantes en el sentido que tenemos mucho por hacer pero también mucho que definir, y todo está mezclado. No podemos parar, pero tampoco podemos dejarnos llevar sin más. Lo más fácil siempre es atender a las urgencias para calmarlas y resolver el problema acuciante de turno, y por desgracia entro demasiadas veces al juego. Es lo más sencillo y da la tranquilidad inmediata de que estás con algo. Pero sabes que no.&lt;/p&gt;
&lt;p&gt;Me considero buen técnico, capaz de resolver muchos problemas gracias a una buena base de conocimiento, la curiosidad, y de experiencia adquirida. Pero me he dejado llevar por el torbellino en varios de los trabajos que he tenido, porque mis compañeros y jefes consideraban también que era lo importante, así que mi experiencias no han sido tan completas. Hasta ahora. &lt;/p&gt;
&lt;p&gt;En la vida es necesario que te quiten el suelo de vez en cuando para que tengas que prestar atención. A veces tienes que golpearte contra el muro un par de veces o más. Hay que dejar que se quemen algunas cosas que parecían importantes pero que una vez quemadas ves que no era tan vitales. &lt;/p&gt;
&lt;p&gt;Hay que investigar el por qué se incendian y no gastar el tiempo solo en apagar esos fuegos, que muchas veces dan igual porque alguien o algo prenderá de nuevo la mecha. Me preparé como ingeniero para construir buenas soluciones, no para ser un héroe del día a día.&lt;/p&gt;
&lt;p&gt;Uno de los mejores ejercicios que he hecho ha sido plantearme dónde quiero ir realmente, qué quiero hacer. Este ejercicio de Claridad es la base fundamental para ir a parar a algún sitio de forma consciente. Tratar de resistir donde no quiero ir. Evitar llegar de casualidad. Dando muchas vueltas he llegado a veces a sitios interesantes, y está bien, pero creo que cuando se toma el timón se disfruta mucho más, y el resultado es mucho más placentero.&lt;/p&gt;
&lt;p&gt;Qué tiene que ver saber lo que quiero con lo que estoy haciendo, pues tan simple como dificultar el hecho de dejarme llevar. Entrar más fácilmente en las contradicciones de lo que quieres sobre lo que haces realmente. Si te acercan o no a tus objetivos.&lt;/p&gt;
&lt;p&gt;Este ejercicio de lo que quiero hacer no puede cubrir solo la parte profesional, sino que parte desde lo más personal que ya no va por separado. Ahora es una tarea recursiva de alinear lo que quiero sobre los siguientes pasos a dar, de cumplir un plan o reconstruirlo cuando cambia. Y esto es más fácil cuando ya sabes donde quieres ir.&lt;/p&gt;</content><category term="2020"/><category term="objetivos"/><category term="reflexiones"/></entry><entry><title>Las redes sociales y la privacidad</title><link href="https://javiblog.com/2014/las-redes-sociales-y-la-privacidad.html" rel="alternate"/><published>2014-09-16T12:41:00+02:00</published><updated>2014-09-16T12:41:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2014-09-16:/2014/las-redes-sociales-y-la-privacidad.html</id><summary type="html">&lt;p&gt;La falsa sensación de control de nuestros datos en las redes sociales. No es tan privado como nos lo cuentan&lt;/p&gt;</summary><content type="html">&lt;p&gt;Sobre este tema se han escrito muchísimos bytes, pero yo también quiero escribir sobre mi punto de vista personal. Llevo trabajando en temas de &lt;strong&gt;redes sociales&lt;/strong&gt; desde hace ya más de 4 años, cuando mi socio Álex y yo decidimos lanzar la red social &lt;a href="https://www.redciclista.com"&gt;redciclista.com&lt;/a&gt;.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2014/Logo_web_128x128.jpg" alt="Logo RedCiclista"&gt;
&lt;/div&gt;

&lt;p&gt;Poco nos podíamos imaginar que facebook nos iba a pegar tan fuerte a las redes sociales verticales o temáticas. Nuestra idea inicial era abordar un &lt;strong&gt;nicho&lt;/strong&gt; en el que las relaciones giran sobre un mismo interés: &lt;strong&gt;el ciclismo&lt;/strong&gt;, e intereses más particulares como carretera, montaña, BMX, etc. Pero no, facebook quiere tener a todo el mundo y con todos los temas, en un mix que puede volver loco a los que comienzan.&lt;/p&gt;
&lt;h3&gt;Sobre tus datos privados&lt;/h3&gt;
&lt;p&gt;Hay un tema que ahora pocos nos detenemos a pensar seriamente, &lt;strong&gt;la privacidad&lt;/strong&gt; de nuestros datos y nuestras acciones. Suele preocuparnos por si nos van a enviar publicidad masiva (spam), o nos van a contactar gente de la que no tenemos interés, pero para mi lo más preocupante es saber &lt;strong&gt;qué va a ser de mis datos, mi actividad y lo que se deducirá de ello&lt;/strong&gt;.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2014/gafas_privacidad_facebook.jpg" alt="Gafas privacidad en facebook"&gt;
&lt;/div&gt;

&lt;p&gt;Los propietarios siempre han de tener todo el control sobre con &lt;strong&gt;quién&lt;/strong&gt; lo comparten y &lt;strong&gt;qué&lt;/strong&gt; comparten. Como ejemplo, en Red Ciclista puedo existir con mis datos en privado y sólo los conoceré yo, sin tener la obligación de compartirlo públicamente con nadie.&lt;/p&gt;
&lt;p&gt;En cualquier red social, un dato que se haga en algún momento público ya estará disponible para cualquier persona o robot que pueda acceder, y posteriormente &lt;strong&gt;ser archivado fuera de tu control&lt;/strong&gt;. También puedo compartir solo con un amigo o un familiar, pero este a su vez puede hacer luego lo que quiera con ello.&lt;/p&gt;
&lt;p&gt;Todos tenemos amigos especialmente activos en las redes sociales, que te acaban etiquetando los sitios más insospechados.&lt;/p&gt;
&lt;p&gt;Tenemos que tener muy claro que el borrado o modificación de una información no va a implicar que esta desaparezca, es muy probable que esa información, ya archivada, esté relacionada contigo hasta el &lt;strong&gt;fin de los tiempos&lt;/strong&gt;. Un ejemplo: &lt;a href="https://web.archive.org/"&gt;internet archive&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Sobre el servicio gratuito&lt;/h3&gt;
&lt;p&gt;Qué hacen con mis &lt;strong&gt;datos públicos&lt;/strong&gt; y &lt;strong&gt;privados&lt;/strong&gt; redes como facebook, twitter, google+, etc. Lee las condiciones legales y verás que por poco más casi les vendes tu alma. Normalmente seguimos adelante sin mirar, porque entonces sólo te queda una opción: no estar, decidir entre tener el servicio o no, estar relacionado o no.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2014/redes_interconectadas.jpg" alt="Grafo de redes interconectadas"&gt;
&lt;/div&gt;

&lt;p&gt;Podemos pensar siendo tantos millones de usuarios pasaremos desapercibidos, pero no es completamente cierto, tus datos están filtrados y categorizados como no te lo puedes ni imaginar. Los algoritmos que se utilizan pueden encasillarnos con una fiabilidad impresionante en los temas que supuestamente nos interesan &lt;strong&gt;o te interesarán en el futuro&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Las empresas detrás de las redes sociales utilizan estos jugosos datos para que, de forma anónima, otras empresas puedan ofrecerte los &lt;em&gt;clavos reforzados&lt;/em&gt; que estás buscando para tu &lt;em&gt;casita de madera en los Montes de Toledo&lt;/em&gt;, y de paso unas &lt;em&gt;mosquiteras&lt;/em&gt; que no habías pensado aún poner. Esto es publicidad muy segmentada a tus intereses, incluso aquellos más inconfesables.&lt;/p&gt;
&lt;h3&gt;Sobre ser anónimo&lt;/h3&gt;
&lt;p&gt;Si protegemos los datos para que no sean públicos así deberían quedar, &lt;strong&gt;anónimos&lt;/strong&gt;. El perfil será conocido sólo dentro de esa red social y a los que hemos dado permiso. Los anunciantes que utilizan los servicios de anuncios de la red social no deberían saber nada de forma particular, ni aunque hayamos puesto los datos públicos. La red social sólo vende categorías de perfiles. Un anunciante normalmente quiere llegar a un perfil tipo y le dará igual como nos llamemos. &lt;strong&gt;Pero atención, podrían querer saber más cosas de nosotros&lt;/strong&gt;.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2014/cara_anonima.png" alt="emoticono cara anónimo"&gt;
&lt;/div&gt;

&lt;p&gt;Si alguien o &lt;em&gt;una entidad&lt;/em&gt; quiere conocernos de forma concreta, a partir de unos pocos datos personales y las relaciones con gente, podrían sacar un perfil de cómo somos y qué hacemos, cualquiera que acceda a herramientas tan sencillas como los buscadores y las redes sociales puede investigar la vida de una persona con cierta actividad en internet, al punto de llegar casi a conocer sus hábitos. ¿Quién no ha buscado compañeros de clase para ver qué es de su vida o cómo son ahora?&lt;/p&gt;
&lt;p&gt;Ahora tenemos un nuevo comportamiento, subir a internet nuestra &lt;strong&gt;ubicación&lt;/strong&gt; habitual, con nuestros logros deportivos, paseos, quedadas, citas, etc. Está claro que no solo podrían saber de nosotros sino que también pueden encontrarnos sin dificultad alguna. Como &lt;strong&gt;ejemplo real&lt;/strong&gt;, puedo conocer el lugar donde está un conocido mio, todo lo &lt;em&gt;tuitea&lt;/em&gt; con la ubicación activada.&lt;/p&gt;
&lt;p&gt;Más preocupante es la captura de datos de algunos gobiernos para ver si somos &lt;strong&gt;malas personas&lt;/strong&gt;. Todos creemos que estamos hoy a salvo, ya que no hacemos nada sospechoso ni nada que no haga ya la mayoría, nos sentimos ocultos en la muchedumbre. Bueno, en cierta forma es cierto que es muy poco probable que un don nadie sea vigilado de una forma ta particular, pero los &lt;strong&gt;falsos positivos&lt;/strong&gt; existen o incluso en algún momento podemos dejar de ser un don nadie, y ya es tarde, estamos ahí mismo expuestos.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2014/anonymous.gif" alt="Careta Anonymous"&gt;
&lt;/div&gt;

&lt;p&gt;¿LinkedIn es fiable para hacer negocios? ¿Y para buscar compañeros, inversores? ¿Publico ahí mi business plan? ¿Quién más tiene acceso a todas esta mina de oro?&lt;/p&gt;
&lt;h3&gt;Sobre el control de tus datos&lt;/h3&gt;
&lt;p&gt;El único control que nos queda es usar sentido común, es decir, no compartir nada que no quieres que se sepa de ti públicamente. Tan fácil y a veces tan complicado como eso.&lt;/p&gt;
&lt;p&gt;Si quieres hacerte un selfie con un desnudo integral, y crees que está a salvo en tu teléfono, pues quizás deberías pensarlo de nuevo.&lt;/p&gt;
&lt;p&gt;El único dato controlado es aquel que no ha sido puesto disponible.&lt;/p&gt;
&lt;h3&gt;Sobre el derecho al olvido&lt;/h3&gt;
&lt;p&gt;Hace poco que Europa exigió a google el cumplimiento de lo que se conoce como el derecho al olvido, es decir que alguien pueda solicitar a los buscadores que eliminen alguna información personal.&lt;/p&gt;
&lt;p&gt;Muy difícil, incluso aunque google lo elimine de sus índices o de los resultados, la información podrá seguir apareciendo en muchos otros sitios que guardaron en su momento la información. Tu "enemigo" habrá capturado eso que no quieres que se sepa, y lo publicará las veces que haga falta. Es más cuanto más notoria sea tu oposición más visibilidad podrá tener lo que quieres ocultar.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;a href="http://es.wikipedia.org/wiki/Efecto_Streisand" title="Efecto Streisand"&gt;
&lt;img src="/images/2014/barbra-streisand-pixabay.jpg" alt="Barbra Streisand"&gt;
&lt;/a&gt;
&lt;br&gt;&lt;small&gt;Efecto Streisand&lt;/small&gt;
&lt;/div&gt;

&lt;h3&gt;Conclusión&lt;/h3&gt;
&lt;p&gt;No muestres lo que no quieres que se sepa, y si ya lo has hecho, borra o modifica silenciosamente. La vida que uno lleva suele ser poco o nada interesante para terceros, hasta que ocurre algo que puede llevarte a ser foco de atención y decidas que mucha información no debería estar ahí, quizás sea tarde.&lt;/p&gt;
&lt;p&gt;Cuida con quien te relacionas en las redes, no todos buscan ser amiguetes.&lt;/p&gt;
&lt;p&gt;Separa las relaciones profesionales de las más privadas, tienes diferentes tipologías de redes sociales para hacerlo, o diferentes cuentas. Si te es posible, no relaciones una red social con otra de forma directa, ni indirecta utilizando el mismo email, nick, foro, teléfono, etc.&lt;/p&gt;</content><category term="2014"/><category term="privacidad"/><category term="redes sociales"/><category term="anonimato"/></entry><entry><title>La deuda técnica intencionada en el desarrollo</title><link href="https://javiblog.com/2014/la-deuda-tecnica-intencionada-en-el-desarrollo.html" rel="alternate"/><published>2014-09-01T03:43:00+02:00</published><updated>2020-05-02T13:20:00+02:00</updated><author><name>Javi</name></author><id>tag:javiblog.com,2014-09-01:/2014/la-deuda-tecnica-intencionada-en-el-desarrollo.html</id><summary type="html">&lt;p&gt;Qué son las deudas técnicas en el desarrollo de software, por qué pueden ser útiles y cómo deberías controlarlo&lt;/p&gt;</summary><content type="html">&lt;p&gt;Hoy (2014) he aprendido una nueva definición que me ha llamado la atención por el nombre, y que a lo largo de mi trabajo como programador he tenido que lidiar con ello. Nunca le había conocido un nombre hasta hoy: &lt;strong&gt;deuda técnica&lt;/strong&gt; (&lt;em&gt;technical debt&lt;/em&gt; en su origen inglés), aunque de alguna manera siempre he sido consciente de su existencia y de sus consecuencias.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2014/atajo-en-laberinto.jpg" alt="atajo"&gt;
&lt;/div&gt;

&lt;p&gt;Se trata a la deuda como algo malo a evitar, pero me voy a centrar en la utilidad de la deuda &lt;strong&gt;intencionada&lt;/strong&gt; que dejamos pendiente de saldar con conocimiento de causa y sus posibles consecuencias.&lt;/p&gt;
&lt;h2&gt;¿En qué consiste la deuda técnica intencionada?&lt;/h2&gt;
&lt;p&gt;Si has trabajado en proyectos de desarrollo de software con una pobre planificación, o bien con una fecha &lt;em&gt;demasiado ajustada&lt;/em&gt; para cumplirla, o quizás por otros motivos, es fácil que te haya llevado a optar por una solución provisional menos óptima, por ser más simple y rápida.&lt;/p&gt;
&lt;p&gt;¡Ojo!, &lt;strong&gt;una deuda técnica intencionada no es sinónimo de una chapuza&lt;/strong&gt; o la típica &lt;em&gt;ñapa&lt;/em&gt;, esta deuda es un compromiso para satisfacer unos requisitos más básicos y cumplir con una demo o una primera entrega preliminar. Este compromiso permite tomar un camino más rápido con la promesa de, mediante un refactoring o reescritura del código, resolverlo posteriormente de forma más correcta.&lt;/p&gt;
&lt;p&gt;Un ejemplo típico es hacer un código más sencillo con una optimización muy básica que soportará un volumen de accesos bajo. La deuda técnica pendiente podría ser refactorizar
cambiando la arquitectura o el código para implementar colas, caches o una optimización de la base de datos.&lt;/p&gt;
&lt;p&gt;Otro ejemplo es relajar la seguridad de la aplicación para una demo a un cliente, aquí es más evidente que no pagar la deuda podría ser muy doloroso al paso a producción.&lt;/p&gt;
&lt;p&gt;A nivel de diseño también podrías adquirir una deuda técnica intencionada, pero estas son más complicadas y poco recomendables salvo que esté bien justificado y controlado. Este tipo de deuda en diseño ha de documentarse muy bien hacia abajo para tener en cuenta este detalle en la codificación. El posterior pago de la deuda probablemente llevará mucho más esfuerzo
o rehacerlo casi todo, pero la ventaja de que sabré mucho más de lo que pretendo solucionar y lo que no debo implementar.&lt;/p&gt;
&lt;div style="text-align:center;"&gt;
&lt;img src="/images/2014/deuda-tecnica.jpg" alt="Deuda técnica"&gt;
&lt;/div&gt;

&lt;h2&gt;Documenta tus deudas y gestiónalas&lt;/h2&gt;
&lt;p&gt;Es importante que todas estas deudas que vamos dejando estén &lt;strong&gt;documentadas&lt;/strong&gt; para no olvidar por qué existen. En mi caso solía documentar lo más importante mediante listas de
pendientes, pero después de acumular muchas deudas tenía la sensación de que era mejor rehacerlo todo según aumentaba su volumen, y lo que es peor, si no documentas olvidas el motivo de la deuda.&lt;/p&gt;
&lt;p&gt;Así que toma conciencia que existen las deudas técnicas y utilizarlas en mi opinión no es malo, &lt;strong&gt;te permite desarrollar y probar más rápido&lt;/strong&gt;. A cambio has de tener en cuenta que en algún momento has de incorporar el &lt;strong&gt;pago de esas deudas&lt;/strong&gt; al flujo de trabajo, y mejor cuanto antes, que los intereses luego pueden ser muy altos o directamente inasumibles.&lt;/p&gt;
&lt;p&gt;Si no incluyes &lt;strong&gt;el pago de tus deudas técnicas en tu metodología de trabajo&lt;/strong&gt;, y en un &lt;strong&gt;tiempo razonable&lt;/strong&gt;, entonces tu código no será óptimo, dejará de cumplir los requisitos reales para los que se escribió y finalmente quedarán pegotes para la posteridad.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dear maintainer:&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// Once you are done trying to &amp;#39;optimize&amp;#39; this routine,&lt;/span&gt;
&lt;span class="c1"&gt;// and have realized what a terrible mistake that was,&lt;/span&gt;
&lt;span class="c1"&gt;// please increment the following counter as a warning&lt;/span&gt;
&lt;span class="c1"&gt;// to the next guy:&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// total_hours_wasted_here = 42&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="2014"/><category term="desarrollo"/><category term="metodologías"/><category term="equipos"/></entry></feed>