<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Blog on Froilán Irizarry Rivera</title>
        <link>https://froi.dev/posts/</link>
        <description>Recent content in Blog on Froilán Irizarry Rivera</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <atom:link href="https://froi.dev/posts/index.xml" rel="self" type="application/rss+xml" />
        
        <item>
            <title>TIL: Claude Code Messed Up My WezTerm Config</title>
            <link>https://froi.dev/posts/til-claude-code-messed-up-my-wezterm-config/</link>
            <pubDate>Sat, 15 Nov 2025 18:28:54 -0500</pubDate>
            
            <guid>https://froi.dev/posts/til-claude-code-messed-up-my-wezterm-config/</guid>
            <description>&lt;p&gt;Hace poco instalé Claude Code para ver como podía jugar un rato con la herramienta. Mi interés principal es agilizar
la creación de proofs of concepts de ideas que llevo diseñando hace demasiado tiempo.&lt;/p&gt;
&lt;p&gt;Todo funcionó como esperado al seguir el &lt;a href=&#34;https://code.claude.com/docs/en/quickstart&#34;&gt;quickstart&lt;/a&gt;, pero al cerrar y
abrir mi terminal toda su configuración dejo de funcionar.&lt;/p&gt;
&lt;p&gt;Fue de usar catppuccin y remover el tab-line a tener su configuración default.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://froi.dev/posts/til-claude-code-messed-up-my-wezterm-config/images/wezterm-with-config.png&#34;
    alt=&#34;Una imagen de un instancia de WezTerm con mi configuración activa&#34; width=&#34;100%&#34; height=&#34;100%&#34;&gt;&lt;figcaption&gt;
      &lt;p&gt;WezTerm con mi configuración activada&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Hace poco instalé Claude Code para ver como podía jugar un rato con la herramienta. Mi interés principal es agilizar
la creación de proofs of concepts de ideas que llevo diseñando hace demasiado tiempo.</p>
<p>Todo funcionó como esperado al seguir el <a href="https://code.claude.com/docs/en/quickstart">quickstart</a>, pero al cerrar y
abrir mi terminal toda su configuración dejo de funcionar.</p>
<p>Fue de usar catppuccin y remover el tab-line a tener su configuración default.</p>
<figure><img src="/posts/til-claude-code-messed-up-my-wezterm-config/images/wezterm-with-config.png"
    alt="Una imagen de un instancia de WezTerm con mi configuración activa" width="100%" height="100%"><figcaption>
      <p>WezTerm con mi configuración activada</p>
    </figcaption>
</figure>

<figure><img src="/posts/til-claude-code-messed-up-my-wezterm-config/images/wezterm-no-config.png"
    alt="Una imagen de una instancia de WezTerm con su configuración default activa" width="100%" height="100%"><figcaption>
      <p>WezTerm con su configuración default</p>
    </figcaption>
</figure>

<p>Después de pasar una cantidad de tiempo absurda tratando de ver porque no tomaba mi configuración encontré que
Claude Code busca la configuración de WezTerm siguiendo su <a href="https://wezterm.org/config/files.html#configuration-files">documentación</a> y asume que solo puede
estar en el directorio <em>home</em> del usuario:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>&gt; /terminal-setup
</span></span><span style="display:flex;"><span>  ⎿  Installed WezTerm Shift+Enter key binding
</span></span><span style="display:flex;"><span>     You may need to restart WezTerm <span style="color:#66d9ef">for</span> changes to take effect
</span></span><span style="display:flex;"><span>     See /Users/froi/.wezterm.lua
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>─────────────────────────────────────────────────────────────────────────────────
</span></span><span style="display:flex;"><span>&gt;
</span></span><span style="display:flex;"><span>─────────────────────────────────────────────────────────────────────────────────
</span></span><span style="display:flex;"><span>  ? <span style="color:#66d9ef">for</span> shortcuts                                   Thinking on <span style="color:#f92672">(</span>tab to toggle<span style="color:#f92672">)</span>
</span></span></code></pre></div><p>Este comando lo que intenta añadir es configuración que permita usar SHIFT+Enter para enviar un prompt de multiples
lineas, lo cual es util.</p>
<details>
<summary>Hacer click aquí para ver el config</summary>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#66d9ef">local</span> wezterm <span style="color:#f92672">=</span> require <span style="color:#e6db74">&#39;wezterm&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> config <span style="color:#f92672">=</span> wezterm.config_builder()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>config.keys <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>  {key<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Enter&#34;</span>, mods<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;SHIFT&#34;</span>, action<span style="color:#f92672">=</span>wezterm.action{SendString<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\x1b\r</span><span style="color:#e6db74">&#34;</span>}},
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> config
</span></span></code></pre></div></details>
<p>Por ahora lo único que se puede hacer es mover tu configuración a <strong>~/.wezterm.lua</strong> o añadir la entrada a <em>config.keys</em>
manualmente. En mi caso eso fue lo que <a href="https://codeberg.org/froi/configs/src/branch/main/wezterm/.config/wezterm/wezterm.lua#L94">hice</a>.</p>
<p>Ya existe un <a href="https://github.com/anthropics/claude-code/issues/9753">bug</a> reportando este comportamiento. No me sorprendería si esto no es un tema
exclusivo a WezTerm y me pregunto si Anthropic arreglara el problema.</p>
]]></content>
        </item>
        
        <item>
            <title>Dejando GitHub atrás</title>
            <link>https://froi.dev/posts/dejando-github-atras/</link>
            <pubDate>Fri, 26 Sep 2025 17:13:21 -0400</pubDate>
            
            <guid>https://froi.dev/posts/dejando-github-atras/</guid>
            <description>&lt;p&gt;Por muchos años fui un súper fan de GitHub, pero esto ha ido cambiando desde el 2019 cuando me uní a la compañía.&lt;/p&gt;
&lt;p&gt;Después de separarme de la compañía en el 2021, he visto como el cambio acelerado la ha llevado de mal en peor. Es una
pena que una plataforma tan integral a lo que era ser un developer en el internet se haya convertido en un
vehiculo para aumentar el consumo de Azure y ahora AI para Microsoft. Sí, esto lleva mucho tiempo cuajándose, pero la
última gota para mi fue cuando el &lt;a href=&#34;https://www.theverge.com/news/757461/microsoft-github-thomas-dohmke-resignation-coreai-team-transition&#34;&gt;CEO de GitHub renunció y la compañía completa fue integrada al equipo de AI en
Microsoft&lt;/a&gt;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Por muchos años fui un súper fan de GitHub, pero esto ha ido cambiando desde el 2019 cuando me uní a la compañía.</p>
<p>Después de separarme de la compañía en el 2021, he visto como el cambio acelerado la ha llevado de mal en peor. Es una
pena que una plataforma tan integral a lo que era ser un developer en el internet se haya convertido en un
vehiculo para aumentar el consumo de Azure y ahora AI para Microsoft. Sí, esto lleva mucho tiempo cuajándose, pero la
última gota para mi fue cuando el <a href="https://www.theverge.com/news/757461/microsoft-github-thomas-dohmke-resignation-coreai-team-transition">CEO de GitHub renunció y la compañía completa fue integrada al equipo de AI en
Microsoft</a>.</p>
<p>Si soy honesto, mi discontento con GitHub lleva tiempo pero me hice de la vista larga. Ignoré y hasta vendí ciertos
valores por quedarme en lo conocido. Me enfoqué en lo que me gustaba de la plataforma y me dije &ldquo;lo que tengo que hacer
es no utilizar lo que no me gusta&rdquo;.</p>
<p>Llevo unos meses probando alternativas para mover la mayoría del código que me pertenece a otras plataformas. Digo la
mayoría porque la verdad es que no todo con lo que he trabajado es mio. Todo lo que hice con <a href="https://github.com/Code4PuertoRico/">Code for Puerto
Rico</a> se va a quedar en GitHub junto a los forks que hice de proyectos que viven en ahí.</p>
<h2 id="este-blog">Este blog</h2>
<p>froidotdev era un repositorio en GitHub y la página estaba siendo servida mediante GitHub Pages. Eso cambio al escribir
este post.</p>
<p>El contenido de esta página ahora vive en GitLab en un repositorio privado y está servido como un static site app en
DigitalOcean.</p>
<p>Siendo una página generada utilizando Hugo hizo el movimiento extremadamente fácil. DigitalOcean tiene
<a href="https://www.digitalocean.com/community/tutorials/how-to-build-and-deploy-a-hugo-site-to-digitalocean-app-platform#step-4-deploying-to-digitalocean-with-app-platform">un excelente tutorial</a> de como construir y hacer deploy de un Hugo site.</p>
<p>Fuera de cambiar el uso de GitHub, tuve que añadir <a href="https://docs.digitalocean.com/products/app-platform/reference/buildpacks/hugo/#specify-a-hugo-version">HUGO_EXTENDED = 1</a> como variable de ambiente
para especificar que versión de Hugo utilizar. Esto se debe al uso de Sass/SCSS en el theme de la página.</p>
<h2 id="mis-repositorios">Mis repositorios</h2>
<p>Voy a estar experimentando con <a href="https://codeberg.org">Codeberg.org</a>, <a href="https://forgejo.org/">Forgejo</a> y <a href="https://gitlab.com/froidotdev">GitLab</a>.</p>
<p>Me gusta mucho <a href="https://forgejo.org/">Forgejo</a>, me recuerda un poco a lo que era GitHub en el pasado. Es una plataforma que se
hace fácil hacer self hosting y quiero ver si es algo que me conviene hacer.</p>
<p>Por esto, todo lo que es FOSS donde soy el dueño lo estaré moviendo a <a href="https://codeberg.org/froi">Codeberg.org/froi</a>.
<a href="https://codeberg.org">Codeberg.org</a> es una entidad sin fines de lucro operando en Berlín que maneja una instancia de Forgejo.
Su misión y la estructura bajo la que operan me llama mucho la atención. Cubre todo lo que considero importante para mí
dentro de FOSS, todo lo que ignoré por mucho años. Todo lo que estoy trabajando fuera del ambito de FOSS lo estaré
moviendo a <a href="https://gitlab.com/froidotdev">GitLab</a>.</p>
<h2 id="por-qué-no-mover-todo-a-gitlab-o-codeberg">¿Por qué no mover todo a GitLab o Codeberg?</h2>
<p>Codeberg.org está 100% dedicado al apoyo a FOSS. Dentro de sus terminos de uso especifica que no apoya repositorios
privados (con excepciones) u organizaciones con fines de lucro que trabajen con código propietario. Quiero respetar
esto. Por ende, todo proyecto con fin de lucro o que no sea 100% abierto lo estaré trabajando desde GitLab.
Es importante que protejamos los recursos como Codeberg para que estén disponibles para comunidad y evitar la
<a href="https://es.wikipedia.org/wiki/Tragedia_de_los_bienes_comunales">tragedia de los bienes comunales</a> (<a href="https://en.wikipedia.org/wiki/Tragedy_of_the_commons">tragedy of the commons</a>).</p>
<p>GitLab también provee mucha conveniencia al ser una plataforma completa. De esta manera colaborar con mi equipo remoto
se agiliza. Muchas de las preguntas sobre DevOps ya están contestadas y manejadas por la plataforma. Aunque me tome
&ldquo;mucho&rdquo; acostumbrarme a GitLab (no soy muy fanático de como está estructurado), creo que es la opción correcta y más
pragmática.</p>
<h2 id="cuando-dejaré-de-brincar">Cuando dejaré de brincar</h2>
<p>Pues no sé. Por ahora creo que este arreglo va a funcionar bien. En los próximos meses intentaré seguir removiendo mi
dependencia de servicios y productos de &ldquo;big tech&rdquo; y de compañías que sean de los EEUU, algo de lo que escribiré en otro
post.</p>
<p>Si tienen ideas que compartir tirenme un toot a <a href="https://mastodon.social/@froi">mastodon.social/@froi</a>.</p>
]]></content>
        </item>
        
        <item>
            <title>Working with TODO comments</title>
            <link>https://froi.dev/posts/working-with-todo-comments/</link>
            <pubDate>Mon, 04 Aug 2025 01:20:14 -0400</pubDate>
            
            <guid>https://froi.dev/posts/working-with-todo-comments/</guid>
            <description>&lt;p&gt;Code comments are as common as any language keyword. From the venerable &lt;em&gt;TODO&lt;/em&gt; to a &lt;em&gt;DAFUQ&lt;/em&gt;, I&amp;rsquo;ve seen comments used
to inform, express frustration, and mark jobs to be done. For a long time finding these comments would frustrate me.
Why comment a piece of code with a &lt;em&gt;FIXME&lt;/em&gt; when you could just fix it or create an issue in your tool of choice?&lt;/p&gt;
&lt;p&gt;While I&amp;rsquo;m still of the opinion that these comments are troublesome when going stale, I&amp;rsquo;ve changed my perspective a
bit by looking at them as tags that can help me navigate a code base. These tags are hints for me or my team to take
a look and action on a part of the code we&amp;rsquo;ve marked as &amp;ldquo;of interest&amp;rdquo;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Code comments are as common as any language keyword. From the venerable <em>TODO</em> to a <em>DAFUQ</em>, I&rsquo;ve seen comments used
to inform, express frustration, and mark jobs to be done. For a long time finding these comments would frustrate me.
Why comment a piece of code with a <em>FIXME</em> when you could just fix it or create an issue in your tool of choice?</p>
<p>While I&rsquo;m still of the opinion that these comments are troublesome when going stale, I&rsquo;ve changed my perspective a
bit by looking at them as tags that can help me navigate a code base. These tags are hints for me or my team to take
a look and action on a part of the code we&rsquo;ve marked as &ldquo;of interest&rdquo;.</p>
<p>After some time accepting and working with these &ldquo;tags&rdquo; I started to look for tooling I could use in NVIM that would
enhance my experience. I wanted these tags to be visually distinctive and I wanted my IDE/code editor to help me find
them. Turns out that a few awesome folks have wanted and built this tooling, and it&rsquo;s not just for big IDEs.</p>
<p>Let&rsquo;s start by looking at the <a href="/posts/working-with-todo-comments/#tags">tags</a> before we go into the <a href="/posts/working-with-todo-comments/#tooling">tooling</a>.</p>

            <link rel="stylesheet" href="/css/vendors/admonitions.4fd9a0b8ec8899f2ca952048d255a569f433f77dfb3f52f5bc87e7d65cdce449.css" integrity="sha256-T9mguOyImfLKlSBI0lWlafQz9337P1L1vIfn1lzc5Ek=" crossorigin="anonymous">
    <div class="admonition tip">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M272 384c9.6-31.9 29.5-59.1 49.2-86.2c0 0 0 0 0 0c5.2-7.1 10.4-14.2 15.4-21.4c19.8-28.5 31.4-63 31.4-100.3C368 78.8 289.2 0 192 0S16 78.8 16 176c0 37.3 11.6 71.9 31.4 100.3c5 7.2 10.2 14.3 15.4 21.4c0 0 0 0 0 0c19.8 27.1 39.7 54.4 49.2 86.2l160 0zM192 512c44.2 0 80-35.8 80-80l0-16-160 0 0 16c0 44.2 35.8 80 80 80zM112 176c0 8.8-7.2 16-16 16s-16-7.2-16-16c0-61.9 50.1-112 112-112c8.8 0 16 7.2 16 16s-7.2 16-16 16c-44.2 0-80 35.8-80 80z"/></svg>
        <span>Tip</span>
      </div>
      <div class="admonition-content">
        <p>You can jump to the <a href="/posts/working-with-todo-comments/#vs-code-and-vs-codium-example">example configuration for VS Code / Codium</a> if that&rsquo;s all you need.</p>
      </div>
    </div><h2 id="tags">Tags</h2>
<p>There&rsquo;s a ton of tags that we could use but to keep it &ldquo;short&rdquo; I&rsquo;ve been using some version of</p>
<ul>
<li><a href="/posts/working-with-todo-comments/#todo"><strong>TODO</strong></a></li>
<li><a href="/posts/working-with-todo-comments/#issue"><strong>ISSUE</strong></a></li>
<li><a href="/posts/working-with-todo-comments/#hack"><strong>HACK</strong></a></li>
<li><a href="/posts/working-with-todo-comments/#tip"><strong>TIP</strong></a></li>
<li><a href="/posts/working-with-todo-comments/#info"><strong>INFO</strong></a></li>
<li><a href="/posts/working-with-todo-comments/#pref"><strong>PERF</strong></a></li>
<li><a href="/posts/working-with-todo-comments/#test"><strong>TEST</strong></a></li>
<li><a href="/posts/working-with-todo-comments/#warn"><strong>WARN</strong></a></li>
</ul>
<h3 id="todo">TODO</h3>
<p>The &ldquo;classic&rdquo; comment that can be found in many a code base.</p>
<ul>
<li><strong>Alternatives:</strong> TO-DO</li>
</ul>
<h3 id="warn">WARN</h3>
<p>Used to warn the reader that something is off but can&rsquo;t be easily identified as a bug or hack.</p>
<ul>
<li><strong>Alternatives:</strong> WARNING, WAT</li>
</ul>
<h3 id="issue">ISSUE</h3>
<p>Tag to indicate something is off and we should come back to fix. I also add an issue link if one exists. It&rsquo;s
important to note that this tag should be removed. I think it&rsquo;s a big smell if a &ldquo;fixme&rdquo; comment is there for a
long period of time. At that point, do you really need to fix it?</p>
<ul>
<li><strong>Alternatives:</strong> BUG, FIX, FIXIT, FIX-IT, FIXME, FIX</li>
</ul>
<h3 id="hack">HACK</h3>
<p>Tag to indicate that a piece of code might be working well but has some sort of smell or is not optimal</p>
<h3 id="tip">TIP</h3>
<p>Tag to provide a call out for some insight around the use or structure of a piece of code. Used more to
draw attention of the reader than to properly document.</p>
<ul>
<li><strong>Alternatives:</strong> IMPORTANT</li>
</ul>
<h3 id="info">INFO</h3>
<p>Sometimes I want to add some addition context to a piece of code. I treat this tag like a &ldquo;general&rdquo; code comment.</p>
<ul>
<li><strong>Alternatives:</strong> NOTE</li>
</ul>
<h3 id="perf">PERF</h3>
<p>I rarely use this tag, but once in a while I find I want to call out the structure of a code block as being optimize
or needing optimization. I find this helps with code that might not look &ldquo;normal&rdquo; or following common patterns but
isn&rsquo;t a <a href="/posts/working-with-todo-comments/#hack"><em>HACK</em></a> (at least in my eyes).</p>
<ul>
<li><strong>Alternatives:</strong> OPTIM, PERFORMANCE, OPTIMIZE</li>
</ul>
<h3 id="test">TEST</h3>
<p>Used to mark a section of code that&rsquo;s meant to be a test. Imagine having a utility function that you just don&rsquo;t know if
you want to keep</p>
<ul>
<li><strong>Alternatives:</strong> TESTING</li>
</ul>
<h2 id="tooling">Tooling</h2>
<p>Tooling has always been a rabbit hole for me. I was &ldquo;lucky&rdquo; that <a href="https://www.lazyvim.org/">Lazyvim</a> has <a href="https://github.com/folke/todo-comments.nvim">todo-comments.nvim</a>
already packaged in the distribution.</p>
<p><a href="https://github.com/folke/todo-comments.nvim">todo-comments.nvim</a> is another fantastic plugin by <a href="https://github.com/folke">folke</a> that</p>
<blockquote>
<p>is a lua plugin for Neovim &gt;= 0.8.0 to highlight and search for todo comments like TODO, HACK, BUG in your code base.</p></blockquote>
<p>This plugin uses other excellent plugins like <a href="https://github.com/folke/trouble.nvim">trouble.nvim</a>, <a href="https://github.com/nvim-telescope/telescope.nvim">telescope</a>, and <a href="https://github.com/ibhagwan/fzf-lua">fzflua</a>
to provide an IDE like experience.</p>
<p><img src="https://user-images.githubusercontent.com/292349/118135272-ad21e980-b3b7-11eb-881c-e45a4a3d6192.png" alt="todo-comments"></p>
<p>Having the TODOS, WARNINGS, and other tags searchable and show up in <a href="https://github.com/folke/trouble.nvim">trouble.nvim</a> makes using them to
navigate the code base incredibly simple. Over the last couple of weeks it&rsquo;s helped me find code blocks that needed
attention. While some of these comments were definitely out of date, I still found them useful. At a minimum I
had a really easy time identifying where to do some clean up.</p>

    <div class="admonition note">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M0 64C0 28.7 28.7 0 64 0L224 0l0 128c0 17.7 14.3 32 32 32l128 0 0 125.7-86.8 86.8c-10.3 10.3-17.5 23.1-21 37.2l-18.7 74.9c-2.3 9.2-1.8 18.8 1.3 27.5L64 512c-35.3 0-64-28.7-64-64L0 64zm384 64l-128 0L256 0 384 128zM549.8 235.7l14.4 14.4c15.6 15.6 15.6 40.9 0 56.6l-29.4 29.4-71-71 29.4-29.4c15.6-15.6 40.9-15.6 56.6 0zM311.9 417L441.1 287.8l71 71L382.9 487.9c-4.1 4.1-9.2 7-14.9 8.4l-60.1 15c-5.5 1.4-11.2-.2-15.2-4.2s-5.6-9.7-4.2-15.2l15-60.1c1.4-5.6 4.3-10.8 8.4-14.9z"/></svg>
        <span>Note</span>
      </div>
      <div class="admonition-content">
        <p>I found the default <a href="https://github.com/folke/todo-comments.nvim?tab=readme-ov-file#%EF%B8%8F-configuration">configuration for todo-comments</a> to be exactly what I needed.</p>
      </div>
    </div><h3 id="vs-code-and-vs-codium">VS Code and VS Codium</h3>
<p>While I was perfectly happy in my <a href="https://www.lazyvim.org/">Lazyvim</a> bubble, for the rest of my team <a href="https://code.visualstudio.com/">VSCode</a> / <a href="https://vscodium.com/">VSCodium</a> is the editor of choice.
I found two really great extensions that make working with these tags a joy, <a href="https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree">Todo Tree</a> and
<a href="https://marketplace.visualstudio.com/items?itemName=EdwinHuiSH.better-comments-next">Better Comments Next</a>.</p>
<p><a href="https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree">Todo Tree</a> will provide a similar experience to <a href="https://github.com/folke/trouble.nvim">trouble</a> and <a href="https://github.com/nvim-telescope/telescope.nvim">telescope</a>,
making the comments searchable and letting you navigate to them with a click.</p>
<p><img src="https://raw.githubusercontent.com/Gruntfuggly/todo-tree/master/resources/screenshot.png" alt="todo-tree-ui"></p>
<p><a href="https://marketplace.visualstudio.com/items?itemName=EdwinHuiSH.better-comments-next">Better Comments Next</a> provides the color and highlighting for the comments.</p>
<p>To get these extensions to work similar to my NVIM plugins I added some configuration in the <strong>.vscode/settings.json</strong>
file.</p>

    <div class="admonition important">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/></svg>
        <span>Important</span>
      </div>
      <div class="admonition-content">
        <p>You will want to define a minimum set of tags that are shared in all of your IDEs and code editors. It&rsquo;s fine
if one is a superset of the other, but a minimum overlap will help you and your team have the same experience.</p>
      </div>
    </div><h3 id="todo-tree">Todo Tree</h3>
<p>To configure <a href="https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree">Todo Tree</a> I added two sections</p>
<ul>
<li>
<p><em>todo-tree.general.tags</em>: a list of all the tags I wanted to add/support</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#e6db74">&#34;todo-tree.general.tags&#34;</span><span style="color:#960050;background-color:#1e0010">:</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;BUG&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;HACK&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;FIX&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;FIXIT&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;FIX-IT&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;FIXME&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;FIX-ME&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;IMPORTANT&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#960050;background-color:#1e0010">...</span>
</span></span><span style="display:flex;"><span>]<span style="color:#960050;background-color:#1e0010">,</span>
</span></span></code></pre></div></li>
<li>
<p><em>todo-tree.general.tagGroups</em>: an object that defines how to group the tags into categories. The keys of the objects
are the categories while the values can be simple string or arrays of strings.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#e6db74">&#34;todo-tree.general.tagGroups&#34;</span><span style="color:#960050;background-color:#1e0010">:</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;INFO&#34;</span>: [<span style="color:#e6db74">&#34;NOTE&#34;</span>],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;TODO&#34;</span>: [<span style="color:#e6db74">&#34;TO-DO&#34;</span>, <span style="color:#e6db74">&#34;[ ]&#34;</span>, <span style="color:#e6db74">&#34;[X]&#34;</span>],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;BUG&#34;</span>: [<span style="color:#e6db74">&#34;FIX&#34;</span>, <span style="color:#e6db74">&#34;FIXIT&#34;</span>, <span style="color:#e6db74">&#34;FIX-IT&#34;</span>, <span style="color:#e6db74">&#34;FIXME&#34;</span>, <span style="color:#e6db74">&#34;FIX-ME&#34;</span>],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;WARN&#34;</span>: [<span style="color:#e6db74">&#34;WARNING&#34;</span>, <span style="color:#e6db74">&#34;WAT&#34;</span>, <span style="color:#e6db74">&#34;XXX&#34;</span>],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;HACK&#34;</span>: [<span style="color:#e6db74">&#34;IMPORTANT&#34;</span>, <span style="color:#e6db74">&#34;TIP&#34;</span>],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;PERF&#34;</span>: [<span style="color:#e6db74">&#34;OPTIM&#34;</span>, <span style="color:#e6db74">&#34;PERFORMANCE&#34;</span>, <span style="color:#e6db74">&#34;OPTIMIZE&#34;</span>],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;TEST&#34;</span>: [<span style="color:#e6db74">&#34;TESTING&#34;</span>]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></li>
</ul>
<h3 id="better-comments-next">Better Comments Next</h3>
<p>[Better Comments Next][better-commments-next] required a bit more configuration. Just like with
<a href="/posts/working-with-todo-comments/#todo-tree">Todo Tree</a>, I needed to add a section to the configuration.</p>
<ul>
<li>
<p><em>better-comments.tags</em>: a list of objects that configure the styles of a tag</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#e6db74">&#34;better-comments.tags&#34;</span><span style="color:#960050;background-color:#1e0010">:</span> [
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;tag&#34;</span>: [<span style="color:#e6db74">&#34;todo&#34;</span>, <span style="color:#e6db74">&#34;to-do&#34;</span>, <span style="color:#e6db74">&#34;[ ]&#34;</span>, <span style="color:#e6db74">&#34;[X]&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#2563EB&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;#39579748&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;multiline&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;tag&#34;</span>: [<span style="color:#e6db74">&#34;note&#34;</span>, <span style="color:#e6db74">&#34;info&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#14D1F3FF&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;#18879B61&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;multiline&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    <span style="color:#960050;background-color:#1e0010">...</span>
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div></li>
</ul>
<h3 id="vs-code-and-vs-codium-example">VS Code and VS Codium example</h3>
<p>Here&rsquo;s a complete example showing the current configuration I use in VS Condium. For a breakdown on the extensions
that I&rsquo;m using take a look at <a href="/posts/working-with-todo-comments/#vs-code-and-vs-codium">VS Code and VS Codium</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;workbench.iconTheme&#34;</span>: <span style="color:#e6db74">&#34;material-icon-theme&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;workbench.sideBar.location&#34;</span>: <span style="color:#e6db74">&#34;right&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;editor.minimap.enabled&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;editor.fontSize&#34;</span>: <span style="color:#ae81ff">18</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;better-comments.tags&#34;</span>: [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: <span style="color:#e6db74">&#34;#&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#18b566&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;transparent&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: <span style="color:#e6db74">&#34;!&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#FF2D00&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;transparent&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: <span style="color:#e6db74">&#34;?&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#3498DB&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;transparent&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: <span style="color:#e6db74">&#34;//&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#474747&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;transparent&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: [<span style="color:#e6db74">&#34;todo&#34;</span>, <span style="color:#e6db74">&#34;to-do&#34;</span>, <span style="color:#e6db74">&#34;[ ]&#34;</span>, <span style="color:#e6db74">&#34;[X]&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#2563EB&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;#39579748&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;multiline&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: [<span style="color:#e6db74">&#34;note&#34;</span>, <span style="color:#e6db74">&#34;info&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#14D1F3FF&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;#18879B61&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;multiline&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: <span style="color:#e6db74">&#34;*&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#98C379&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;transparent&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: [<span style="color:#e6db74">&#34;hack&#34;</span>, <span style="color:#e6db74">&#34;important&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#9B59B6&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;#9C59B62B&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;multiline&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: [<span style="color:#e6db74">&#34;bug&#34;</span>, <span style="color:#e6db74">&#34;fixme&#34;</span>, <span style="color:#e6db74">&#34;fix-me&#34;</span>, <span style="color:#e6db74">&#34;fix&#34;</span>, <span style="color:#e6db74">&#34;fixit&#34;</span>, <span style="color:#e6db74">&#34;fix-it&#34;</span>, <span style="color:#e6db74">&#34;issue&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#DC2626&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;#B95E5E47&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;multiline&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: [<span style="color:#e6db74">&#34;perf&#34;</span>, <span style="color:#e6db74">&#34;optim&#34;</span>, <span style="color:#e6db74">&#34;performance&#34;</span>, <span style="color:#e6db74">&#34;optimize&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#FD79A8&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;#FD79A731&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;multiline&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: [<span style="color:#e6db74">&#34;warn&#34;</span>, <span style="color:#e6db74">&#34;warning&#34;</span>, <span style="color:#e6db74">&#34;wat&#34;</span>, <span style="color:#e6db74">&#34;xxx&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#FBBF24&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;#90773860&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;multiline&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;tag&#34;</span>: [<span style="color:#e6db74">&#34;test&#34;</span>, <span style="color:#e6db74">&#34;testing&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;color&#34;</span>: <span style="color:#e6db74">&#34;#FF00FF&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;strikethrough&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;underline&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;backgroundColor&#34;</span>: <span style="color:#e6db74">&#34;#983B9871&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;bold&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;italic&#34;</span>: <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;multiline&#34;</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;todo-tree.general.tags&#34;</span>: [
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;BUG&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;HACK&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;FIX&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;FIXIT&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;FIX-IT&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;FIXME&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;FIX-ME&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;IMPORTANT&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;INFO&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;ISSUE&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;NOTE&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;PERF&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;OPTIM&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;PERFORMANCE&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;OPTIMIZE&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;TEST&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;TESTING&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;TIP&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;TODO&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;TO-DO&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;WARN&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;WARNING&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;WAT&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;XXX&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;[ ]&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;[x]&#34;</span>
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;todo-tree.general.tagGroups&#34;</span>: {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;INFO&#34;</span>: [<span style="color:#e6db74">&#34;NOTE&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;TODO&#34;</span>: [<span style="color:#e6db74">&#34;TO-DO&#34;</span>, <span style="color:#e6db74">&#34;[ ]&#34;</span>, <span style="color:#e6db74">&#34;[X]&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;BUG&#34;</span>: [<span style="color:#e6db74">&#34;FIX&#34;</span>, <span style="color:#e6db74">&#34;FIXIT&#34;</span>, <span style="color:#e6db74">&#34;FIX-IT&#34;</span>, <span style="color:#e6db74">&#34;FIXME&#34;</span>, <span style="color:#e6db74">&#34;FIX-ME&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;WARN&#34;</span>: [<span style="color:#e6db74">&#34;WARNING&#34;</span>, <span style="color:#e6db74">&#34;WAT&#34;</span>, <span style="color:#e6db74">&#34;XXX&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;HACK&#34;</span>: [<span style="color:#e6db74">&#34;IMPORTANT&#34;</span>, <span style="color:#e6db74">&#34;TIP&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;PERF&#34;</span>: [<span style="color:#e6db74">&#34;OPTIM&#34;</span>, <span style="color:#e6db74">&#34;PERFORMANCE&#34;</span>, <span style="color:#e6db74">&#34;OPTIMIZE&#34;</span>],
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;TEST&#34;</span>: [<span style="color:#e6db74">&#34;TESTING&#34;</span>]
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content>
        </item>
        
        <item>
            <title>TIL: Celery and the --app argument</title>
            <link>https://froi.dev/posts/til-celery-and-the-app-argument/</link>
            <pubDate>Sun, 22 Sep 2024 18:47:00 -0400</pubDate>
            
            <guid>https://froi.dev/posts/til-celery-and-the-app-argument/</guid>
            <description>&lt;h2 id=&#34;tldr&#34;&gt;TLDR&lt;/h2&gt;
&lt;p&gt;Starting a Celery worker with &lt;code&gt;celery -A jobs worker -l INFO&lt;/code&gt; will look for&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;app&lt;/strong&gt; or &lt;strong&gt;celery&lt;/strong&gt; attribute in &lt;em&gt;jobs&lt;/em&gt;: &lt;code&gt;jobs:app&lt;/code&gt; or &lt;code&gt;jobs:celery&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;celery submodule&lt;/strong&gt; with an &lt;strong&gt;app&lt;/strong&gt; or &lt;strong&gt;celery&lt;/strong&gt; attribute: &lt;code&gt;jobs.celery:app&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you aren&amp;rsquo;t following these patterns you need to specify where the Celery app is. For a &lt;em&gt;jobs&lt;/em&gt; package with a &lt;em&gt;tasks
submodule&lt;/em&gt; and a Celery app declared as &lt;em&gt;celery_app&lt;/em&gt; the command should be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;celery --app jobs.tasks:celery_app worker -l INFO
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;Not using a piece of tech for a while can present relearning headaches that make you ask youself &amp;ldquo;why didn&amp;rsquo;t I just
write this down somewhere the first time?&amp;rdquo;. That&amp;rsquo;s what this TIL is.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="tldr">TLDR</h2>
<p>Starting a Celery worker with <code>celery -A jobs worker -l INFO</code> will look for</p>
<ul>
<li>An <strong>app</strong> or <strong>celery</strong> attribute in <em>jobs</em>: <code>jobs:app</code> or <code>jobs:celery</code></li>
<li>A <strong>celery submodule</strong> with an <strong>app</strong> or <strong>celery</strong> attribute: <code>jobs.celery:app</code></li>
</ul>
<p>If you aren&rsquo;t following these patterns you need to specify where the Celery app is. For a <em>jobs</em> package with a <em>tasks
submodule</em> and a Celery app declared as <em>celery_app</em> the command should be:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>celery --app jobs.tasks:celery_app worker -l INFO
</span></span></code></pre></div><hr>
<p>Not using a piece of tech for a while can present relearning headaches that make you ask youself &ldquo;why didn&rsquo;t I just
write this down somewhere the first time?&rdquo;. That&rsquo;s what this TIL is.</p>
<p>Before we start though, <a href="https://docs.celeryq.dev/en/stable/index.html">Celery</a> is a distributed task queue system
written in Python. It can be compared to other queue systems like</p>
<ul>
<li><a href="https://sidekiq.org/">Sidekiq</a> for Ruby</li>
<li><a href="https://github.com/OptimalBits/bull">Bull</a> for Node</li>
<li><a href="https://riverqueue.com/">River Queue</a> for Go</li>
</ul>
<h2 id="some-background-and-the-issue">Some background and the issue</h2>
<p>Throughout the documentation you&rsquo;ll find that starting a Celery working is a simple as executing</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>celery -A tasks worker --loglevel INFO
</span></span></code></pre></div><p>When strictly following the getting started you should have no problems and thing will work as expected. Beyond this
simple use though you will want to understand hwo the <code>-A</code> or <code>--app</code> works. Especially when adding a Celery application
to a new package in an existing project.</p>
<p>Since I&rsquo;m refreshing my Celery knowledge after years of not using it, I decided to keep it simple and as close to what
is found in the Celery documentation. The only difference was that I needed to call the Celery task from a FastAPI
endpoint.</p>
<p>I&rsquo;m starting off with this project layout (very similar to what you see in the <a href="https://docs.celeryq.dev/en/stable/getting-started/next-steps.html#our-project">docs</a>)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>❯ tree src/jobs
</span></span><span style="display:flex;"><span>src/jobs
</span></span><span style="display:flex;"><span>├── __init__.py
</span></span><span style="display:flex;"><span>├── steps.py
</span></span><span style="display:flex;"><span>└── tasks.py
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span> directory, <span style="color:#ae81ff">3</span> files
</span></span></code></pre></div><p>The tasks.py file is where I&rsquo;m configuring my Clery app and where I&rsquo;m also defining my initial task <code>send_data</code>.
<code>steps.py</code> is currently empty.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-py" data-lang="py"><span style="display:flex;"><span><span style="color:#f92672">from</span> celery <span style="color:#f92672">import</span> Celery
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> app.config <span style="color:#f92672">import</span> config
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># from .steps import get_usage_spans</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>celery_app <span style="color:#f92672">=</span> Celery(<span style="color:#e6db74">&#34;jobs&#34;</span>, broker<span style="color:#f92672">=</span>config<span style="color:#f92672">.</span>REDIS_URI)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@celery_app.task</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">send_data</span>(data: dict[str, Any]):
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">...</span><span style="color:#960050;background-color:#1e0010"></span>   <span style="color:#ae81ff">2</span>   <span style="color:#960050;background-color:#1e0010">```</span>sh
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Send data request received: &#34;</span>
</span></span></code></pre></div><p>Starting my worker presented no issues, but the tasks was called during a request sent to the API I got this error
message:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#f92672">[</span>2024-09-22 18:14:45,756: ERROR/MainProcess<span style="color:#f92672">]</span> Received unregistered task of type <span style="color:#e6db74">&#39;jobs.tasks.send_data&#39;</span>.
</span></span><span style="display:flex;"><span>The message has been ignored and discarded.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Did you remember to import the module containing this task?
</span></span><span style="display:flex;"><span>Or maybe you<span style="color:#e6db74">&#39;re using relative imports?
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Please see
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">https://docs.celeryq.dev/en/latest/internals/protocol.html
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">for more information.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">The full contents of the message body was:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">b&#39;</span><span style="color:#f92672">[[</span><span style="color:#e6db74">&#34;field1&#34;</span>, <span style="color:#e6db74">&#34;field2&#34;</span>, <span style="color:#e6db74">&#34;field3&#34;</span>, <span style="color:#e6db74">&#34;field4&#34;</span><span style="color:#f92672">]</span>, <span style="color:#f92672">{}</span>, <span style="color:#f92672">{</span><span style="color:#e6db74">&#34;callbacks&#34;</span>: null, <span style="color:#e6db74">&#34;errbacks&#34;</span>: null, <span style="color:#e6db74">&#34;chain&#34;</span>: null, <span style="color:#e6db74">&#34;chord&#34;</span>: null<span style="color:#f92672">}]</span><span style="color:#e6db74">&#39; (123b)
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">The full contents of the message headers:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{&#39;</span>lang<span style="color:#e6db74">&#39;: &#39;</span>py<span style="color:#e6db74">&#39;, &#39;</span>task<span style="color:#e6db74">&#39;: &#39;</span>jobs.tasks.send_data<span style="color:#e6db74">&#39;, &#39;</span>id<span style="color:#e6db74">&#39;: &#39;</span>b301e3bc-9ab9-48f6-b4c9-3158e1437a85<span style="color:#e6db74">&#39;, &#39;</span>shadow<span style="color:#e6db74">&#39;: None, &#39;</span>eta<span style="color:#e6db74">&#39;: None, &#39;</span>expires<span style="color:#e6db74">&#39;: None, &#39;</span>group<span style="color:#e6db74">&#39;: None, &#39;</span>group_index<span style="color:#e6db74">&#39;: None, &#39;</span>retries<span style="color:#e6db74">&#39;: 0, &#39;</span>timelimit<span style="color:#e6db74">&#39;: [None, None], &#39;</span>root_id<span style="color:#e6db74">&#39;: &#39;</span>b301e3bc-9ab9-48f6-b4c9-3158e1437a85<span style="color:#e6db74">&#39;, &#39;</span>parent_id<span style="color:#e6db74">&#39;: None, &#39;</span>argsrepr<span style="color:#e6db74">&#39;: &#34;(&#39;</span>tenant<span style="color:#e6db74">&#39;, &#39;</span>account<span style="color:#e6db74">&#39;, &#39;</span>service_point<span style="color:#e6db74">&#39;, &#39;</span>device<span style="color:#e6db74">&#39;)&#34;, &#39;</span>kwargsrepr<span style="color:#e6db74">&#39;: &#39;</span><span style="color:#f92672">{}</span><span style="color:#e6db74">&#39;, &#39;</span>origin<span style="color:#e6db74">&#39;: &#39;</span>gen95044@froi.local<span style="color:#e6db74">&#39;, &#39;</span>ignore_result<span style="color:#e6db74">&#39;: False, &#39;</span>replaced_task_nesting<span style="color:#e6db74">&#39;: 0, &#39;</span>stamped_headers<span style="color:#e6db74">&#39;: None, &#39;</span>stamps<span style="color:#e6db74">&#39;: {}}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">The delivery info for this task is:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{&#39;</span>exchange<span style="color:#e6db74">&#39;: &#39;&#39;, &#39;</span>routing_key<span style="color:#e6db74">&#39;: &#39;</span>celery<span style="color:#e6db74">&#39;}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Traceback (most recent call last):
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  File &#34;/Users/froi/Library/Caches/pypoetry/virtualenvs/data-integrations-iehcu-zB-py3.11/lib/python3.11/site-packages/celery/worker/consumer/consumer.py&#34;, line 659, in on_task_received
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    strategy = strategies[type_]
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">               ~~~~~~~~~~^^^^^^^
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">KeyError: &#39;</span>jobs.tasks.send_data<span style="color:#960050;background-color:#1e0010">&#39;</span>
</span></span></code></pre></div><p>Thus the moral of this story.</p>
<h2 id="the-app-argument">The &ndash;app argument</h2>
<p>Starting a worker is simple</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>celery -A workers worker -l INFO
</span></span></code></pre></div><p>The -A or &ndash;app is used to specify the Celery application instance to use. What I didn&rsquo;t remember was that this follows
a module.path:attribute pattern. I also didn&rsquo;t remember the defaults it follows.</p>
<p>I was starting my workers with</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>celery -A jobs worker -l INFO
</span></span></code></pre></div><p>This meant that Celery will look for the configured application by</p>
<ol>
<li>Look for an <strong>app</strong> or <strong>celery</strong> attribute in a jobs module, the equivalent of writting it as <code>celery -A jobs:app worker -l INFO</code></li>
<li>Or by looking for and <strong>app</strong> or <strong>celery</strong> attribute in a <strong>celery submodule</strong> in the <em>jobs</em> package, the equivalent
of writting it as <code>celery -A jobs.celery:app worker -l INFO</code></li>
</ol>
<p>Since didn&rsquo;t declare any of my resources in this way I needed to start my worker with</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>celery -A jobs.tasks:celery_app worker -l INFO
</span></span></code></pre></div><p>Once I finally understood this again, like magic, my code worked. Hope this helps somebody not have to scream at their
monitor.</p>
]]></content>
        </item>
        
        <item>
            <title>TIL: NVIM quick fix list and cdo</title>
            <link>https://froi.dev/posts/til-nvim-quick-fix-list-and-cdo/</link>
            <pubDate>Tue, 13 Feb 2024 23:47:21 +0000</pubDate>
            
            <guid>https://froi.dev/posts/til-nvim-quick-fix-list-and-cdo/</guid>
            <description>&lt;p&gt;De todas las cosas que he tenido que aprender al cambiar mi editor de VS Code
a NVim, el hacer &amp;ldquo;search and replace&amp;rdquo; atravez de multiples archivos ha sido
lo que mas productivo me ha hecho. Hoy por fin me hizo &amp;ldquo;click&amp;rdquo; al entender
lo que son Quickfix list, el comando de cdo y como utilizarlos con
Telescope.&lt;/p&gt;
&lt;p&gt;Utilizando Telescope, busca el texto que se quiere cambiar, en este ejemplo voy a buscar &lt;em&gt;buen&lt;/em&gt;:&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>De todas las cosas que he tenido que aprender al cambiar mi editor de VS Code
a NVim, el hacer &ldquo;search and replace&rdquo; atravez de multiples archivos ha sido
lo que mas productivo me ha hecho. Hoy por fin me hizo &ldquo;click&rdquo; al entender
lo que son Quickfix list, el comando de cdo y como utilizarlos con
Telescope.</p>
<p>Utilizando Telescope, busca el texto que se quiere cambiar, en este ejemplo voy a buscar <em>buen</em>:</p>
<figure><img src="https://froidotdev.nyc3.cdn.digitaloceanspaces.com/images/telescope-search.gif">
</figure>

<p>Cuando obtengas el listado de la busqueda en Telescope, abre el &ldquo;quickfix list&rdquo; utilizando C-Q (combinación por defecto):</p>
<figure><img src="https://froidotdev.nyc3.cdn.digitaloceanspaces.com/images/nvim-quickfix-list.gif">
</figure>

<p>Ahora utilizando el comando <em><strong>cdo</strong></em> junto a <em><strong>update</strong></em> se puede cambiar todas las instancias a
la vez y resguardar los cambios</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span>:<span style="color:#a6e22e">cdo</span> <span style="color:#a6e22e">s</span><span style="color:#e6db74">/texto_para_cambiar/</span><span style="color:#a6e22e">texto_nuevo</span>/ | <span style="color:#a6e22e">update</span>
</span></span></code></pre></div><p>Si no quieres resguardar los archivos automaticamente, elimina el comando de <em><strong>update</strong></em></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span>:<span style="color:#a6e22e">cdo</span> <span style="color:#a6e22e">s</span><span style="color:#e6db74">/texto_para_cambiar/</span><span style="color:#a6e22e">texto_nuevo</span>/
</span></span></code></pre></div><figure><img src="https://froidotdev.nyc3.cdn.digitaloceanspaces.com/images/quickfix-list-update.gif">
</figure>

<p>Con esto una funcionalidad que me faltaba de editores como VS Code esta
cubierta.</p>
]]></content>
        </item>
        
        <item>
            <title>Migrando Froidotdev Pt 1</title>
            <link>https://froi.dev/posts/migrando-froi/</link>
            <pubDate>Tue, 04 Jul 2023 21:59:21 +0000</pubDate>
            
            <guid>https://froi.dev/posts/migrando-froi/</guid>
            <description>&lt;p&gt;La entrada anterior escribí sobre mover mi blog. En los días después me senté a darle un poco de casco. Esta no es la primera vez que hago esto en los pasados años y quiero algo que no me haga decir &amp;ldquo;meh&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Esta serie de posts van a ser tipo &lt;em&gt;dev log&lt;/em&gt; para ir documentando lo que hago e ir creando costumbre.&lt;/p&gt;
&lt;p&gt;La pregunta entonces es &lt;em&gt;¿Qué quiero?&lt;/em&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://froi.dev/posts/migrando-froi/images/que-quiero.png&#34;&gt;
&lt;/figure&gt;

&lt;ul&gt;
&lt;li&gt;Una estructura sencilla&lt;/li&gt;
&lt;li&gt;Un enfoque en el blog&lt;/li&gt;
&lt;li&gt;Algo que escriba el HTML por mi&lt;/li&gt;
&lt;li&gt;Contenido en Markdown (text is king)&lt;/li&gt;
&lt;li&gt;Portátil y estático (cero base de datos)&lt;/li&gt;
&lt;li&gt;Fácil de hacer &amp;ldquo;deployment&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Bajo costo&lt;/li&gt;
&lt;li&gt;Extendible&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Con estos criterios y el hecho que estoy tirándome a aprender Go, decidí usa &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>La entrada anterior escribí sobre mover mi blog. En los días después me senté a darle un poco de casco. Esta no es la primera vez que hago esto en los pasados años y quiero algo que no me haga decir &ldquo;meh&rdquo;.</p>
<p>Esta serie de posts van a ser tipo <em>dev log</em> para ir documentando lo que hago e ir creando costumbre.</p>
<p>La pregunta entonces es <em>¿Qué quiero?</em>.</p>
<figure><img src="/posts/migrando-froi/images/que-quiero.png">
</figure>

<ul>
<li>Una estructura sencilla</li>
<li>Un enfoque en el blog</li>
<li>Algo que escriba el HTML por mi</li>
<li>Contenido en Markdown (text is king)</li>
<li>Portátil y estático (cero base de datos)</li>
<li>Fácil de hacer &ldquo;deployment&rdquo;</li>
<li>Bajo costo</li>
<li>Extendible</li>
</ul>
<p>Con estos criterios y el hecho que estoy tirándome a aprender Go, decidí usa <a href="https://gohugo.io">Hugo</a>.</p>
<h2 id="hosting">Hosting</h2>
<p>Ahora el tema de portabilidad y costo. Por ahora estoy entre <a href="https://digitalocean.com">Digital Ocean</a> y <a href="https://pages.github.com/">GitHub Pages</a>. Estoy moviendo mucho de lo que hago de otros clouds a Digital Ocean, incluyendo manejo del DNS de froi.dev y una instancia de <a href="https://beluga.froi.dev/index.html">Beluga</a>1, esto lo hace conveniente. GitHub Pages es la opción más sencilla, el contenido ya va a estar en un repositorio en GitHub, publicar aquí dejaría todo en un solo lugar.</p>
<p>Probaré con ambos y veré cual me gusta más, pero comenzaré con GitHub Pages ya que es algo que conozco más. Para esta prueba usare <em>gh-tmp.froi.dev</em> para no romper lo que ya esta corriendo.</p>
<hr>
<ol>
<li><a href="https://beluga.social">Beluga</a> por <a href="https://gcollazo.com">Giovanni Collazo</a></li>
</ol>
]]></content>
        </item>
        
        <item>
            <title>Cambios al blog por el &#34;meltdown&#34; del internet</title>
            <link>https://froi.dev/posts/cambios-al-blog-por-el-meltdown-del-internet/</link>
            <pubDate>Sun, 02 Jul 2023 22:19:14 +0000</pubDate>
            
            <guid>https://froi.dev/posts/cambios-al-blog-por-el-meltdown-del-internet/</guid>
            <description>&lt;p&gt;Recientemente vi un &lt;a href=&#34;https://mastodon.social/@mcc/110633589938836938&#34;&gt;toot en Mastodon&lt;/a&gt; con el texto &amp;ldquo;Entire Internet is dying at once&amp;rdquo; y me hizo pensar sobre todo lo que en este año a cambiado para que varias personas se sientan así. Los cambios en Twitter, la llegada de LLMs como ChatGPT, el cambio con el API de Reddit, la hegemonía de YouTube sobre el contenido que vemos, todo esto atribuye al sentir de destrucción de &amp;ldquo;verdades&amp;rdquo; que creíamos era evidentes.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Recientemente vi un <a href="https://mastodon.social/@mcc/110633589938836938">toot en Mastodon</a> con el texto &ldquo;Entire Internet is dying at once&rdquo; y me hizo pensar sobre todo lo que en este año a cambiado para que varias personas se sientan así. Los cambios en Twitter, la llegada de LLMs como ChatGPT, el cambio con el API de Reddit, la hegemonía de YouTube sobre el contenido que vemos, todo esto atribuye al sentir de destrucción de &ldquo;verdades&rdquo; que creíamos era evidentes.</p>
<p>Como muchos, yo tengo mis opiniones sobre todo esto, pero lo que realmente me volvió a traer a la mente fue &ldquo;yo debo de controlar más donde vive mi contenido y que contenido consumo&rdquo;.</p>
<p>Este blog vive en la plataforma <a href="https://ghost.org/">Ghost</a>. Aunque es un servicio excelente, quiero moverme a algo mas sencillo, algo que yo controle, algo más portable.</p>
<p>Lo que quiero es una serie de archivos de texto que se puedan leer por el internet.</p>
<p>Estaré moviendo todo este contenido a un hogar nuevo y a comenzar a utilizar <a href="https://gohugo.io/">Hugo</a> como generador del contenido. Quiero además expandir <em>froi.dev</em> a ser algo mas que un blog. Estaré cambiando el formato, la estructura y el diseño a algo mas sencillo.</p>
<p>Las próximas entradas serán sobre el proceso y la experiencia.</p>
]]></content>
        </item>
        
        <item>
            <title>Clang, MacOS y Python</title>
            <link>https://froi.dev/posts/clang-macos-y-python/</link>
            <pubDate>Fri, 05 May 2023 00:49:28 +0000</pubDate>
            
            <guid>https://froi.dev/posts/clang-macos-y-python/</guid>
            <description>&lt;p&gt;En los últimos meses he tenido problemas instalando paquetes de Python que necesitan algún tipo de compilación de C/C++. En mi caso, los paquetes que estaba intentando instalar como dependencias eran&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;apache-beam&lt;/li&gt;
&lt;li&gt;grpcio&lt;/li&gt;
&lt;li&gt;grpcio-tools&lt;/li&gt;
&lt;li&gt;protoc&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cada vez que intentaba instalar estos paquetes me encontraba con un el siguiente error de compilación&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;error: no member named &#39;nullptr_t&#39; in the global namespace
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Presiona &lt;a href=&#34;https://gist.github.com/froi/ebb80848d6baf9c8002a69ee42586867&#34;&gt;aquí&lt;/a&gt; si quieres ver el log en su totalidad.&lt;/em&gt;&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>En los últimos meses he tenido problemas instalando paquetes de Python que necesitan algún tipo de compilación de C/C++. En mi caso, los paquetes que estaba intentando instalar como dependencias eran</p>
<ul>
<li>apache-beam</li>
<li>grpcio</li>
<li>grpcio-tools</li>
<li>protoc</li>
</ul>
<p>Cada vez que intentaba instalar estos paquetes me encontraba con un el siguiente error de compilación</p>
<pre><code>error: no member named 'nullptr_t' in the global namespace
</code></pre>
<p><em>Presiona <a href="https://gist.github.com/froi/ebb80848d6baf9c8002a69ee42586867">aquí</a> si quieres ver el log en su totalidad.</em></p>
<p>Esto solo sucedía utilizando MacOS, que en mi caso estaba en version Ventura 13.3.1.</p>
<p>Después de una buena búsqueda y lectura de issues en GitHub, encontré que el problema estaba con la version del SKD de MacOS y clang.</p>
<p>Aparenta que en un cambio de versiones de varias librerías fueron movidas o eliminadas. Esto aparenta no ser el caso en versiones de Debian o Ubuntu Linux ya que la misma compilación funcionaba al correrla en un contenedor de Docker.</p>
<h2 id="versiones-con-problemas">Versiones con problemas</h2>
<p>Las versiones que estaban causando problemas para mi fueron</p>
<ul>
<li>Apple clang version 14.0.0 (clang-1400.0.29.202)</li>
<li>Xcode 14.1</li>
<li>Python 3.8 a 3.10</li>
</ul>
<p>La solución esta en actualizar Xcode a la versión mas reciente, <em>version 14.3 (14E222b)</em> al escribir este post. Esta actualización a la vez actualiza la version de Clang a <em>Apple clang version 14.0.3 (clang-1403.0.22.14.1)</em>.</p>
<p>Espero que esto ayude a alguien que este buscando solución en vano.</p>
]]></content>
        </item>
        
        <item>
            <title>Books, Blogs, Courses, and Vids</title>
            <link>https://froi.dev/posts/books-blogs-courses-and-vids/</link>
            <pubDate>Wed, 03 May 2023 04:11:18 +0000</pubDate>
            
            <guid>https://froi.dev/posts/books-blogs-courses-and-vids/</guid>
            <description>&lt;p&gt;Over the last two years I&amp;rsquo;ve been asked for resources I would recommend for software engineers starting their career. After writing this list out a couple of times and feeling a bit silly for doing it, I finally took the time to write this up as a post.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s my attempt in keeping a list of resources, many of which are Python focused &amp;hellip; at least for now.&lt;/p&gt;
&lt;h2 id=&#34;books&#34;&gt;Books&lt;/h2&gt;
&lt;p&gt;By far my favorite medium to learn. Over the years I&amp;rsquo;ve gravitated more towards books about the craft of software engineering over books on a specific technology. That said, I&amp;rsquo;ve been very happy with the O&amp;rsquo;Reilly learning platform, what used to be Safari Books Online. I&amp;rsquo;ve used this platform to follow learning path on specific technologies like Go, Kubernetes, and data engineering.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Over the last two years I&rsquo;ve been asked for resources I would recommend for software engineers starting their career. After writing this list out a couple of times and feeling a bit silly for doing it, I finally took the time to write this up as a post.</p>
<p>Here&rsquo;s my attempt in keeping a list of resources, many of which are Python focused &hellip; at least for now.</p>
<h2 id="books">Books</h2>
<p>By far my favorite medium to learn. Over the years I&rsquo;ve gravitated more towards books about the craft of software engineering over books on a specific technology. That said, I&rsquo;ve been very happy with the O&rsquo;Reilly learning platform, what used to be Safari Books Online. I&rsquo;ve used this platform to follow learning path on specific technologies like Go, Kubernetes, and data engineering.</p>
<h3 id="for-beginners">For beginners</h3>
<ul>
<li><a href="https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/">The Pragmatic Programmer, 20th Anniversary Edition</a></li>
<li><a href="https://realpython.com/products/python-basics-book/">Python Basics: A practical introduction to Python 3</a></li>
<li><a href="https://greenteapress.com/wp/think-python-2e/">Think Python second edition</a>: While this book has been out for a number of years, I would be remiss to not mention it. Fortunately this book is available under the Creative Commons Attribution-NonCommercial 3.0 Unported License. If you do read it and it helps, be sure to show your support 😉</li>
</ul>
<h3 id="intermediate-to-advanced">Intermediate to advanced</h3>
<ul>
<li><a href="https://www.oreilly.com/library/view/fluent-python-2nd/9781492056348/">Fluent Python, 2nd Edition</a></li>
<li><a href="https://www.oreilly.com/library/view/modern-software-engineering/9780137314942/">Modern Software Engineering: Doing What Works to Build Better Software Faster</a></li>
<li><a href="https://www.oreilly.com/library/view/building-microservices-2nd/9781492034018/">Building Microservices, 2nd Edition</a></li>
<li><a href="https://www.oreilly.com/library/view/domain-driven-design-tackling/0321125215/">Domain-Driven Design: Tackling Complexity in the Heart of Software</a></li>
<li><a href="https://www.oreilly.com/library/view/design-patterns-for/9781492090700/">Design Patterns for Cloud Native Applications</a></li>
</ul>
<h2 id="websites-and-blogs">Websites and blogs</h2>
<p>There are a ton of excellent websites with a universe of content. These are just a few that I find helpful and enjoyable.</p>
<ul>
<li><a href="https://realpython.com/">Real Python</a>: Some really great Python specific resources in the form of blog posts, tutorials, and paid courses.</li>
<li><a href="https://www.blog.pythonlibrary.org/">Mouse vs Python</a>: solid Python focused blog posts</li>
<li><a href="https://bytebytego.com">ByteByteGo</a>: great general computing topics. They&rsquo;re short and straight to the point. I tend to look for their content a lot.</li>
<li><a href="https://training.talkpython.fm/">Talk Python Training</a>: I&rsquo;ve gone over some of the training materials here and I&rsquo;ve always enjoyed them. They always have package discounts that make them extremely worth it. You&rsquo;ll also support the Talk Python Podcast while you&rsquo;re at it.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<p>After books, this is my favorite way to consume tech topics and news. There&rsquo;s way to many excellent podcasts to mention here, but these are my recent go to list</p>
<ul>
<li><a href="https://realpython.com/podcasts/rpp/">Real Python Podcast</a></li>
<li><a href="https://talkpython.fm/">Talk Python to Me</a></li>
<li><a href="https://pythonbytes.fm/">PythonBytes</a></li>
<li><a href="https://gotopia.tech/podcast">goto;</a></li>
<li><a href="https://changelog.com/podcast">Changelog</a></li>
<li><a href="https://devinterrupted.com/podcasts/">Dev Interrupted</a></li>
</ul>
<h2 id="youtube">YouTube</h2>
<p>While YouTube content can be all over the place I find these to have great content and I consistently come back to them</p>
<ul>
<li><a href="https://www.youtube.com/c/ArjanCodes">ArjanCodes</a>: When it comes to Python content from a YouTube creator, you can&rsquo;t go wrong with Arjan. He produces great high quality content.</li>
<li><a href="https://www.youtube.com/c/Freecodecamp">freeCodeCamp</a>: talking about tutorials and courses on YouTube without mentioning the <em>OGs</em> would be sacrilege. The amount of content can be overwhelming but a good search is well worth it.</li>
<li><a href="https://www.youtube.com/c/ByteByteGo">ByteByteGo</a>: This is the accompanying YouTube channel to the <a href="https://bytebytego.com">ByteByteGo</a> and newsletter. They have some amazing explainer videos on some complicated subjects.</li>
<li><a href="https://www.youtube.com/@PyConUS">Pycon US</a>: When it comes to Python conferences you can&rsquo;t go wrong with the original. PyCon US has a world of talks from beginner to advanced topics.</li>
<li><a href="https://www.youtube.com/c/GotoConferences">goto; Conferences</a>: This channel is more of a general tech channel about the craft and business of software development. Their videos range from conference talks to book clubs.</li>
</ul>
<h2 id="learning-platforms">Learning platforms</h2>
<p>There are many learning platforms out there. While many are excellent I keep going back to and enjoying <a href="https://www.oreilly.com/">O&rsquo;Reilly.com</a>. This platform is what used to be Safari Books Online. They&rsquo;ve expanded from just offering a book subscription to providing learning paths that take from their extensive catalog of books, videos, courses, and talks. I&rsquo;ve found that the subscription, while not the cheapest, is worth the value I get from it.</p>
<hr>
<p>And there we are. There are definitely some excellent resources that I&rsquo;m missing with this list. This is not meant to be an extensive list but a good starting point for software developers that are starting their career or are looking for resources to enhance their journey in this craft.</p>
]]></content>
        </item>
        
        <item>
            <title>Reading List</title>
            <link>https://froi.dev/posts/reading-list/</link>
            <pubDate>Thu, 06 Jan 2022 06:15:20 +0000</pubDate>
            
            <guid>https://froi.dev/posts/reading-list/</guid>
            <description>&lt;p&gt;Una lista de los blogs que frecuento leer. Gracias &lt;a href=&#34;https://gcollazo.com&#34;&gt;Giovanni Collazo&lt;/a&gt; por la &lt;a href=&#34;https://gcollazo.com/blogroll/&#34;&gt;idea&lt;/a&gt; y la &lt;a href=&#34;https://opml-to-html.glitch.me/&#34;&gt;herramienta&lt;/a&gt; para hacer esto.&lt;/p&gt;
&lt;h2 id=&#34;companies&#34;&gt;Companies&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a href=&#34;https://medium.com/feed/airbnb-engineering&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://medium.com/airbnb-engineering?source=rss----53c7c27702d5---4&#34;&gt;AirBnB Engineering &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://medium.com/feed/brexeng&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://medium.com/brexeng?source=rss----a476509afa8d---4&#34;&gt;Brex Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://circleci.com/blog/feed.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://circleci.com/blog/&#34;&gt;CircleCI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://blog.cloudflare.com/rss/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://blog.cloudflare.com/&#34;&gt;Cloudflare Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://medium.com/feed/discord-engineering/tagged/engineering&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://blog.discord.com/tagged/engineering?source=rss----cb96a1f03649--engineering&#34;&gt;Discord Engineering &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://engineering.fb.com/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://engineering.fb.com/&#34;&gt;Facebook Engineering &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://cloudblog.withgoogle.com/products/gcp/rss/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://cloud.google.com/blog/products/gcp/&#34;&gt;GCP Blog &amp;amp; Announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://github.blog/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://github.blog/&#34;&gt;GitHub Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://engineering.linkedin.com/blog.rss.html&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://engineering.linkedin.com/blog.rss.html&#34;&gt;LinkedIn Engineering &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://eng.lyft.com/feed&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://eng.lyft.com?source=rss----25cd379abb8---4/&#34;&gt;Lyft Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://blog.mozilla.org/en/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://blog.mozilla.org/en/&#34;&gt;Mozilla Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://hacks.mozilla.org/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://hacks.mozilla.org/&#34;&gt;Mozilla Hacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://netflixtechblog.com/feed&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://netflixtechblog.com?source=rss----2615bd06b42e---4/&#34;&gt;Netflix Tech Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://www.oreilly.com/radar/feed/index.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://www.oreilly.com/radar&#34;&gt;O&amp;rsquo;Reilly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://slack.engineering/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://slack.engineering/&#34;&gt;Slack Engineering &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://engineering.atspotify.com/feed&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://engineering.atspotify.com/&#34;&gt;Spotify Engineering &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://developer.squareup.com/blog/rss.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://developer.squareup.com/&#34;&gt;Square Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://eng.uber.com/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://eng.uber.com/&#34;&gt;Uber Engineering &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;development&#34;&gt;Development&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a href=&#34;https://golangcode.com/index.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://golangcode.com/&#34;&gt;Golang Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://cprss.s3.amazonaws.com/golangweekly.com.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://golangweekly.com/&#34;&gt;Golang Weekly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://www.blog.pythonlibrary.org/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://www.blog.pythonlibrary.org/&#34;&gt;Mouse vs Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://talkpython.fm/episodes/rss&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://talkpython.fm/&#34;&gt;Talk Python to Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://threedots.tech/index.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://threedots.tech/&#34;&gt;Three Dots&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;humans&#34;&gt;Humans&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a href=&#34;https://www.alexedwards.net/static/feed.rss&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://www.alexedwards.net/blog&#34;&gt;Alex Edwards&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://holub.com/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://holub.com/&#34;&gt;Allen Holub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://hoverbear.org/rss.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://hoverbear.org/&#34;&gt;Ana Hobden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://benhoyt.com/writings/rss.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://benhoyt.com/writings/&#34;&gt;Ben Hoyt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://notes.eatonphil.com/rss.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;http://notes.eatonphil.com/&#34;&gt;Eaton phil&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://blog.pragmaticengineer.com/rss/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://blog.pragmaticengineer.com/&#34;&gt;Gergely Orosz - The Pragmatic Programmer &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://gcollazo.com/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://gcollazo.com/&#34;&gt;Giovanni Collazo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://jacobian.org/index.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://jacobian.org/&#34;&gt;Jacob Kaplan-Moss&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://janbosch.com/blog/index.php/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://janbosch.com/blog&#34;&gt;Jan Bosch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://www.joelonsoftware.com/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://www.joelonsoftware.com/&#34;&gt;Joel on Software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://jpadilla.com/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://jpadilla.com/&#34;&gt;José A. Padilla&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://www.lpalmieri.com/rss.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://www.lpalmieri.com/&#34;&gt;Luca Palmieri&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://www.arp242.net/feed.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://www.arp242.net/&#34;&gt;Martin Tournoij&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;__GHOST_URL__/rss&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;__GHOST_URL__/&#34;&gt;Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://rickcarlino.com/rss/feed.rss&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://rickcarlino.com/&#34;&gt;Rick Carlino&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://swyx.io/rss.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://swyx.io/&#34;&gt;Shawn Wang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://simonwillison.net/atom/everything/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;http://simonwillison.net/&#34;&gt;Simon Willison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://tilkov.com/feed.atom&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://www.tilkov.com/&#34;&gt;Stefan Tilkov&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://ufried.com/blog/index.xml&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://ufried.com/blog/&#34;&gt;Uwe Friedrichsen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;of-interest&#34;&gt;Of Interest&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a href=&#34;https://daringfireball.net/feeds/main&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://daringfireball.net/&#34;&gt;Daring Fireball&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://feed.infoq.com/architecture-design/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://www.infoq.com/&#34;&gt;InfoQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://www.macstories.net/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://www.macstories.net/&#34;&gt;Mac Stories&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[&lt;a href=&#34;https://panic.com/blog/feed/&#34;&gt;RSS&lt;/a&gt;] &lt;a href=&#34;https://panic.com/blog&#34;&gt;Panic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
            <content type="html"><![CDATA[<p>Una lista de los blogs que frecuento leer. Gracias <a href="https://gcollazo.com">Giovanni Collazo</a> por la <a href="https://gcollazo.com/blogroll/">idea</a> y la <a href="https://opml-to-html.glitch.me/">herramienta</a> para hacer esto.</p>
<h2 id="companies">Companies</h2>
<ul>
<li>[<a href="https://medium.com/feed/airbnb-engineering">RSS</a>] <a href="https://medium.com/airbnb-engineering?source=rss----53c7c27702d5---4">AirBnB Engineering </a></li>
<li>[<a href="https://medium.com/feed/brexeng">RSS</a>] <a href="https://medium.com/brexeng?source=rss----a476509afa8d---4">Brex Blog</a></li>
<li>[<a href="https://circleci.com/blog/feed.xml">RSS</a>] <a href="https://circleci.com/blog/">CircleCI</a></li>
<li>[<a href="https://blog.cloudflare.com/rss/">RSS</a>] <a href="https://blog.cloudflare.com/">Cloudflare Blog</a></li>
<li>[<a href="https://medium.com/feed/discord-engineering/tagged/engineering">RSS</a>] <a href="https://blog.discord.com/tagged/engineering?source=rss----cb96a1f03649--engineering">Discord Engineering </a></li>
<li>[<a href="https://engineering.fb.com/feed/">RSS</a>] <a href="https://engineering.fb.com/">Facebook Engineering </a></li>
<li>[<a href="https://cloudblog.withgoogle.com/products/gcp/rss/">RSS</a>] <a href="https://cloud.google.com/blog/products/gcp/">GCP Blog &amp; Announcement</a></li>
<li>[<a href="https://github.blog/feed/">RSS</a>] <a href="https://github.blog/">GitHub Blog</a></li>
<li>[<a href="https://engineering.linkedin.com/blog.rss.html">RSS</a>] <a href="https://engineering.linkedin.com/blog.rss.html">LinkedIn Engineering </a></li>
<li>[<a href="https://eng.lyft.com/feed">RSS</a>] <a href="https://eng.lyft.com?source=rss----25cd379abb8---4/">Lyft Engineering</a></li>
<li>[<a href="https://blog.mozilla.org/en/feed/">RSS</a>] <a href="https://blog.mozilla.org/en/">Mozilla Blog</a></li>
<li>[<a href="https://hacks.mozilla.org/feed/">RSS</a>] <a href="https://hacks.mozilla.org/">Mozilla Hacks</a></li>
<li>[<a href="https://netflixtechblog.com/feed">RSS</a>] <a href="https://netflixtechblog.com?source=rss----2615bd06b42e---4/">Netflix Tech Blog</a></li>
<li>[<a href="https://www.oreilly.com/radar/feed/index.xml">RSS</a>] <a href="https://www.oreilly.com/radar">O&rsquo;Reilly</a></li>
<li>[<a href="https://slack.engineering/feed/">RSS</a>] <a href="https://slack.engineering/">Slack Engineering </a></li>
<li>[<a href="https://engineering.atspotify.com/feed">RSS</a>] <a href="https://engineering.atspotify.com/">Spotify Engineering </a></li>
<li>[<a href="https://developer.squareup.com/blog/rss.xml">RSS</a>] <a href="https://developer.squareup.com/">Square Engineering</a></li>
<li>[<a href="https://eng.uber.com/feed/">RSS</a>] <a href="https://eng.uber.com/">Uber Engineering </a></li>
</ul>
<h2 id="development">Development</h2>
<ul>
<li>[<a href="https://golangcode.com/index.xml">RSS</a>] <a href="https://golangcode.com/">Golang Code</a></li>
<li>[<a href="https://cprss.s3.amazonaws.com/golangweekly.com.xml">RSS</a>] <a href="https://golangweekly.com/">Golang Weekly</a></li>
<li>[<a href="https://www.blog.pythonlibrary.org/feed/">RSS</a>] <a href="https://www.blog.pythonlibrary.org/">Mouse vs Python</a></li>
<li>[<a href="https://talkpython.fm/episodes/rss">RSS</a>] <a href="https://talkpython.fm/">Talk Python to Me</a></li>
<li>[<a href="https://threedots.tech/index.xml">RSS</a>] <a href="https://threedots.tech/">Three Dots</a></li>
</ul>
<h2 id="humans">Humans</h2>
<ul>
<li>[<a href="https://www.alexedwards.net/static/feed.rss">RSS</a>] <a href="https://www.alexedwards.net/blog">Alex Edwards</a></li>
<li>[<a href="https://holub.com/feed/">RSS</a>] <a href="https://holub.com/">Allen Holub</a></li>
<li>[<a href="https://hoverbear.org/rss.xml">RSS</a>] <a href="https://hoverbear.org/">Ana Hobden</a></li>
<li>[<a href="https://benhoyt.com/writings/rss.xml">RSS</a>] <a href="https://benhoyt.com/writings/">Ben Hoyt</a></li>
<li>[<a href="https://notes.eatonphil.com/rss.xml">RSS</a>] <a href="http://notes.eatonphil.com/">Eaton phil</a></li>
<li>[<a href="https://blog.pragmaticengineer.com/rss/">RSS</a>] <a href="https://blog.pragmaticengineer.com/">Gergely Orosz - The Pragmatic Programmer </a></li>
<li>[<a href="https://gcollazo.com/feed/">RSS</a>] <a href="https://gcollazo.com/">Giovanni Collazo</a></li>
<li>[<a href="https://jacobian.org/index.xml">RSS</a>] <a href="https://jacobian.org/">Jacob Kaplan-Moss</a></li>
<li>[<a href="https://janbosch.com/blog/index.php/feed/">RSS</a>] <a href="https://janbosch.com/blog">Jan Bosch</a></li>
<li>[<a href="https://www.joelonsoftware.com/feed/">RSS</a>] <a href="https://www.joelonsoftware.com/">Joel on Software</a></li>
<li>[<a href="https://jpadilla.com/feed/">RSS</a>] <a href="https://jpadilla.com/">José A. Padilla</a></li>
<li>[<a href="https://www.lpalmieri.com/rss.xml">RSS</a>] <a href="https://www.lpalmieri.com/">Luca Palmieri</a></li>
<li>[<a href="https://www.arp242.net/feed.xml">RSS</a>] <a href="https://www.arp242.net/">Martin Tournoij</a></li>
<li>[<a href="__GHOST_URL__/rss">RSS</a>] <a href="__GHOST_URL__/">Me</a></li>
<li>[<a href="https://rickcarlino.com/rss/feed.rss">RSS</a>] <a href="https://rickcarlino.com/">Rick Carlino</a></li>
<li>[<a href="https://swyx.io/rss.xml">RSS</a>] <a href="https://swyx.io/">Shawn Wang</a></li>
<li>[<a href="https://simonwillison.net/atom/everything/">RSS</a>] <a href="http://simonwillison.net/">Simon Willison</a></li>
<li>[<a href="https://tilkov.com/feed.atom">RSS</a>] <a href="https://www.tilkov.com/">Stefan Tilkov</a></li>
<li>[<a href="https://ufried.com/blog/index.xml">RSS</a>] <a href="https://ufried.com/blog/">Uwe Friedrichsen</a></li>
</ul>
<h2 id="of-interest">Of Interest</h2>
<ul>
<li>[<a href="https://daringfireball.net/feeds/main">RSS</a>] <a href="https://daringfireball.net/">Daring Fireball</a></li>
<li>[<a href="https://feed.infoq.com/architecture-design/">RSS</a>] <a href="https://www.infoq.com/">InfoQ</a></li>
<li>[<a href="https://www.macstories.net/feed/">RSS</a>] <a href="https://www.macstories.net/">Mac Stories</a></li>
<li>[<a href="https://panic.com/blog/feed/">RSS</a>] <a href="https://panic.com/blog">Panic</a></li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>Lecciones aprendidas: especificaciones técnicas</title>
            <link>https://froi.dev/posts/lecciones-aprendidas-especificaciones-tecnicas/</link>
            <pubDate>Mon, 03 Jan 2022 21:07:00 +0000</pubDate>
            
            <guid>https://froi.dev/posts/lecciones-aprendidas-especificaciones-tecnicas/</guid>
            <description>&lt;p&gt;En nuestro campo [&lt;em&gt;software engineering&lt;/em&gt;] se habla mucho de velocidad de entrega. Pasamos mucho tiempo optimizando como utilizamos el tiempo, fechas de entrega y distribución de trabajo. Tenemos metodologías y sistemas para asegurar que esto fluya correctamente. &amp;ldquo;&lt;a href=&#34;https://www.explainxkcd.com/wiki/index.php/1428:_Move_Fast_and_Break_Things&#34;&gt;Move fast and break things&lt;/a&gt;&amp;rdquo; todavía es un &lt;em&gt;mantra&lt;/em&gt; para muchos.&lt;/p&gt;
&lt;figure&gt;&lt;a href=&#34;https://xkcd.com/1428&#34;&gt;&lt;img src=&#34;https://froi.dev/posts/lecciones-aprendidas-especificaciones-tecnicas/images/Artboard.png&#34;
    alt=&#34;Comic de XKCD con alguien tomando una entrevista mencionando su mantra de moverse rapido y romper cosas. Tiene una lista de los trabajos de los cuales lo han despedido&#34;&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;A mucho les encanta gritar &amp;ldquo;practicamos &lt;a href=&#34;https://es.wikipedia.org/wiki/Desarrollo_%C3%A1gil_de_software&#34;&gt;Agile development&lt;/a&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Agile_software_development&#34;&gt;en&lt;/a&gt;&amp;rdquo; y se adhieren a los rituales diversos rituales para asegurarse que así sea. Sin embargo &lt;a href=&#34;https://en.wikipedia.org/wiki/Scrum_%28software_development%29#Sprint&#34;&gt;&lt;em&gt;sprint&lt;/em&gt;&lt;/a&gt; tras &lt;em&gt;sprint&lt;/em&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Milestone_%28project_management%29&#34;&gt;&lt;em&gt;milestone&lt;/em&gt;&lt;/a&gt; tras &lt;em&gt;milestone&lt;/em&gt;, volvemos a dialogar de los mismo problemas que teníamos con otras metodologías,&lt;em&gt;&lt;a href=&#34;https://es.wikipedia.org/wiki/S%C3%ADndrome_del_lavadero&#34;&gt;scope creep&lt;/a&gt;&lt;/em&gt;, requerimientos no documentados, expectativas que cambian, entre otros. Además, seguimos con la misma &lt;a href=&#34;https://en.wikipedia.org/wiki/Agile_software_development#Code_vs._documentation&#34;&gt;falta de documentación&lt;/a&gt;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>En nuestro campo [<em>software engineering</em>] se habla mucho de velocidad de entrega. Pasamos mucho tiempo optimizando como utilizamos el tiempo, fechas de entrega y distribución de trabajo. Tenemos metodologías y sistemas para asegurar que esto fluya correctamente. &ldquo;<a href="https://www.explainxkcd.com/wiki/index.php/1428:_Move_Fast_and_Break_Things">Move fast and break things</a>&rdquo; todavía es un <em>mantra</em> para muchos.</p>
<figure><a href="https://xkcd.com/1428"><img src="/posts/lecciones-aprendidas-especificaciones-tecnicas/images/Artboard.png"
    alt="Comic de XKCD con alguien tomando una entrevista mencionando su mantra de moverse rapido y romper cosas. Tiene una lista de los trabajos de los cuales lo han despedido"></a>
</figure>

<p>A mucho les encanta gritar &ldquo;practicamos <a href="https://es.wikipedia.org/wiki/Desarrollo_%C3%A1gil_de_software">Agile development</a><a href="https://en.wikipedia.org/wiki/Agile_software_development">en</a>&rdquo; y se adhieren a los rituales diversos rituales para asegurarse que así sea. Sin embargo <a href="https://en.wikipedia.org/wiki/Scrum_%28software_development%29#Sprint"><em>sprint</em></a> tras <em>sprint</em>, <a href="https://en.wikipedia.org/wiki/Milestone_%28project_management%29"><em>milestone</em></a> tras <em>milestone</em>, volvemos a dialogar de los mismo problemas que teníamos con otras metodologías,<em><a href="https://es.wikipedia.org/wiki/S%C3%ADndrome_del_lavadero">scope creep</a></em>, requerimientos no documentados, expectativas que cambian, entre otros. Además, seguimos con la misma <a href="https://en.wikipedia.org/wiki/Agile_software_development#Code_vs._documentation">falta de documentación</a>.</p>
<p>En los pasados meses, mi equipo se ha dado la tarea de escribir <em>engineering specs</em> para enfocar la conversación en lo que conocemos y lo que no sobre un problema. Me gustaría compartir lo que he aprendido sobre la practica.</p>
<p>Una búsqueda rápida por el internet les darán un sinnúmero de excelente artículos enumerando los beneficios de escribir un <em>engineering spec (ver enlances al final del articulo)</em>. Por esto, prefiero entrar en las lecciones que he aprendido en los pasados meses de estar escribiendo estos documentos con mucha frecuencia.</p>
<h3 id="crea-una-plantilla-template">Crea una plantilla (<em>template</em>)</h3>
<p>Escribir este tipo de documento puede intimidar. Mucho tiempo se puede ir pensando cómo mejor estructurarlo, que partes incluir y que es importante. La creación de un <em>template</em> es de infinita ayuda para reducir estas incertidumbres  y ayudar a concentrar en el contenido.</p>
<p>Pueden ver el <a href="https://gist.github.com/froi/3f28dea50fe920d4862bbdd00c22dd65"><em>template</em> que estoy utilizando</a>. Una gran parte viene del articulo <a href="https://stackoverflow.blog/2020/04/06/a-practical-guide-to-writing-technical-specs/"><em>A practical guide to writing technical specs</em></a> por <a href="https://stackoverflow.blog/author/zara-cooper/">Zara Cooper</a>. Les recomiendo que vean el <a href="https://gist.githubusercontent.com/froi/3f28dea50fe920d4862bbdd00c22dd65/raw/02049415c2cff8d6c6e7ed8f3975346394dd1bf9/engineering-spec-template.md">Markdown crudo</a> ya que tiene comentarios dando una breve explicación de cada sección.</p>
<h3 id="modifiquen-el-template-mientras-escriban">Modifiquen el <em>template</em> mientras escriban</h3>
<p>La función de la plantilla es ayudarte a escribir. Esta perfectamente bien remover secciones que no hacen falta o añadir secciones que te ayuden a escribir un mejor <em>spec</em>.</p>
<p>Un buen ejemplo son las secciones de <em>prior art</em> y <em>current solution</em> en el <em>template</em> que compartí. Proyectos nuevos pueden no tener estos ejemplos o la necesidad de mencionarlos. Es mejor tener un documento que su estructura demuestre finalidad que tener a un lector preguntarse si esta incompleto.</p>
<h3 id="traten-el-template-como-un-documento-viviente">Traten el <em>template</em> como un documento viviente</h3>
<p>Durante los pasados meses mi equipo se ha dado la tarea de validar que nuestro <em>template</em> realmente es útil para nosotros. Iteramos sobre él, lo compartimos con el resto de la organización de ingeniería y pedimos retroalimentación. Esto a creado una aceptación del mismo y otros equipo lo han adoptado para sus necesidades.</p>
<h3 id="escribe-el-spec-antes-de-implementar">Escribe el spec antes de implementar</h3>
<p>Esto es más importante de lo que uno se imagina.</p>
<p>Un propósito de un <em>engineering spec</em> es de proponer soluciones a un problema y de retar asunciones que podamos tener de dichas soluciones. Encuentro que el tener un documento escrito que exponga estas asunciones ayuda en la construcción de prototipos que puedan sostener o desaprobar las mismas.</p>
<p>Una vez el <em>spec</em> esta aceptado también sirve de documentación durante las etapas de planificación y desarrollo. Esto ayuda a mantener todo dentro del <a href="https://es.wikipedia.org/wiki/Alcance_%28gesti%C3%B3n_de_proyectos%29">alcance</a> (<a href="https://en.wikipedia.org/wiki/Scope_%28project_management%29"><em>scope</em></a>) del proyecto y a evitar <a href="https://es.wikipedia.org/wiki/S%C3%ADndrome_del_lavadero"><em>scope creep</em></a></p>
<h3 id="pongan-un-limite-de-tiempo-para-escribir">Pongan un limite de tiempo para escribir</h3>
<p>De todas las lecciones creo que esta fue las más obvia que no vimos hasta después de escribir varios <em>specs</em>.</p>
<p>Es de suma importancia que mantengan el proceso de escribir un <em>spec</em> activo. Estos documentos pueden volverse complicados y extensos. Existe el potencial de dejarlos sin terminar para atender otros asuntos de &ldquo;mayor importancia&rdquo;. Esto puede paralizar el proceso y llevar al equipo a brincar directamente a una etapa de implementación.</p>
<p>El mantener un limite de tiempo no solo ayuda a imponer un termino para completar el documento, sino que puede ayudar a identificar si el <em>scope</em> del problema es muy extenso. Esto presenta una excelente oportunidad para revaluar el problema y quizás dividirlo en tamaños más manejable.</p>
<h3 id="hagan-el-escribir-el-spec-parte-de-su-proceso-de-desarrollo">Hagan el escribir el <em>spec</em> parte de su proceso de desarrollo</h3>
<p>Escribir un <em>spec</em> conlleva tiempo y esfuerzo. Se debería considerar igual de importante que la implementación de código. Incluye esta tarea como cualquier otra en tu sesiones de planificación, ya sea <em>agile</em>, <em>scrum</em>, <em>sprints</em>, no importa. El trabajo se debería representar correctamente y ayuda al equipo ir aprendiendo cuánto realmente toma definir, investigar y escribir un <em>spec</em>.</p>
<p>Mi equipo esta incluyendo estos documentos como parte de los <em><a href="https://en.wikipedia.org/wiki/Spike_%28software_development%29">spikes</a></em> en nuestro <em>sprint</em>. Nos ayuda a mantener el proceso del <em>spec</em> corriendo, nos permite comunicar a las otras partes de la organización donde estamos con entregables y nos da un artefacto de entrega al final del <em>sprint</em> que nos sirve para <em>demos</em>.</p>
<h3 id="incluye-el-mantenimiento-de-tus-spec-en-tus-tareas">Incluye el mantenimiento de tus <em>spec</em> en tus tareas</h3>
<p>Un <em>spec</em> realmente no esta terminado del todo. Durante el proceso de desarrollo los requerimientos pueden cambiar, el equipo aprende más sobre el tema o se prueba que la solución no es la correcta. Tu <em>spec</em> debería reflejar esto.</p>
<p>La actualización de un <em>spec</em> deberían formar parte de tu proceso de desarrollo, tal como actualizas la documentación del proyecto. Esto puede ser parte de las tareas del desarrollador al someter cambios al código, de un desarrollador senior o un <em><a href="https://en.wikipedia.org/wiki/Lead_programmer">tech lead</a></em>, hasta de un <a href="https://en.wikipedia.org/wiki/Scrum_%28software_development%29#Product_owner"><em>product owner</em></a>.</p>
<p>Para ayudarnos, mi equipo incluye preguntas en nuestro <a href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/about-issue-and-pull-request-templates#pull-request-templates"><em>pull request template</em></a> donde el desarrollador puede indicar si hace falta algún cambio en documentación.</p>
<p>Esto no resuelve el problema del todo, pero sí nos mantiene pensando en estas tareas.</p>
<h2 id="para-terminar">Para terminar</h2>
<p>El valor de crear especificaciones técnicas es bien alto tanto para el desarrollador como para su equipo y organización. Escribir estos documentos nos permite pensar sobre soluciones alejados de los detalles de implementación, abre las puertas a colaboración de otros equipos y personas en tu equipo y puede ahorrar tiempo de implementación. Dicho todo esto, esto no es una solución mágica para crear buen <em>software</em>, sino parte del proceso.</p>
<p>Toma el tiempo para evaluar si esta practica funciona para tus proyectos y equipos. Como toda disciplina toma tiempo sentirse cómod@ en su practica. Existen varios artículos que te pueden ayudar a comenzar. Estos son algunos que me ayudaron a mí:</p>
<ol>
<li><a href="https://stackoverflow.blog/2020/04/06/a-practical-guide-to-writing-technical-specs/"><em>A practical guide to writing technical specs</em></a> por <a href="https://stackoverflow.blog/author/zara-cooper/">Zara Cooper</a></li>
<li><a href="https://eng.lyft.com/awesome-tech-specs-86eea8e45bb9"><em>How to write awesome tech specs</em></a> por <a href="https://medium.com/@blackqueentech">Della Anjeh (@blackqueentech)</a></li>
<li><a href="https://medium.com/easyread/writing-technical-specification-and-why-it-matters-b9ea78fbeb49"><em>Writing Technical Specification, and Why it Matters</em></a> por <a href="https://medium.com/@angaziz">Anggie Aziz</a></li>
<li><a href="https://codeburst.io/on-writing-tech-specs-6404c9791159"><em>On Writing Tech Specs</em></a> por <a href="https://cgroom.medium.com/">Chuck Groom</a></li>
</ol>
<p>Gracias por leer y nos vemos en la próxima.</p>
]]></content>
        </item>
        
        <item>
            <title>Gov APIs: el SEC</title>
            <link>https://froi.dev/posts/gov-apis-el-sec/</link>
            <pubDate>Mon, 04 Oct 2021 14:16:34 +0000</pubDate>
            
            <guid>https://froi.dev/posts/gov-apis-el-sec/</guid>
            <description>&lt;p&gt;Continuando con el tema de APIs gubernamentales y su uso para mejorar la interacción con el ciudadano, vamos a mirar al US Securities and Exchange Commission (SEC).&lt;/p&gt;
&lt;h2 id=&#34;qué-es-el-sec&#34;&gt;¿Qué es el SEC?&lt;/h2&gt;
&lt;p&gt;El SEC es una agencia independiente del gobierno federal de los EEUU que se encarga de regular y esforzar las leyes contra la manipulación de los mercados. La misma fue creado como una respuesta al &lt;a href=&#34;https://es.wikipedia.org/wiki/Crac_del_29?wprov=sfti1&#34;&gt;colapso de los mercados de Wall Street en el 1929&lt;/a&gt;, que llevo a la &lt;a href=&#34;https://es.wikipedia.org/wiki/Gran_Depresi%C3%B3n?wprov=sfti1&#34;&gt;Gran Depresión de la década de 1930&lt;/a&gt;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Continuando con el tema de APIs gubernamentales y su uso para mejorar la interacción con el ciudadano, vamos a mirar al US Securities and Exchange Commission (SEC).</p>
<h2 id="qué-es-el-sec">¿Qué es el SEC?</h2>
<p>El SEC es una agencia independiente del gobierno federal de los EEUU que se encarga de regular y esforzar las leyes contra la manipulación de los mercados. La misma fue creado como una respuesta al <a href="https://es.wikipedia.org/wiki/Crac_del_29?wprov=sfti1">colapso de los mercados de Wall Street en el 1929</a>, que llevo a la <a href="https://es.wikipedia.org/wiki/Gran_Depresi%C3%B3n?wprov=sfti1">Gran Depresión de la década de 1930</a>.</p>
<p>Para lograr su mandato el SEC esfuerza requerimientos a compañías publicas y reguladas de radicar informes trimestrales, anuales y otros periodos durante el año. Estos reportes con cruciales para inversionistas, analistas de mercado y el publico en general.</p>
<p>Para hacer esta información accesible de una manera equitativa para todos, el SEC mantiene un sistema llamado <a href="https://en.wikipedia.org/wiki/EDGAR?wprov=sfti1">EDGAR (the Electronic Data Gathering, Analysis, and Retrieval system)</a>. El mismo funciona como un sistema de búsqueda e inventario para los informes suministrados por compañías. <a href="https://www.sec.gov/edgar/search/">La búsqueda</a> es una típica que uno puede encontrar alrededor del internet.</p>
<figure><img src="/posts/gov-apis-el-sec/images/sec-edgar-search.png"
    alt="Una imagen de la pagina de búsqueda del sistema EDGAR de la agencia federal de los EEUU llamada el SEC. Contiene un listado de datos de una búsqueda para la compañía Apple." width="100%" height="100%">
</figure>

<h2 id="mas-aya-de-una-página">Mas aya de una página</h2>
<p>Muchos de nosotros esperaríamos que los esfuerzos del SEC se queden ahi, una búsqueda y que todos nosotros nos resolvamos con eso. Sin embargo, el SEC a construido <a href="https://www.sec.gov/developer">recursos para desarrolladores</a>.</p>
<h3 id="por-qué-es-que-esto-es-especial">¿Por qué es que esto es especial?</h3>
<p>Para entender esto tenemos que entender como se utiliza esta data. Las declaraciones financieras de estas <a href="https://es.wikipedia.org/wiki/Empresa_de_capital_abierto">&ldquo;public companies&rdquo; (empresas de capital abierto)</a> son utilizadas por inversionistas para evaluar estas compañías y planificar sus inversiones. Muchos inversionistas dependen de servicios que toman estos informes y los convierten en data accionable. De estos servicios quizás el mas famoso es el <a href="https://www.bloomberg.com/professional/solution/bloomberg-terminal/">Bloomberg terminal</a>. Estos servicios son esenciales para inversionistas.</p>
<h2 id="la-data">La data</h2>
<p>Tradicionalmente, la distribución de esto informes no era muy accesible. Aunque siempre estaban en el dominio publico, su acceso no era programática. Es esto lo que hace los <a href="https://www.sec.gov/developer">recursos para desarrolladores</a> del SEC un avance grande. El acceso programático que es posible con su API crea oportunidades para que desarrolladores y compañías creen servicios competitivos con los establecidos. También les permiten a los inversionistas que tengan mayor conocimiento técnico a construir sus propias herramientas. Esto abre muchas posibilidades.</p>
<p>Esto no solo ayuda a los inversionistas. Esta data también es utilizada por reporteros, entidades fiscalizadoras y el propio gobiernos. Abrir esta data de esta manera crea oportunidades a estos a poder hacer su trabajo de una manera mas eficiente, tanto en costo como en tiempo.</p>
<h2 id="como-podemos-usar-esta-data">Como podemos usar esta data</h2>
<p>Tener esta data es solo una parte de la ecuación. Al final del día lo más importante es como la utilizamos y que podemos aprender de ella. Hable con <a href="https://twitter.com/arivera">Axel Rivera</a>, que ademas de ser unos de los mejores iOS developers que he conocido, lleva años dedicando su tiempo libre a entender los mercados. Dos usos claves para él son el poder ver como las compras y ventas de <a href="https://en.wikipedia.org/w/index.php?title=Fund_managers&amp;amp;redirect=no">&ldquo;fund managers&rdquo;</a> como <a href="https://en.wikipedia.org/wiki/Warren_Buffett">Warren Buffet</a> y <a href="https://en.wikipedia.org/wiki/Machine_learning">machine learning</a> (<a href="https://es.wikipedia.org/wiki/Aprendizaje_autom%C3%A1tico">es</a>).</p>
<h3 id="qué-beneficio-tiene-el-ver-las-compras-y-ventas-de-fund-managers">¿Qué beneficio tiene el ver las compras y ventas de fund managers?</h3>
<p>Como mucho en la vida, el tener ejemplos a emular ayuda cuando se comienza en un campo o practica. El poder ver esta data permite poder emular las practicas que estos profesionales de inversion ejecutan, así ayudándote a comprender mercados y planificar tus propias compras y ventas.</p>
<h3 id="qué-tal-con-machine-learning">¿Qué tal con machine learning?</h3>
<p>Machine learning (ML) es un tema extremadamente abarcador y al igual que sus usos. Esta data podría ser utilizada para crear modelos que nos ayude entender patrones económicos y pronosticar eventos. También podría abrir oportunidades de desarrollo económico, fiscalización y proyecciones de mercados.</p>
<p>De seguro habra otros usos e ideas al tener esta data disponible. Data no es necesariamente buena o mala y su uso esta en nuestras manos. Dicho esto el acceso a la misma es de suma importancia. Tener entidades en nuestro gobierno abriendo este acceso nos puede ayudar a no solo fiscalizarlo, pero también crear oportunidades para nuestro crecimiento.</p>
<p>Sí les interesa el tema del uso de data abierta y de gobierno para impacto social y oportunidades económicas, denle un vistazo a <a href="https://opportunity.census.gov">The Opportunity Project</a> de la <a href="https://www.census.gov">Oficina del Censo de los EEUU</a>.</p>
<hr>
<p>Gracias a <a href="https://twitter.com/arivera">Axel Rivera</a> por la edición y apuntarme en la dirección correcta.</p>
<p>Gracias por la lectura ❤️</p>
]]></content>
        </item>
        
        <item>
            <title>Want to be a Senior Developer? Mentor Another</title>
            <link>https://froi.dev/posts/want-to-be-a-senior-developer-mentor-another/</link>
            <pubDate>Sat, 21 Aug 2021 15:33:35 +0000</pubDate>
            
            <guid>https://froi.dev/posts/want-to-be-a-senior-developer-mentor-another/</guid>
            <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This was originally posted on April 21, 2018 on &lt;a href=&#34;https://medium.com/@froi/want-to-be-a-senior-developer-mentor-another-3ba383587669&#34;&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;What really is a “senior developer”? How does one get this honorific? Is it based on years? Projects worked on? Knowledge? Dumb luck? Achievement?&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://froi.dev/posts/want-to-be-a-senior-developer-mentor-another/images/philoso-raptor.png&#34;
    alt=&#34;Image of the philoso raptor meme. A dinosaur in a deep in thought pose.&#34;&gt;&lt;figcaption&gt;
      &lt;p&gt;What am I?&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I’m going to go out on limb and say that you can only really get to call yourself a “senior” developer when you mentor another. When you impart your knowledge for the benefit of another in a way that is understandable and useful. Now this doesn’t mean hand holding, although it could. Sometimes being a mentor is imparting harsh truths. Until you do that you’re just a developer.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<blockquote>
<p><em>This was originally posted on April 21, 2018 on <a href="https://medium.com/@froi/want-to-be-a-senior-developer-mentor-another-3ba383587669">Medium</a>.</em></p></blockquote>
<p>What really is a “senior developer”? How does one get this honorific? Is it based on years? Projects worked on? Knowledge? Dumb luck? Achievement?</p>
<figure><img src="/posts/want-to-be-a-senior-developer-mentor-another/images/philoso-raptor.png"
    alt="Image of the philoso raptor meme. A dinosaur in a deep in thought pose."><figcaption>
      <p>What am I?</p>
    </figcaption>
</figure>

<p>I’m going to go out on limb and say that you can only really get to call yourself a “senior” developer when you mentor another. When you impart your knowledge for the benefit of another in a way that is understandable and useful. Now this doesn’t mean hand holding, although it could. Sometimes being a mentor is imparting harsh truths. Until you do that you’re just a developer.</p>
<p>To clarify my “just a developer” isn’t meant to be derogatory. You can “just be a developer” and be amazing. You could have incredible knowledge and build wonders the world has never seen. You just aren’t a senior developer in my eyes. The same way you can’t call yourself a teacher or professor until you teach.</p>
<p>So what, you might ask? Why should we even care?</p>
<p>Mentorship is the bedrock from where professions are constructed. The more people we have the better the whole is, the more ideas we can consume, we are just better for it.</p>
<p>My professional software developer career spans 13 years. I’ve been a tech lead, team lead, a senior developer, a junior developer, just a developer. Other descriptions that have been given to me include the guy that broke the build, the guy that deleted the database, and other very colorful but deserved ones. Out of all of these I never really thought I deserved the “senior” label. It just never felt right, like I didn’t deserve it.</p>
<p>That started to change one day though. The catalyst? I explained how functions work to a kid who wanted to learn.</p>
<figure><img src="/posts/want-to-be-a-senior-developer-mentor-another/images/prpig-mentoria.png"
    alt="Picture of two people in front of a whiteboard in a white room. The older of the two is explaining some computer programming concepts.">
</figure>

<p>I believe I learned more here that what I could have explained.
Now that in and of itself is not the big deal. What really hit me was that I did so without a script. It wasn’t that I prepared an intro or had slides. I just had a small whiteboard and somebody that looked to me to explain what something was.</p>
<p>The look on his face as he went from <em>“huh?”</em> to <em>“ooohhhh!”</em> was incredibly satisfying. He then went on to explain to me how he would do some basic math exercises using the little Python I taught him. I knew at that point that helping people was the only way that a community or a profession could sustain itself. His uncle, who was himself a developer finishing up his studies at the University of Puerto Rico, told me he later got <em>“a thousand”</em> questions from his nephew and that he continued to be interested in development.</p>
<p>That simple experience helped me realize that to earn the <em>“senior honorific”</em>, I had to help others as much as I could. I started volunteering at workshops, Startup Weekends, created meetups, and invited other colleagues to do the same. I started to get other people asking for advice about not only their code but their professional career. Questions like <em>“what technologies should I learn”</em>, <em>“is there a better way to do this”</em>, <em>“how should I build one thing or another”</em>. Then one day it happened, somebody introduced me as one of their mentors. I was instantly in a <em>“position of authority”</em> in the best possible way. I felt I could now help developers that were starting their careers. Give back the help that I got when I started.</p>
<p>Nobody does anything by themselves. Somewhere in your life there’s somebody that took the time to help you, even if it was an uncomfortable conversation. If you really want to feel like you have gotten to a <em>“senior”</em> level in your career I invite you to take some time and mentor somebody that needs it. It doesn’t have to be much, it doesn’t have to mean hand holding, just help until you can’t anymore. I’m certain that both of you will be better for it.</p>
]]></content>
        </item>
        
        <item>
            <title>Destiny Item Manager: un ejemplo de valor añadido para gobiernos y civic tech</title>
            <link>https://froi.dev/posts/destiny-item-manager-un-ejemplo-de-valor-anadido/</link>
            <pubDate>Sun, 08 Aug 2021 21:00:00 +0000</pubDate>
            
            <guid>https://froi.dev/posts/destiny-item-manager-un-ejemplo-de-valor-anadido/</guid>
            <description>&lt;p&gt;El crear una plataforma permite la creación y el empoderamiento de una comunidad alrededor de un producto o servicio. Esto a su vez crea oportunidades de innovación por la comunidad, para la comunidad, que al final pudiese mejorar la experiencia de la misma. Múltiples ejemplos existen en industrias que antiguamente eran cerradas, es hora que nuestros gobiernos y sus contratistas hagan lo mismo de una manera más amplia.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Los video juegos han sido una constante en mi vida. Desde el Atari 2600 al PlayStation 4 que tengo ahora siempre he tenido alguna consola en mi casa. Durante este tiempo la industria de los video juegos a crecido a una de alcance mundial con ingresos que superan a los de las industrias de cine y música combinadas . Este crecimiento también a cambiado la demografía que consume estos juegos. La audiencia se ha expandido con los dispositivos móviles y la creación de juegos como &lt;em&gt;Angry Birds&lt;/em&gt;, &lt;em&gt;Candy Crunch&lt;/em&gt; y el porte de &lt;em&gt;Fortnite&lt;/em&gt;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>El crear una plataforma permite la creación y el empoderamiento de una comunidad alrededor de un producto o servicio. Esto a su vez crea oportunidades de innovación por la comunidad, para la comunidad, que al final pudiese mejorar la experiencia de la misma. Múltiples ejemplos existen en industrias que antiguamente eran cerradas, es hora que nuestros gobiernos y sus contratistas hagan lo mismo de una manera más amplia.</p>
<hr>
<p>Los video juegos han sido una constante en mi vida. Desde el Atari 2600 al PlayStation 4 que tengo ahora siempre he tenido alguna consola en mi casa. Durante este tiempo la industria de los video juegos a crecido a una de alcance mundial con ingresos que superan a los de las industrias de cine y música combinadas . Este crecimiento también a cambiado la demografía que consume estos juegos. La audiencia se ha expandido con los dispositivos móviles y la creación de juegos como <em>Angry Birds</em>, <em>Candy Crunch</em> y el porte de <em>Fortnite</em>.</p>
<p>Más interesante aun es el cambio en la relación de los estudios y casas publicadoras con los jugadores y las comunidades que crean. Las redes sociales han creado la oportunidad de un dialogo directo entre las comunidades de estos juegos y los desarrolladores. La apertura de <a href="https://es.wikipedia.org/wiki/Interfaz_de_programaci%C3%B3n_de_aplicaciones">APIs</a> (interfaces aplicativas que permiten la interacción con un servicio) por algunas compañías han llevado esta relación a un nivel más aya que meramente uno de consumo. Este es el aspecto en el que me quiero enfocar con el juego <em>Destiny 2</em> y la compañía que lo desarrolla, Bungie.</p>
<figure><a href="https://www.bungie.net/7/en/Destiny"><img src="/posts/destiny-item-manager-un-ejemplo-de-valor-anadido/images/destiny-new-light.jpeg"
    alt="Imagen de anuncio de la expansión New Light del video juego Destiny 2. Se ve un número dos grande que ocupa el centro de la imagen y esta sobre una ciudad que aparenta estar en fuego o bajo ataque" width="100%" height="100%"></a>
</figure>

<p>Durante el 2020 me encontré pasando mucho tiempo con este juego. <em>Destiny 2</em> es un <a href="https://es.wikipedia.org/wiki/Videojuego_de_disparos_en_primera_persona?wprov=sfti1"><em>first person shooter</em></a>, <a href="https://es.wikipedia.org/wiki/Videojuego_de_rol_multijugador_masivo_en_l%C3%ADnea?wprov=sfti1"><em>massive multiplayer online role playing game</em></a>. Esto lo que significa es que como jugador uno comparte este mundo digital simultáneamente con jugadores de alrededor del mundo. Crear este tipo de mundo requiere un esfuerzo continuo que incluye actualizaciones constantes. El mantener a la comunidad de jugadores interesados y activos requiere un ciclo constante de dialogo e iteración. El objetivo es que estas comunidades se sientan parte del proceso y que se sientan dueñas del mundo. Para la compañía esto representa una audiencia cautiva con la cual devenga sus ingresos. Una excelente manera de lograr esto es de permitir acceso al juego y su plataforma mediante <a href="https://es.wikipedia.org/wiki/Interfaz_de_programaci%C3%B3n_de_aplicaciones">APIs</a>. Esto es precisamente lo que <em>Bungie</em> ha hecho.</p>
<p>Como mencione, este año pasado le he dedicado mucho tiempo a este juego, y como todo, me he topado con elementos que se convierten en labores tediosa mientras más interactúas con ellas. La decisión de <em>Bungie</em> de <a href="https://bungie-net.github.io/">abrir su API</a> a permitido que la comunidad desarrolle herramientas que alivian y hasta mejoran la experiencia creada por <em>Bungie</em>. Un ejemplo de una de estas aplicaciones hechas por la comunidad lo es el <a href="https://destinyitemmanager.com/">Destiny Item Manager</a>. Con esta herramienta jugadores pueden manejar el uso de sus recursos en el juego afuera del mismo con cualquier dispositivo. Por consiguiente, mi tiempo dentro del juego ha sido mejor utilizado para los eventos y el entretenimiento que busco. Suena gracioso pero me ha hecho más &ldquo;productivo&rdquo;.</p>
<figure><a href="#ZgotmplZ"><img src="/posts/destiny-item-manager-un-ejemplo-de-valor-anadido/images/bungie-api-docs.png"
    alt="Imagen de la documentación para el API de Bungie encontrado en https://bungie-net.github.io/" width="100%" height="100%"></a><figcaption>
      <p>Documentación para el API de Bungie en <a href="https://bungie-net.github.io/">https://bungie-net.github.io/</a></p>
    </figcaption>
</figure>

<p><em>Bungie</em> creó y abrió su plataforma para sus usuarios y comunidades. No solo esta disponible al publico en <a href="https://github.com/Bungie-net/api">GitHub</a>, pero también dedican recursos para atender preguntas de la comunidad. No solo es algo que publican porque pueden, sino <a href="https://help.bungie.net/hc/en-us/sections/360010408111-Companion-App-and-Extension-Support">es una parte integral de su producto</a>. Con esto creo una plataforma de innovación y creación para sus jugadores.</p>
<p>Llevemos este pensar a nuestras interacciones con nuestro gobierno, sus agencia y las tareas que realizamos con ellas. En esta narrativa <em>Bungie</em> no es distinto a un gobierno. Al igual que un gobierno no es común que la comunidad de usuarios, en este caso la ciudadanía, pueda crear o aportar a la experiencia de usuario con un servicio. La mayoría de los constituyentes somos consumidores. No tenemos el acceso para crear herramientas o interacciones que los publicadores (el gob. y sus contratista) no hayan pensado. Esto, en mi opinión, alimenta las frustraciones y lleva a una relación antagónica.</p>
<p>Imaginemos entonces que aprendamos de los ejemplos de compañías publicadoras de video juegos como Bungie. Que nuestros gobiernos y sus agencias se transformen en proveedores de servicios y plataformas. Donde los servicios y paginas oficiales ofrezcan un <a href="https://es.wikipedia.org/wiki/Interfaz_de_programaci%C3%B3n_de_aplicaciones">API</a> abierto y accesible, con el que las comunidades de civic-tech puedan aumentar los servicios existentes con productos complementarios. Imaginen el potencial de tener un <a href="https://es.wikipedia.org/wiki/Interfaz_de_programaci%C3%B3n_de_aplicaciones">API</a> que exponga los procesos legislativos que sea abierto y que la comunidad pueda utilizarlo para crear servicios para explicar las medidas en un lenguaje accesible.</p>
<p>Imaginen que podamos crear servicios que mantengan a la ciudadanía invertida en los procesos que mantiene a nuestra sociedad corriendo. Donde la apatía se convierta en retroalimentación, donde la falta de acceso se convierta en esfuerzos comunitarios para mejorar nuestras comunidades.</p>
<p>Existen ejemplos claros tanto en la industria privada, como en gobiernos de alrededor del mundo. Esto, aunque en concepto es sencillo, no es fácil. Conlleva cambios en contratación, cultura y visión. No obstante, estos cambios pueden lograrse con incrementos pequeños. En futuras publicaciones adentrare en ideas y ejemplos que puedo ver desde afuera del gobierno y basados en mi experiencia desde adentro del mismo.</p>
<p>Si les interesa esta conversación acompáñenme en los <a href="https://www.meetup.com/code-for-puerto-rico/events/279824261/">hack nights de Code for Puerto Rico</a>, subscribiese a este blog o <a href="__GHOST_URL__/contact/">contáctenme directamente</a>. Juntos podemos traer ideas para mejorar nuestro país y nuestras comunidades.</p>
]]></content>
        </item>
        
        <item>
            <title>La Huella Digital de los Municipios en Puerto Rico: un análisis mal hecho</title>
            <link>https://froi.dev/posts/la-huella-digital-de-los-municipios-en-puerto-rico-un-analisis-mal-hecho/</link>
            <pubDate>Sun, 01 Aug 2021 14:07:32 +0000</pubDate>
            
            <guid>https://froi.dev/posts/la-huella-digital-de-los-municipios-en-puerto-rico-un-analisis-mal-hecho/</guid>
            <description>&lt;p&gt;&lt;em&gt;Esta entrada fue publicada originalmente como parte de la &lt;a href=&#34;https://medium.com/code-4-puerto-rico/la-huella-digital-de-los-municipios-en-puerto-rico-un-an%C3%A1lisis-mal-hecho-6d8fefcca078&#34;&gt;publicación de Code for Puerto Rico&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;78 municipios.&lt;/strong&gt; Estos son los gobiernos que mas afectan el día a día a la ciudadanía. Son la primera parada para ayudas durante desastres, emergencias de salud y festividades locales. Los servicios que ofrecen los municipios son vitales, desde el recogido de escombros, hasta el manejo de seguridad.&lt;/p&gt;
&lt;p&gt;Con tanta importancia que estas instituciones tienen como es que se comunican con los ciudadanos?&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p><em>Esta entrada fue publicada originalmente como parte de la <a href="https://medium.com/code-4-puerto-rico/la-huella-digital-de-los-municipios-en-puerto-rico-un-an%C3%A1lisis-mal-hecho-6d8fefcca078">publicación de Code for Puerto Rico</a>.</em></p>
<p><strong>78 municipios.</strong> Estos son los gobiernos que mas afectan el día a día a la ciudadanía. Son la primera parada para ayudas durante desastres, emergencias de salud y festividades locales. Los servicios que ofrecen los municipios son vitales, desde el recogido de escombros, hasta el manejo de seguridad.</p>
<p>Con tanta importancia que estas instituciones tienen como es que se comunican con los ciudadanos?</p>
<p>En el 2020 y después de mucho intentos de modernización, uno se esperaría que la presencia digital de los municipios este, en lo mínimo, organizada. Que como ciudadano, uno pueda encontrar un lugar donde se pueda acceder información de importancia del lugar en donde se vive. Una pagina de internet, con una dirección fácil de acordarse y la información relevante es lo mas básico que un municipio necesita para crear esta confianza a sus ciudadanos.</p>
<p>En el mundo del internet esto se puede lograr de varias maneras. Para entidades de gobierno en EEUU y sus territorios se puede utilizar el sufijo .gov para indicar que es oficial. En el caso de Puerto Rico se puede ver este intento con <a href="https://pr.gov">pr.gov</a>.</p>
<h2 id="por-que-es-importante-el-gov">Por que es importante el .gov</h2>
<p>Confianza, es así de sencillo.</p>
<p>El internet es una plataforma donde cualquiera puede comprar un dominio que este disponible y apuntarlo a una pagina. Los sufijos como <code>.com</code>, <code>.org</code>, <code>.net</code>, entre otros, nos permiten tener un pedacito del internet para nuestras compañías, organización no gubernamentales y cualquier otro propósito que queramos. Existen sufijos que están controlados por entidades y que velan su uso. El <code>.gov</code> es uno de estos sufijos. Este sufijo esta <a href="https://es.wikipedia.org/wiki/.gov">controlado por el gobierno federal de los EEUU</a> y solo se le da acceso entidades gubernamentales dentro del territorio del mismo. Gracias a esto uno puede estar seguro que <a href="https://pr.gov">pr.gov</a> es el portal oficial del gobierno de Puerto Rico y no <code>https://www.pr.com/</code>.</p>
<p>Con todo lo que ha pasado en los pasados años en Puerto Rico, en Code4PR queríamos ver cuál era la huella digital de los municipios. Queríamos ver cuan fácil se nos podia hacer encontrar información relevante de un municipio que pudiese asistir a sus constituyentes.</p>
<p>Se nos ocurrió comenzar por el portal de <a href="https://pr.gov">pr.gov</a>. Decidimos esto por varias razones:</p>
<ol>
<li>Es el portal oficial del gobierno de Puerto Rico.</li>
<li>Tiene un <a href="https://www.pr.gov/Directorios/Pages/DirectoriodeMunicipios.aspx">directorio de Municipios de Puerto Rico</a>.</li>
</ol>
<p>Los resultados no fueron los mas alentadores,lo que se encontró fue un sin numero de data sin actualizar desde el 2017 y otra simplemente errónea.</p>
<h2 id="el-análisis">El análisis</h2>
<p>Nos dimos la tarea de analizar qué exactamente estaba mal en el directorio. Pueden ver los resultados aquí.</p>
<p>Lo que encontramos se puede agrupar en lo siguiente:</p>
<ol>
<li><a href="/posts/la-huella-digital-de-los-municipios-en-puerto-rico-un-analisis-mal-hecho/#falta-de-informacion">Falta de información sobre las paginas oficiales de los municipios</a></li>
<li><a href="/posts/la-huella-digital-de-los-municipios-en-puerto-rico-un-analisis-mal-hecho/#informaci%c3%b3n-obsoleta-o-err%c3%b3nea">Información obsoleta o errónea de las paginas oficiales de los municipios</a></li>
<li><a href="/posts/la-huella-digital-de-los-municipios-en-puerto-rico-un-analisis-mal-hecho/#p%c3%a1ginas-y-dominios-abandonados">Páginas y dominios abandonados</a></li>
<li><a href="/posts/la-huella-digital-de-los-municipios-en-puerto-rico-un-analisis-mal-hecho/#perdida-de-dominios-y-uso-nefasto-de-los-mismos">Perdida de dominios y uso nefasto de los mismos</a></li>
<li><a href="/posts/la-huella-digital-de-los-municipios-en-puerto-rico-un-analisis-mal-hecho/#uso-confuso-de-paginas-o-grupos-en-redes-sociales">Uso confuso de paginas o grupos en redes sociales</a>.</li>
</ol>
<h3 id="falta-de-información">Falta de información</h3>
<p>Para este análisis estamos definiendo falta de información como:</p>
<blockquote>
<p>Recursos digitales de un municipio que no están incluidos en la entrada del municipio en el <a href="https://www.pr.gov/Directorios/Pages/DirectoriodeMunicipios.aspx">directorio de pr.gov</a>.</p></blockquote>
<p>En el documento adjunto se pueden contar alrededor de 29 dominios que no aparecen en pr.gov. Hay algunos de estos 29 que son dominios que ya no son validos. Esto se puede deber a que no los renovaron o simplemente ya no están en uso.</p>
<h3 id="información-obsoleta-o-errónea">Información obsoleta o errónea</h3>
<p>¿Qué es peor que no tener data? Tener data errónea.</p>
<p>Existen entradas en <a href="https://www.pr.gov/Directorios/Pages/DirectoriodeMunicipios.aspx">pr.gov</a> que están erróneas. Lo que vimos se puede agrupar en:</p>
<ul>
<li>Direcciones de internet erróneas</li>
<li>Dominios de internet caducados</li>
<li>Paginas de internet que no existen</li>
</ul>
<p>Para que el <a href="https://www.pr.gov/Directorios/Pages/DirectoriodeMunicipios.aspx">directorio de municipios</a> sea util para ciudadanos buscando ayuda esto se tiene que arreglar.</p>
<h3 id="páginas-y-dominios-abandonados">Páginas y dominios abandonados</h3>
<p>Encontramos un numero de paginas municipales que aparentan estar abandonadas. Alguna paginas parecían que no se actualizaban con información relevante. Otras se encontraban en un estado perpetuo de construcción. Al final del día, y totalmente nuestra opinion, el ciudadano no podia depender de estas herramientas para obtener información de su municipio.</p>
<p>Esto no se debe de confundir con dominios que hayan caducado. Esto es otro problema del cual hablaremos.</p>
<p>¿Por qué es importante esto?</p>
<p>Volvemos al tema principal, confianza ciudadana.</p>
<p>Cuando uno entra a un edificio que esta bien mantenido, limpio y ordenado, uno se siente bien. Es un sentimiento de “aquí las cosas están bien”. El edificio no tiene qué ser super moderno, aunque eso también ayuda, solo bien cuidado. Una pagina de internet es igual. Para una marca, entidad o comunidad su pagina de internet es su casa, su tarjeta de presentación. Esto debe de ser igual para entidades de gobierno, sin importar en qué rama se encuentra.</p>
<h3 id="perdida-de-dominios-y-uso-nefasto-de-los-mismos">Perdida de dominios y uso nefasto de los mismos</h3>
<p>¿Perdida de dominios? En pocas palabras, el municipio dejo caducar el dominio. Los dominios en el internet se pagan por un periodo de tiempo. Se puede comparar con un alquiler de una propiedad que se paga anualmente. Este &ldquo;alquiler&rdquo; puede hacerse por periodos mas extensos que un año, por ejemplo se puede pagar por el uso del dominio por un periodo diez años. Al final de este periodo, el que sea, se tiene que volver a pagar por su uso.</p>
<p>Al final del día no le vemos problema dejar caducar un dominio que el municipio no vaya a utilizar o si no tiene el presupuesto para mantenerlo. De pasar esto el municipio debe de tener un proceso para alejarse del dominio y de actualizar la información en pr.gov para dejar claro que ya no lo esta utilizando. El no hacer esto abre el camino para el uso nefasto del mismo y la perdida de confianza del ciudadano.</p>
<p>Una vez el dominio se pueda comprar por cualquiera cabe la posibilidad que se pueda usar para acciones nefastas. Esto combinado con el municipio no removiendo el dominio de paginas oficiales puede causar situaciones de disgustos, en el mejor de los casos, o peligro genuino y desinformación en el peor.</p>
<h3 id="uso-confuso-de-paginas-o-grupos-en-redes-sociales">Uso confuso de paginas o grupos en redes sociales.</h3>
<p>Servicios como Facebook y Twitter nos ha permitido llegar a una audiencia enorme de una manera inmediata. Para muchas personas estos servicios <strong>son</strong> el internet, es su interface a información y comunidad. Estas son herramientas que municipios pueden utilizar como su propiedad principal o de manera suplemental a sus propiedades digitales existentes.</p>
<p>¿Dónde esta el problema entonces?</p>
<p>El problema esta en el tipo de uso y el mantenimiento del mismo. Encontramos varios municipios que una pagina o grupo de Facebook era su única propiedad digital y estaba abandonada. En ocaciones se nos hacia un poco difícil saber si el grupo o pagina era una oficial del municipio.</p>
<p>Al igual que los dominios en el internet, cualquiera puede crear una pagina de Facebook con el nombre de un municipio. Los municipios tienen que darle seguridad a sus ciudadanos que la información que están viendo es real y qué viene <strong>del municipio</strong>.</p>
<h3 id="soluciones">Soluciones</h3>
<p>Sin importar la situación, el municipio debe de tener <strong>una estrategia digital unificadora</strong> para el manejo y mantenimiento de todas sus propiedades digitales. ¿Qué debería ser esa estrategia? Esa contestación solo la puede suplir el municipio.</p>
<p>Para nosotros lo principal es mantener la información de los municipios actualizada. Los municipios y el gobierno estatal deben de colaborar en esto. Parte de la estrategia del municipio debe ser el mantener su información actualizada pero necesitan las herramientas para hacerlo. Enviar un correo electrónico con información a actualizar no es suficiente. Sin saber cómo funciona pr.gov, pensamos que lo idóneo sería ofrecer una sección en esta página donde los municipios puedan mantener su información.</p>
<p>Dicho esto, la realidad es que los presupuestos y recursos disponibles para los municipios pueden ser bien limitados. Con esto en mente intentamos crear un listado de sugerencias que se pueden implementar por su cuenta y en etapas.</p>
<h4 id="para-los-municipios">Para los municipios</h4>
<p>Primordialmente necesitan una estrategia digital. La misma puede incluir:</p>
<ul>
<li>Identificar una persona en el municipio que tenga todo el conocimiento necesario para mantener la información al día.</li>
<li>Tener una estrategia para el manejo de dominios municipales.</li>
<li>Eliminar el uso y mención del dominios expirados en propiedades digitales.</li>
<li>Utilizar un dominio que no caduque que este manejado por alguna rama del gobierno de Puerto Rico.</li>
<li>Un buen ejemplo de esto lo es <a href="https://barranquitas.pr.gov/">https://barranquitas.pr.gov/</a>.</li>
<li>Tener un inventario de sus propiedades digitales que sea accesible al publico.</li>
<li>Consolidar esfuerzos en solo uno o dos propiedades digitales.</li>
<li>No tener propiedades digitales</li>
<li>Aunque esto suene contra producente, nuestra opinion es que no tener una presencia digital es mejor que tener una que confunda a los ciudadanos.</li>
<li>Colaborar con municipios que tengan recursos para compartir.</li>
<li>No existe una razón que los municipios no puedan compartir recursos para ofrecer una mejor experiencia y servicios digitales.</li>
<li>Proveer una manera de aceptar retroalimentación del ciudadano de una manera anónima.</li>
</ul>
<h4 id="para-el-gobierno-estatal">Para el gobierno estatal</h4>
<p>Esta es una excelente oportunidad para que el gobierno estatal, utilizando a <a href="http://www.prits.pr.gov/">PRITS</a>, tenga un rol de liderazgo y trabaje una estrategia digital para Puerto Rico.</p>
<ul>
<li>Tener un sistema de diseño que pueda asegurar la misma experiencia de usuario en varias propiedades digitales.</li>
<li>Un buen ejemplo de esto los es el <a href="https://designsystem.digital.gov/">US Web Design System</a>.</li>
<li>Una herramienta en <a href="https://pr.gov">pr.gov</a> que haga el mantenimiento de la información municipal un proceso sencillo y eficiente.</li>
<li>Tener un proceso de validación de data y notificar a los municipios cuando la data no este correcta.</li>
<li>Proveer una manera de aceptar retroalimentación del ciudadano de una manera anónima.</li>
</ul>
<h2 id="en-conclusión">En Conclusión</h2>
<p>El mantener las propiedades digitales de entidades de gobierno es altamente importante. Debería considerarse parte de los servicios esenciales que se le ofrece al ciudadano.</p>
<p>Los municipios necesitan tener una estrategia para mantener sus propiedades digitales con información actualizada y correcta. Esto crea confianza y mantiene al ciudadano informado en su día a día y en momentos de emergencia.</p>
<p>Para que esto sea eficiente el gobierno estatal necesita ofrecer herramientas para mantener la información en sus directorios al día. Estas herramientas y procesos de mantenimiento de data necesitan ser accesibles y fáciles de utilizar.</p>
<p>Al final del día la meta debe de ser mantener al ciudadano informado y combatir la desinformación. Con cambios pequeños estamos seguros que esto se puede lograr para el beneficio de todos.</p>
]]></content>
        </item>
        
    </channel>
</rss>
