<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title type="text">Esta couve flor</title>
<subtitle type="text">Software design is an art, and like any art it cannot be taught and learned as precise science, by means of theorems and formulas.</subtitle>
<generator uri="https://jekyllrb.com/">Jekyll</generator>
<link rel="self" type="application/atom+xml" href="https://www.estacouveflor.com/feed.xml" />
<link rel="alternate" type="text/html" href="https://www.estacouveflor.com/" />
<updated>2026-10-09T19:34:02+00:00</updated>
<id>https://www.estacouveflor.com/</id>
<author>
  <name>Cleiton Loiola</name>
  <uri>https://www.estacouveflor.com/</uri>
  <email>email@cleiton.dev</email>
</author>


<entry>
  <title type="html"><![CDATA[magic-cursor-wand: Give Your Pointer a Wand]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/magic-cursor-wand-pointer-effects/" />
  <id>https://www.estacouveflor.com/magic-cursor-wand</id>
  <published>2026-09-26T00:00:00+00:00</published>
  <updated>2026-09-26T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">A small browser library that draws chalk lines, glitter and soft clouds behind the pointer on any web page. One script tag or one function call is enough to start.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#what-it-does&quot; id=&quot;markdown-toc-what-it-does&quot;&gt;What it does&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#start-in-one-minute&quot; id=&quot;markdown-toc-start-in-one-minute&quot;&gt;Start in one minute&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#with-a-script-tag&quot; id=&quot;markdown-toc-with-a-script-tag&quot;&gt;With a script tag&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#with-a-bundler&quot; id=&quot;markdown-toc-with-a-bundler&quot;&gt;With a bundler&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#make-it-yours&quot; id=&quot;markdown-toc-make-it-yours&quot;&gt;Make it yours&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#a-few-technical-highlights&quot; id=&quot;markdown-toc-a-few-technical-highlights&quot;&gt;A few technical highlights&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#try-it&quot; id=&quot;markdown-toc-try-it&quot;&gt;Try it&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;A small effect that follows the pointer can make a page feel a bit alive. I built one as a library and published it on npm: &lt;a href=&quot;https://www.npmjs.com/package/magic-cursor-wand&quot;&gt;magic-cursor-wand&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What you get is simple to describe: chalk lines, glitter and soft clouds that follow the pointer on any web page. You can add it with one script tag, without a build step, or with one function call if your project uses a bundler.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/magic-cursor-wand/examples/&quot;&gt;&lt;img src=&quot;https://www.estacouveflor.com/magic-cursor-wand/demo.jpg&quot; alt=&quot;The demo page with a chalk line and the settings panel&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The best way to understand it is to play with it. Open the &lt;a href=&quot;https://www.estacouveflor.com/magic-cursor-wand/examples/&quot;&gt;live demo&lt;/a&gt;, move the pointer, hold the button down to draw, and change the sliders in the settings panel.&lt;/p&gt;

&lt;h2 id=&quot;what-it-does&quot;&gt;What it does&lt;/h2&gt;

&lt;p&gt;There are three built-in effects:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Chalk&lt;/strong&gt;: a chalk line while you hold the pointer button down. The line fades after a short time.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Glitter&lt;/strong&gt;: small particles that twinkle, turn and fall.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cloud&lt;/strong&gt;: soft clouds that rise and fade near the pointer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of them draw on a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canvas&lt;/code&gt;. If you never worked with it, a canvas is an HTML element that works like a blank sheet where JavaScript can paint pixels directly. The library puts one canvas on top of the page and sets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pointer-events: none&lt;/code&gt; on it, so your links and buttons below it continue to receive clicks as usual.&lt;/p&gt;

&lt;h2 id=&quot;start-in-one-minute&quot;&gt;Start in one minute&lt;/h2&gt;

&lt;h3 id=&quot;with-a-script-tag&quot;&gt;With a script tag&lt;/h3&gt;

&lt;p&gt;If you have a static page, a blog or anything without a bundler, add this element at the end of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script
  &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://cdn.jsdelivr.net/npm/magic-cursor-wand@0.2.0/dist/magic-cursor-wand.iife.js&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;integrity=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sha384-XxBXqYPuFEcQp51OYVOK/CslqB4ooezSzEvohIGISSD4E7Gxi3IOg09R3e/wKmF5&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;crossorigin=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;anonymous&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;data-wand-storage-key=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my-site-wand&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;data-wand-cursor=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;glow&quot;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;A few things are happening here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;integrity&lt;/code&gt; attribute holds a hash of the published file. The browser compares the file it downloads with this hash and refuses to run it if they are different. Thus the browser runs only the published file.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data-wand-storage-key&lt;/code&gt; keeps each visitor’s settings in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localStorage&lt;/code&gt;, so they stay after the visitor closes the page.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data-wand-cursor=&quot;glow&quot;&lt;/code&gt; adds a glow around the pointer. The build adds it only on devices with a pointer that can hover, like a mouse.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;with-a-bundler&quot;&gt;With a bundler&lt;/h3&gt;

&lt;p&gt;If your project uses npm and a bundler, install the package:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;npm &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;magic-cursor-wand&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;And create the wand:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createWand&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;magic-cursor-wand&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createWand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;That is it. To remove the canvas and all listeners later, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wand.destroy()&lt;/code&gt;. There is also a React hook, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;useWand&lt;/code&gt;, in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;magic-cursor-wand/react&lt;/code&gt;, which removes the wand when React removes the component.&lt;/p&gt;

&lt;h2 id=&quot;make-it-yours&quot;&gt;Make it yours&lt;/h2&gt;

&lt;p&gt;Each effect has its own settings, and each setting has safe limits. You pass the values you want to change and keep the defaults for the rest:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;nf&quot;&gt;createWand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;#7e23b3&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;chalk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;taper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;glitter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;spawnRate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;If you prefer to tune the values by eye, open the &lt;a href=&quot;https://www.estacouveflor.com/magic-cursor-wand/examples/&quot;&gt;demo&lt;/a&gt;, move the sliders and export the result. All fields and their limits are in the &lt;a href=&quot;https://www.estacouveflor.com/magic-cursor-wand/reference/configuration&quot;&gt;configuration reference&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;a-few-technical-highlights&quot;&gt;A few technical highlights&lt;/h2&gt;

&lt;p&gt;I tried to keep the library small and polite with the page that uses it. These are the parts I think are worth a mention:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;No dependencies in the core.&lt;/strong&gt; The canvas sleeps when nothing moves, and the frame loop also stops while the page is not visible. Each effect has a limit for its particles.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Safe on strict pages.&lt;/strong&gt; A Content Security Policy (CSP) is a set of rules a site sends to the browser to say which scripts and styles it may run. The library sets styles with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;element.style&lt;/code&gt; only and makes no network requests, so the core and the effects need no change to the policy.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Providers for the settings.&lt;/strong&gt; A provider is a small object that loads settings from somewhere and, if you want, saves them back. The package has providers for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localStorage&lt;/code&gt;, an HTTP endpoint and a server event stream. After each change, the wand saves the settings automatically.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Plugins and your own effects.&lt;/strong&gt; A plugin adds a feature without drawing on the canvas. The cursor glow and the settings panel are plugins. Effects, plugins and providers are all small objects, so you can write your own without a change to the core.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Kind to each visitor.&lt;/strong&gt; Some people ask their operating system to reduce motion on screen. Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;theme.motion&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;auto&lt;/code&gt;, and the wand obeys the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prefers-reduced-motion&lt;/code&gt; media query: glitter and clouds turn off, and the chalk line fades without drift.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is how a provider looks in code. This one keeps the settings of each visitor in the browser:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createWand&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;magic-cursor-wand&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;localStorageProvider&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;magic-cursor-wand/providers&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createWand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;providers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;localStorageProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;my-site-wand&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;The library works in Chrome and Edge 88, Firefox 85, Safari and Safari on iOS 14.5, and later versions. It is MIT licensed.&lt;/p&gt;

&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;

&lt;p&gt;If you want to see it before you read anything else, the &lt;a href=&quot;https://www.estacouveflor.com/magic-cursor-wand/examples/&quot;&gt;live demo&lt;/a&gt; is the place. The &lt;a href=&quot;https://www.estacouveflor.com/magic-cursor-wand/&quot;&gt;documentation&lt;/a&gt; has a getting-started guide, how-to pages and the full API reference. The package is on &lt;a href=&quot;https://www.npmjs.com/package/magic-cursor-wand&quot;&gt;npm&lt;/a&gt;, and the source code is on &lt;a href=&quot;https://github.com/klaygomes/magic-cursor-wand&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you put the wand on one of your pages, or you have an idea for a new effect, open an issue on GitHub or leave a comment below. I would be happy to see what you make with it.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/magic-cursor-wand-pointer-effects/&quot;&gt;magic-cursor-wand: Give Your Pointer a Wand&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on September 26, 2026.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[hurl-orchestra: AI first API automation testing]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/hurl-orchestra-ai-first-api-testing/" />
  <id>https://www.estacouveflor.com/hurl-orchestra</id>
  <published>2026-04-05T00:00:00+00:00</published>
  <updated>2026-04-05T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">Write each API test step as a small Hurl file, say which steps must pass first, and hurl-orchestra runs them in the right order and shows you which step broke.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#why-i-built-it&quot; id=&quot;markdown-toc-why-i-built-it&quot;&gt;Why I built it&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-it-looks&quot; id=&quot;markdown-toc-how-it-looks&quot;&gt;How it looks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-graph-in-plain-words&quot; id=&quot;markdown-toc-the-graph-in-plain-words&quot;&gt;The graph, in plain words&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#a-failure-stops-only-its-branch&quot; id=&quot;markdown-toc-a-failure-stops-only-its-branch&quot;&gt;A failure stops only its branch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#why-ai-first&quot; id=&quot;markdown-toc-why-ai-first&quot;&gt;Why “AI first”&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#under-the-hood&quot; id=&quot;markdown-toc-under-the-hood&quot;&gt;Under the hood&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#where-it-went-next&quot; id=&quot;markdown-toc-where-it-went-next&quot;&gt;Where it went next&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#try-it&quot; id=&quot;markdown-toc-try-it&quot;&gt;Try it&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;&lt;img src=&quot;https://www.estacouveflor.com/hurl-orchestra/logo-animated.svg&quot; alt=&quot;A cauliflower conductor beats time while a dependency graph lights up one wave at a time&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you test an API, you probably know this flow: log in, create a cart, add an item, check out. Each
step needs something from the step before it, like a token or an id. &lt;strong&gt;hurl-orchestra&lt;/strong&gt; is a small
tool that lets you write each of those steps as a small text file and then runs them in the right
order for you. When a step breaks, it tells you which one, and it keeps running everything that
does not depend on it.&lt;/p&gt;

&lt;p&gt;Its first release on PyPI was 0.4.1. The examples below use the current version, 0.11.0, so you can
copy them and run them as they are.&lt;/p&gt;

&lt;h2 id=&quot;why-i-built-it&quot;&gt;Why I built it&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://hurl.dev&quot;&gt;Hurl&lt;/a&gt; is a great tool. You write an HTTP request and its assertions in plain
text, and it runs them. The trouble starts when a suite outgrows one file. You split the tests, and
then you need something to call Hurl in the right order and to carry values like a login token from
one file to the next. Usually that “something” ends up being a shell script, and that script only
gets bigger.&lt;/p&gt;

&lt;p&gt;I wanted to declare the order instead of scripting it. So each file now says what it needs, and
the tool works out the rest.&lt;/p&gt;

&lt;h2 id=&quot;how-it-looks&quot;&gt;How it looks&lt;/h2&gt;

&lt;p&gt;A Hurl file gets a small header between two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;---&lt;/code&gt; lines (this header is called &lt;em&gt;frontmatter&lt;/em&gt;, and
it is plain YAML). Here is a login step:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;---
id: auth
outputs: [token]
---
POST {{base_url}}/login
{
  &quot;user&quot;: &quot;ada&quot;,
  &quot;password&quot;: &quot;{{password}}&quot;
}
HTTP 200
[Captures]
token: jsonpath &quot;$.token&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;A &lt;em&gt;capture&lt;/em&gt; is a value Hurl pulls out of a response, here the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;token&lt;/code&gt; from the JSON body. The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;outputs&lt;/code&gt; list says which captures this step shares with others. Now a step that needs it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;---
id: profile
deps: [auth]
---
GET {{base_url}}/profile
Authorization: Bearer {{auth_token}}
HTTP 200
[Asserts]
jsonpath &quot;$.user&quot; == &quot;ada&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deps: [auth]&lt;/code&gt; means “run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;auth&lt;/code&gt; first”. The token arrives as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;auth_token&lt;/code&gt;: the name of the
producer, an underscore, then the output name. I did it this way so that two steps can both capture
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;token&lt;/code&gt; without stepping on each other.&lt;/p&gt;

&lt;p&gt;Running it is two commands:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;hurl-orchestra
hurl-orchestra ./tests&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;Variables file: tests/.env
SUCCESS: auth [captured: token]
SUCCESS: profile [injected: auth_token]
Report saved to tests/report.zip&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.env&lt;/code&gt; file holds global values like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base_url&lt;/code&gt;, and every Hurl call gets it. It can sit next
to the tests, or anywhere else with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--env-file&lt;/code&gt;, for example at the root of your project. The run ends with exit code 0 when everything passes and 1 when something fails, so it
fits any CI.&lt;/p&gt;

&lt;h2 id=&quot;the-graph-in-plain-words&quot;&gt;The graph, in plain words&lt;/h2&gt;

&lt;p&gt;Behind the scenes, the files form a &lt;em&gt;DAG&lt;/em&gt;, a directed acyclic graph. That is a fancy name for a
set of steps connected by arrows (“this needs that”) where the arrows never loop back. From it,
hurl-orchestra builds &lt;em&gt;waves&lt;/em&gt;: a wave is every step whose dependencies are already done. Steps in
the same wave run at the same time; the next wave starts when the current one finishes.&lt;/p&gt;

&lt;p&gt;You can see the plan without sending a single request:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;hurl-orchestra &lt;span class=&quot;nt&quot;&gt;--dry-run&lt;/span&gt; tests/checkout.hurl&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;Resolved dependencies: add_item, auth, create_cart
Plan: 4 node(s)
  wave 1: auth
  wave 2: create_cart
  wave 3: add_item
  wave 4: checkout&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;Notice that I only asked for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;checkout.hurl&lt;/code&gt;, and it pulled in what checkout needs. The whole graph
is also validated before the first request: an unknown dependency, a cycle or a field with the
wrong type stops the run with a one-line error, so a broken graph never runs half a suite.&lt;/p&gt;

&lt;h2 id=&quot;a-failure-stops-only-its-branch&quot;&gt;A failure stops only its branch&lt;/h2&gt;

&lt;p&gt;This is the part I like the most. When a step fails, only the steps that depend on it are skipped.
Everything else keeps going, so one run shows you every broken flow, not only the first one.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.estacouveflor.com/hurl-orchestra/readme/score-light.webp&quot; alt=&quot;The interactive score: create_cart fails, add_item and checkout are skipped, catalog still passes&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the picture, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create_cart&lt;/code&gt; fails, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_item&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;checkout&lt;/code&gt; are skipped, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;catalog&lt;/code&gt;,
which does not need a cart, still passes. You can play with this on the
&lt;a href=&quot;https://www.estacouveflor.com/hurl-orchestra/#the-score&quot;&gt;docs home page&lt;/a&gt;: pick a step, make it
fail and watch the run.&lt;/p&gt;

&lt;h2 id=&quot;why-ai-first&quot;&gt;Why “AI first”&lt;/h2&gt;

&lt;p&gt;I want to be clear here: there is no model inside hurl-orchestra, and nothing to configure. “AI
first” means the files, the commands and the results are easy for a coding agent (Claude Code,
Codex and friends) to write, check and read:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The tests are plain-text Hurl files with a few frontmatter fields. No code to compile.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hurl-orchestra --dry-run --json tests&lt;/code&gt; prints the plan as JSON, including the variable names
each file can use, so an agent can check the graph before it sends any request.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--report-ctrf&lt;/code&gt; writes the results as &lt;em&gt;CTRF&lt;/em&gt;, the Common Test Report Format, a JSON file with
one test per request and the reason for each failure.&lt;/li&gt;
  &lt;li&gt;The whole documentation is published as a single
&lt;a href=&quot;https://www.estacouveflor.com/hurl-orchestra/llms-full.txt&quot;&gt;llms-full.txt&lt;/a&gt; file that you can
hand to an agent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same CTRF file also works for humans: the
&lt;a href=&quot;https://github.com/ctrf-io/github-test-reporter&quot;&gt;GitHub test reporter&lt;/a&gt; turns it into a test
summary in your GitHub Actions job.&lt;/p&gt;

&lt;h2 id=&quot;under-the-hood&quot;&gt;Under the hood&lt;/h2&gt;

&lt;p&gt;It is small on purpose. It needs Python 3.11 or later and has one dependency,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-frontmatter&lt;/code&gt;. The ordering comes from the standard library’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;graphlib&lt;/code&gt;, and the waves run
on a thread pool. Captured values reach Hurl through a private variables file for each call, so a
token never shows up in the process list.&lt;/p&gt;

&lt;h2 id=&quot;where-it-went-next&quot;&gt;Where it went next&lt;/h2&gt;

&lt;p&gt;Since the first release, the project kept growing. Some of what you saw above came later:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dry-run&lt;/code&gt;, and running a single file together with the steps it depends on.&lt;/li&gt;
  &lt;li&gt;The CTRF report for CI.&lt;/li&gt;
  &lt;li&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;retry&lt;/code&gt; policy with exponential backoff and jitter, for APIs that push back with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;429&lt;/code&gt; or a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;503&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;known_failures&lt;/code&gt;, to tolerate a failure you already understand, with a reason and an expiry
date. The report still shows it, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--strict&lt;/code&gt; turns it back into a failure.&lt;/li&gt;
  &lt;li&gt;The JSON plan for agents I mentioned above.&lt;/li&gt;
  &lt;li&gt;A proper &lt;a href=&quot;https://www.estacouveflor.com/hurl-orchestra/&quot;&gt;documentation site&lt;/a&gt;, with a getting
started guide, concepts and how-tos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;

&lt;p&gt;If you have a Hurl suite that is getting too big for one file, or a pile of shell scripts calling
Hurl in order, give it a try:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Docs: &lt;a href=&quot;https://www.estacouveflor.com/hurl-orchestra/&quot;&gt;estacouveflor.com/hurl-orchestra&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;PyPI: &lt;a href=&quot;https://pypi.org/project/hurl-orchestra/&quot;&gt;pypi.org/project/hurl-orchestra&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;GitHub: &lt;a href=&quot;https://github.com/klaygomes/hurl-orchestra&quot;&gt;klaygomes/hurl-orchestra&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if you have a flow it cannot express yet, open an issue or leave a comment below. I would like
to hear about it :)&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/hurl-orchestra-ai-first-api-testing/&quot;&gt;hurl-orchestra: AI first API automation testing&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on April 05, 2026.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Understanding the Heart of the STM32: The Clock System]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/entendendo-coracao-stm32/" />
  <id>https://www.estacouveflor.com/entendendo-coracao-stm32</id>
  <published>2025-08-09T00:00:00+00:00</published>
  <updated>2025-08-09T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">The STM32 clock system is its heart. It uses sources like HSI/HSE and the PLL to generate the 72 MHz SYSCLK, setting the pace for the whole MCU.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#the-stm32-clock-sources&quot; id=&quot;markdown-toc-the-stm32-clock-sources&quot;&gt;The STM32 Clock Sources&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#lets-get-to-know-each-one-of-them&quot; id=&quot;markdown-toc-lets-get-to-know-each-one-of-them&quot;&gt;Let’s get to know each one of them:&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-clock-path-from-start-to-end&quot; id=&quot;markdown-toc-the-clock-path-from-start-to-end&quot;&gt;The Clock Path: From Start to End&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#special-clocks&quot; id=&quot;markdown-toc-special-clocks&quot;&gt;Special Clocks:&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configuring-everything-in-code-systeminit&quot; id=&quot;markdown-toc-configuring-everything-in-code-systeminit&quot;&gt;Configuring Everything in Code (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SystemInit&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;The clock system is like the pulse of your microcontroller (MCU), the heart that sets the pace for everything. In the case of the STM32, which is a pretty complex chip full of peripherals, understanding how this “heart” works is essential.&lt;/p&gt;

&lt;p&gt;Think about it with me: not everything in your project needs to run at full speed. A simple blinking LED doesn’t need the same speed as processing data over USB. Besides that, the faster the clock, the more power the chip consumes and the more sensitive it gets to interference.&lt;/p&gt;

&lt;h2 id=&quot;the-stm32-clock-sources&quot;&gt;The STM32 Clock Sources&lt;/h2&gt;
&lt;p&gt;The STM32 has five clock sources, which are like the “power plants” that generate the rhythm for the chip.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The diagram below shows the STM32 clock tree. It shows how the clock sources (HSI, HSE, LSI, LSE) are selected, multiplied by the PLL, and distributed to the different buses and peripherals.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/images/stm32-clock-tree-RM0008.png&quot; alt=&quot;STM32 clock diagram, like Figure 11 of the RM0008 reference manual&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Looking at the diagram, we can split these sources into two categories:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Speed&lt;/strong&gt;: High-speed sources (for performance) and low-speed sources (for saving power).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Origin&lt;/strong&gt;: Internal sources (they already come in the chip) and external ones (you need to connect a quartz crystal).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;lets-get-to-know-each-one-of-them&quot;&gt;Let’s get to know each one of them:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSI&lt;/code&gt; (High Speed Internal)&lt;/strong&gt;: An 8 MHz internal oscillator. It is handy because it is already there, ready to use, but it is not the most accurate.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSE&lt;/code&gt; (High Speed External)&lt;/strong&gt;: The high-speed external oscillator (usually from 4 to 16 MHz). You connect a crystal on the outside, and it gives you a clock signal much more stable and accurate than the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSI&lt;/code&gt;. It is the recommended one for most serious applications.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LSI&lt;/code&gt; (Low Speed Internal)&lt;/strong&gt;: A little 40 kHz internal “clock”. It uses little power and is meant to feed peripherals that don’t need speed, like the Watchdog (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IWDG&lt;/code&gt;), which “watches” the system to check it hasn’t frozen.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LSE&lt;/code&gt; (Low Speed External)&lt;/strong&gt;: Another low-speed clock, but this one is external and very accurate, at 32.768 kHz. It is the ideal choice for the Real-Time Clock (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RTC&lt;/code&gt;), which needs to keep the time and date right, even while the rest of the chip is “sleeping”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLL&lt;/code&gt; (Phase-Locked Loop)&lt;/strong&gt;: This guy is not an original source, but a multiplier. It takes the signal from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSI&lt;/code&gt; or the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSE&lt;/code&gt; and multiplies it to generate a much higher frequency, reaching up to 72 MHz. It is the trick to make the STM32 run at full speed.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-clock-path-from-start-to-end&quot;&gt;The Clock Path: From Start to End&lt;/h2&gt;
&lt;p&gt;The diagram we saw before shows the whole clock flow. Let’s follow the path:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Selecting the Main Clock (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSCLK&lt;/code&gt;)&lt;/strong&gt;: The high-speed sources (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSI&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSE&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLL&lt;/code&gt;) arrive at a selector switch. Here, the system chooses which one will be the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSCLK&lt;/code&gt;, the main clock that will feed almost everything in the chip. Most of the time, we configure it to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLL&lt;/code&gt; at 72 MHz.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Distribution to the Buses&lt;/strong&gt;: Once it is chosen, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSCLK&lt;/code&gt; is distributed. It goes through frequency dividers (prescalers) to generate slower clocks for different parts of the chip:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HCLK&lt;/code&gt;&lt;/strong&gt;: It is the clock of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AHB&lt;/code&gt; bus, where the CPU, the memory and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DMA&lt;/code&gt; live. Usually, it runs at the same speed as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSCLK&lt;/code&gt; (72 MHz).&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCLK1&lt;/code&gt;&lt;/strong&gt;: It is the clock of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;APB1&lt;/code&gt; bus, where the slower peripherals are (up to 36 MHz), like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I2C&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USARTs&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAN&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCLK2&lt;/code&gt;&lt;/strong&gt;: Clock of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;APB2&lt;/code&gt; bus, which feeds the faster peripherals (up to 72 MHz), like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GPIO&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPI1&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ADC&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;special-clocks&quot;&gt;Special Clocks:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB&lt;/code&gt;&lt;/strong&gt;: The USB peripheral needs an exact 48 MHz clock. This signal comes straight from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLL&lt;/code&gt;, going through a special divider.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RTC&lt;/code&gt;&lt;/strong&gt;: The real-time clock has its own selector switch, and it can use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LSE&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LSI&lt;/code&gt; or even the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSE&lt;/code&gt; divided by 128.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MCO&lt;/code&gt; (Microcontroller Clock Output)&lt;/strong&gt;: A real lifesaver for debugging! You can configure a pin (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PA8&lt;/code&gt;) to “spit out” one of the internal clocks. That way, you can measure it with an oscilloscope and be sure everything is configured right.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;configuring-everything-in-code-systeminit&quot;&gt;Configuring Everything in Code (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SystemInit&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;All this configuration is done at the start of your code’s execution, inside a function called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SystemInit&lt;/code&gt;. By default, STM32 projects already come with this function configured for the following scenario:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Enable the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSE&lt;/code&gt; (assuming an 8 MHz external crystal).&lt;/li&gt;
  &lt;li&gt;Configure the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLL&lt;/code&gt; to multiply the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HSE&lt;/code&gt; by 9 (8 MHz * 9 = 72 MHz).&lt;/li&gt;
  &lt;li&gt;Select the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLL&lt;/code&gt; as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSCLK&lt;/code&gt; source.&lt;/li&gt;
  &lt;li&gt;Configure the dividers of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AHB&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;APB1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;APB2&lt;/code&gt; buses.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The final result is what we see in most projects:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Clock Name&lt;/th&gt;
      &lt;th&gt;Default Speed&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SYSCLK&lt;/code&gt; (System Clock)&lt;/td&gt;
      &lt;td&gt;72 MHz&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HCLK&lt;/code&gt; (AHB Bus Clock)&lt;/td&gt;
      &lt;td&gt;72 MHz&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCLK1&lt;/code&gt; (APB1 Bus Clock)&lt;/td&gt;
      &lt;td&gt;36 MHz&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCLK2&lt;/code&gt; (APB2 Bus Clock)&lt;/td&gt;
      &lt;td&gt;72 MHz&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLL&lt;/code&gt; Clock&lt;/td&gt;
      &lt;td&gt;72 MHz&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;And the most important thing of all: &lt;strong&gt;no peripheral works if its clock is not enabled!&lt;/strong&gt; Whenever you are going to use a timer, a serial port or anything else, the first thing to do in code is to turn on its “clock”.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/entendendo-coracao-stm32/&quot;&gt;Understanding the Heart of the STM32: The Clock System&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on August 09, 2025.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[mini-painel: A Hobby Log About Talking to a Tiny USB Screen in C]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/mini-painel/" />
  <id>https://www.estacouveflor.com/mini-painel</id>
  <published>2025-01-20T00:00:00+00:00</published>
  <updated>2025-01-20T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">A work-in-progress hobby project in C that drives a cheap 3.5-inch USB display from a Mac. What works today, what I&apos;m still poking at, and how to build it.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#it-started-with-six-bytes&quot; id=&quot;markdown-toc-it-started-with-six-bytes&quot;&gt;It started with six bytes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-works-today&quot; id=&quot;markdown-toc-what-works-today&quot;&gt;What works today&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#a-few-details-from-under-the-hood&quot; id=&quot;markdown-toc-a-few-details-from-under-the-hood&quot;&gt;A few details from under the hood&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#building-it&quot; id=&quot;markdown-toc-building-it&quot;&gt;Building it&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#using-the-library&quot; id=&quot;markdown-toc-using-the-library&quot;&gt;Using the library&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-im-still-exploring&quot; id=&quot;markdown-toc-what-im-still-exploring&quot;&gt;What I’m still exploring&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#try-it&quot; id=&quot;markdown-toc-try-it&quot;&gt;Try it&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;&lt;strong&gt;mini-painel&lt;/strong&gt; is a hobby project of mine, and it is not finished. The idea is simple: take one of
those cheap 3.5-inch USB screens and turn it into a small status panel for the desk, showing things
like build status, alerts or who is on call, updating in the background with no browser tab
involved.&lt;/p&gt;

&lt;p&gt;This post is a log of where it stands. What already works, what I’m still exploring, and how you
can build it and play with it yourself. The code is on
&lt;a href=&quot;https://github.com/klaygomes/mini-painel&quot;&gt;GitHub&lt;/a&gt;, written in C99.&lt;/p&gt;

&lt;h2 id=&quot;it-started-with-six-bytes&quot;&gt;It started with six bytes&lt;/h2&gt;

&lt;p&gt;The very first commit was a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.c&lt;/code&gt;. It opened the serial port at 115200 baud (bits per
second), configured it in &lt;em&gt;raw mode&lt;/em&gt; (no line buffering, no echo, the terminal does not touch your
bytes) and sent this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;That is the &lt;strong&gt;HELLO&lt;/strong&gt; handshake. You send six bytes of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x45&lt;/code&gt; and the display answers with six
bytes of its own, which tell you which model you are talking to. Everything else was built on top of
that small conversation.&lt;/p&gt;

&lt;p&gt;Here is the part I like the most: from the computer’s point of view, this screen is not a monitor.
It shows up as a serial device (something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/tty.usbmodem...&lt;/code&gt; on macOS), the same kind of
port you would use to talk to a microcontroller. If you have read my STM32 posts, this will feel
familiar: read the protocol, pack bits in the right order, and respect the timing of the device.&lt;/p&gt;

&lt;h2 id=&quot;what-works-today&quot;&gt;What works today&lt;/h2&gt;

&lt;p&gt;At this point the repo can:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Find and open the screen&lt;/strong&gt; on its own, by scanning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/tty.usbmodem*&lt;/code&gt; and picking the first
device that answers HELLO.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Control the display:&lt;/strong&gt; brightness and orientation. The XuanFang code path also knows how to
set the RGB LED on the back of the Flagship model.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Draw a dashboard&lt;/strong&gt; out of rows of components, using Cairo (a 2D drawing library) to render
them. There are components for deploys, CI status, alerts, outages, on-call, sprint progress, PR
review queue, sparklines (tiny line charts without axes), error rates and SLA gauges.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Split content into pages&lt;/strong&gt; when it does not fit on one screen, and cycle through them.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Run tests without hardware&lt;/strong&gt;, using a fake serial backend. CI builds and runs them on every
push, including a pass with AddressSanitizer and UBSan, compiler tools that catch memory and
undefined-behavior bugs at runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;a-few-details-from-under-the-hood&quot;&gt;A few details from under the hood&lt;/h2&gt;

&lt;p&gt;Some things that were fun to get right, all written down in the repo’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doc/&lt;/code&gt; folder:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Pixel format.&lt;/strong&gt; Your code draws in RGB888, 8 bits per color channel, 3 bytes per pixel. The
screen wants &lt;em&gt;RGB565&lt;/em&gt;, which squeezes a pixel into 16 bits (5 bits red, 6 green, 5 blue). The
library converts before sending.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Packed commands.&lt;/strong&gt; A command is a 6-byte frame where the x/y coordinates are packed across byte
boundaries, with the command byte last. Bit shifting, the classic embedded pastime.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Chunks and pauses.&lt;/strong&gt; Bitmaps go out in chunks of 2560 bytes (320 × 8 rows), which avoids USB
buffer stalls on macOS, plus a 50 ms pause after each bitmap to avoid corrupted frames.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Inverted brightness.&lt;/strong&gt; On the protocol the current build uses, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; means brightest and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;255&lt;/code&gt;
means darkest. The public API hides that and takes a plain percentage from 0 to 100.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;building-it&quot;&gt;Building it&lt;/h2&gt;

&lt;p&gt;You need CMake 3.10 or newer, pkg-config, Cairo and a C99 compiler. The serial code uses POSIX
termios and the README lists macOS as the target. On a Mac:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;cairo
git clone https://github.com/klaygomes/mini-painel
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;mini-painel
&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;build &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;build
cmake ..
make&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;To run the tests, which also write one image per component into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin/&lt;/code&gt; so you can look at them:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;cmake .. &lt;span class=&quot;nt&quot;&gt;-DBUILD_TESTING&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ON
make
ctest &lt;span class=&quot;nt&quot;&gt;--output-on-failure&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;using-the-library&quot;&gt;Using the library&lt;/h2&gt;

&lt;p&gt;The API is small: create a dashboard, add rows of components, render a page and push the frame to
the device. This is the main loop from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;examples/demo.c&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;panel_open_auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;No device found; running in headless mode.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;panel_set_orientation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XF_ORIENT_LANDSCAPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;panel_set_brightness&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dashboard_render_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;dashboard_render_page failed&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;xf_bitmap_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DISPLAY_W&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DISPLAY_H&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rgb888&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;panel_display_bitmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;panel_display_bitmap failed&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Page %d / %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PAGE_INTERVAL_S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;Notice that the demo keeps running without a screen, which is handy for working on the layout
before plugging anything in.&lt;/p&gt;

&lt;p&gt;A component is a plain struct with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;render()&lt;/code&gt; callback that fills a pixel buffer, and an optional
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fetch()&lt;/code&gt; callback that refreshes its data before each frame. Three macros create them, depending on
whether the component is static, reads data you own, or fetches live data:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;n&quot;&gt;xf_component_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logo&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XF_COMPONENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render_logo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;xf_component_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XF_COMPONENT_DATA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;xf_component_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XF_COMPONENT_LIVE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fetch_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_clock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time_ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;what-im-still-exploring&quot;&gt;What I’m still exploring&lt;/h2&gt;

&lt;p&gt;This is where the “work in progress” part really shows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Which protocol, which screen.&lt;/strong&gt; The README talks about the XuanFang 3.5” display (Rev B or
Flagship), and the repo has code for that protocol. But the project notes are written against a
display that identifies as a UsbMonitor 3.5” and speaks what they call the Turing Rev A protocol,
and that is what the current build uses. Both implementations live side by side for now.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Driving it without C.&lt;/strong&gt; There is a JSON command API, where you send an array of commands like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&quot;op&quot;:&quot;row.add&quot;, ...}&lt;/code&gt; and get a JSON reply back, plus a small WebSocket daemon that accepts
those commands and pushes each rendered frame to the screen.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Feeding it real data.&lt;/strong&gt; The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playground/&lt;/code&gt; folder has two experiments in Python: one polls
GitHub through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh&lt;/code&gt; CLI for PR and build data, the other shows Claude Code session state using
hook scripts. The folder name says it all: these are experiments, not features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the docs also lag behind the code (the getting-started page still shows an older
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;panel_display_bitmap&lt;/code&gt; signature), which is a good sign that things are still moving.&lt;/p&gt;

&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;

&lt;p&gt;If you have one of these screens in a drawer and enjoy this kind of tinkering, give
&lt;a href=&quot;https://github.com/klaygomes/mini-painel&quot;&gt;mini-painel&lt;/a&gt; a try. Just keep in mind it is a hobby build
and rough around the edges. If you get it running on a different model, or have an idea, open an
issue or leave a comment below. I would love to hear about it.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/mini-painel/&quot;&gt;mini-painel: A Hobby Log About Talking to a Tiny USB Screen in C&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on January 20, 2025.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Free tools for embedded development]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/stm32-sem-usar-ide/" />
  <id>https://www.estacouveflor.com/stm32-sem-usar-ide</id>
  <published>2021-10-12T00:00:00+00:00</published>
  <updated>2021-10-12T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">A detailed step-by-step guide on how to install free tools for Cortex-M development</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#arm-embedded-tool-chain&quot; id=&quot;markdown-toc-arm-embedded-tool-chain&quot;&gt;Arm Embedded Tool Chain&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#gnulinux&quot; id=&quot;markdown-toc-gnulinux&quot;&gt;GNU/Linux&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#windows&quot; id=&quot;markdown-toc-windows&quot;&gt;Windows&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mac&quot; id=&quot;markdown-toc-mac&quot;&gt;Mac&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#openocd&quot; id=&quot;markdown-toc-openocd&quot;&gt;OpenOCD&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#gnulinux-1&quot; id=&quot;markdown-toc-gnulinux-1&quot;&gt;GNU/Linux&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#windows-1&quot; id=&quot;markdown-toc-windows-1&quot;&gt;Windows&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mac-1&quot; id=&quot;markdown-toc-mac-1&quot;&gt;Mac&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gnu-make&quot; id=&quot;markdown-toc-gnu-make&quot;&gt;GNU Make&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#linux-and-mac&quot; id=&quot;markdown-toc-linux-and-mac&quot;&gt;Linux and Mac&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#windows-2&quot; id=&quot;markdown-toc-windows-2&quot;&gt;Windows&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cmsis&quot; id=&quot;markdown-toc-cmsis&quot;&gt;CMSIS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;Below is the step-by-step you need to follow to download the tools required for development on
Cortex-M controllers. In this article I mention some information specific to STM, but the guide
works for any vendor.&lt;/p&gt;

&lt;h2 id=&quot;arm-embedded-tool-chain&quot;&gt;Arm Embedded Tool Chain&lt;/h2&gt;

&lt;p&gt;It contains the set of tools needed to validate, test and compile programs developed for 32-bit
Cortex processors (the Cortex-M, Cortex-R and A models).&lt;/p&gt;

&lt;h3 id=&quot;gnulinux&quot;&gt;GNU/Linux&lt;/h3&gt;

&lt;p&gt;Download the latest version available on the &lt;a href=&quot;https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads&quot;&gt;official site.&lt;/a&gt;
Preferably, save the file in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Once that is done, extract the files and delete the compressed file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo tar xjf gcc-arm-none-eabi-your-version.bz2 -C /usr/share/
rm gcc-arm-none-eabi-your-version.bz2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After that, you should create symbolic links so these programs are available across the whole
system:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo ln -s /usr/share/gcc-arm-none-eabi-your-version/bin/* /usr/bin/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You may also need to install some additional tools, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libncurses&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libtinfo&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;arm-none-eabi-gcc --version
arm-none-eabi-g++ --version
arm-none-eabi-gdb --version
arm-none-eabi-size --version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To check the installation, open a new terminal window and type:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;arm-none-eabi-gcc --version
arm-none-eabi-g++ --version
arm-none-eabi-gdb --version
arm-none-eabi-size --version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;Download the installer from the &lt;a href=&quot;https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads&quot;&gt;official site.&lt;/a&gt;
Then run it and follow the Wizard’s instructions.&lt;/p&gt;

&lt;p&gt;To check the installation, open a CMD window (Windows key + R, type CMD) and type:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;arm-none-eabi-gcc --version
arm-none-eabi-g++ --version
arm-none-eabi-gdb --version
arm-none-eabi-size --version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;mac&quot;&gt;Mac&lt;/h3&gt;

&lt;p&gt;The easiest way to install this and the other tools is using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Brew&lt;/code&gt;; if you don’t have it yet,
you can install it by running the command below:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once it is installed, you only need to run the command below:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install --cask gcc-arm-embedded
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To check the installation, open a new terminal window and type:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;arm-none-eabi-gcc --version
arm-none-eabi-g++ --version
arm-none-eabi-gdb --version
arm-none-eabi-size --version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;openocd&quot;&gt;OpenOCD&lt;/h2&gt;

&lt;p&gt;It is the tool that handles the communication between the computer and the controller; it is used
mainly to help with debugging, but it can also be used as a flasher. It works as a GDB server,
which receives the requests made by GDB clients, and also as a telnet server.&lt;/p&gt;

&lt;h3 id=&quot;gnulinux-1&quot;&gt;GNU/Linux&lt;/h3&gt;

&lt;p&gt;For the most recent versions of OpenOCD, you will need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libftdi&lt;/code&gt; (even if you have an ST-Link
connector).&lt;/p&gt;

&lt;p&gt;The easiest way to install it is using your package manager.&lt;/p&gt;

&lt;p&gt;On Debian, for example, you need to run:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt install openocd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check which package manager you have; it probably won’t be much different from this.&lt;/p&gt;

&lt;p&gt;To check that it was installed correctly, type:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openocd --version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The output should be something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;windows-1&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;The easiest way is through &lt;a href=&quot;https://chocolatey.org/install&quot;&gt;chocolatey&lt;/a&gt;, a package manager made
specifically for Windows.
Download choco through that link, install it, and then run this command in the command
prompt:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;choco install openocd 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also download the latest version straight from the repository through &lt;a href=&quot;https://github.com/openocd-org/openocd/releases/&quot;&gt;this link&lt;/a&gt;.
The file is at the end of the page and its name will be something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openocd-v0.x.x-i686-w64-mingw32.tar.gz&lt;/code&gt;,
where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.x&lt;/code&gt; is the number of the latest version available.&lt;/p&gt;

&lt;p&gt;To check that it was installed correctly, open the prompt and type:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openocd --version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The output should be something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;mac-1&quot;&gt;Mac&lt;/h3&gt;

&lt;p&gt;On the Mac, as always, the easiest way to install it is using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Brew&lt;/code&gt;, with the
command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install open-ocd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To check that it was installed correctly, type:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openocd --version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The output should be something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;gnu-make&quot;&gt;GNU Make&lt;/h2&gt;

&lt;p&gt;A tool used to help run repetitive tasks; it also figures out which parts of the program need to
be recompiled and runs the related tasks automatically.&lt;/p&gt;

&lt;h3 id=&quot;linux-and-mac&quot;&gt;Linux and Mac&lt;/h3&gt;

&lt;p&gt;It already comes installed by default on these systems.&lt;/p&gt;

&lt;h3 id=&quot;windows-2&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;The easiest way is through &lt;a href=&quot;https://chocolatey.org/install&quot;&gt;chocolatey&lt;/a&gt;, a package manager made
specifically for Windows.
Download choco through that link, install it, and then run this command in the command
prompt:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;choco install make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also install it directly through this &lt;a href=&quot;http://gnuwin32.sourceforge.net/install.html&quot;&gt;link&lt;/a&gt;,
but pay attention: unlike &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;choco&lt;/code&gt;, you will have to install the dependencies and do the
configuration by hand.&lt;/p&gt;

&lt;h2 id=&quot;cmsis&quot;&gt;CMSIS&lt;/h2&gt;

&lt;p&gt;The best way to get the most recent version is straight from the GitHub repository, at
https://github.com/STMicroelectronics/STM32CubeF1/tags. You can download the files by clicking
the “zip” link, right next to the date of the latest release. If you want, you can also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clone&lt;/code&gt;
the latest version straight from the project’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;If you are following our course on YouTube, run the code below in the root directory of your
project:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git clone &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt; 1 ssh@github.com:STMicroelectronics/STM32CubeF1.git stm32 &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_&lt;/span&gt;/.git&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;It downloads the most recent files into a directory called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stm32&lt;/code&gt;, wherever you run it.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;With just the tools above, you will be able to develop for any processor in the Cortex-M, A and R
lines, on every platform and operating system. And as you may have noticed, they have evolved a
lot, and installing them gets easier every time. Now you just need to download them and start
programming.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/stm32-sem-usar-ide/&quot;&gt;Free tools for embedded development&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on October 12, 2021.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Using GNU Make as your Dotfiles manager]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/dotfiles-configuration/" />
  <id>https://www.estacouveflor.com/dotfiles-configuration</id>
  <published>2021-06-20T00:00:00+00:00</published>
  <updated>2021-06-20T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">It tells you how you can manage your dotfiles without any external dependencies.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#the-motivation&quot; id=&quot;markdown-toc-the-motivation&quot;&gt;The motivation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-gnu-make-for-rescue&quot; id=&quot;markdown-toc-the-gnu-make-for-rescue&quot;&gt;The GNU Make for rescue&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-makefile&quot; id=&quot;markdown-toc-the-makefile&quot;&gt;The Makefile&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;For the last years, I got used to set everything on my computer by hand. Yes, I know it is very 
inefficient. But, I barely have to format my laptop. I can count on one hand how many times I have
formatted my computer in the last 4 years.&lt;/p&gt;

&lt;h2 id=&quot;the-motivation&quot;&gt;The motivation&lt;/h2&gt;

&lt;p&gt;In Brazil, as I was working remotely for the last couple of years, I got used to using my computer
to do my job and personal stuff. So, everything that I needed was there. It lasted until I had to 
move, and now as I’m working in a Bank, things have changed. I saw myself being obligated to use 
the company computer and this computer is really restricted. To make things worse, I had to format 
more than one time since I started working (The first time was my fault as I messed with the 
configuration. The second time, an Apple update and compatibility issue made my computer unusable).&lt;/p&gt;

&lt;p&gt;This situation taught me that I needed a dotfile repository where I must manage my configuration
files.  Well, the first thing I did was look at which options we had as working solutions. The most
know one was GNU Stow. Well, I may say it really shines when you have a very complex configuration
tree with many files. It didn’t appear to make sense for my case, where I had just a few
configurations.&lt;/p&gt;

&lt;p&gt;I wanted something that I could use with a new installation of a Mac OS and with only one command,
install everything I need and all the boring stuff, and for using stow, I had to at least install 
it as it does not come in Mac by default.&lt;/p&gt;

&lt;h2 id=&quot;the-gnu-make-for-rescue&quot;&gt;The GNU Make for rescue&lt;/h2&gt;

&lt;p&gt;I was procrastinating on studying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Make&lt;/code&gt; for the last years, so I thought it could be good to learn 
Make and do something relevant. And it was a perfect choice; before I started messing with my 
configuration files, I downloaded the GNU Make documentation (a 230 pages PDF), and I started 
reading it. I may say I got amazed at how it is straightforward, sometimes, of course, the 
documentation gets really dense (try to read the explanation for autovars, for example), but if you
read with care, you will start getting the point of how it was projected.&lt;/p&gt;

&lt;p&gt;In the end, I may say I’m thrilled with the result, and I would like to show what I have learned in
this process.&lt;/p&gt;

&lt;h2 id=&quot;the-makefile&quot;&gt;The Makefile&lt;/h2&gt;

&lt;p&gt;Bellow is my actual make file; Basically, it manages the creation and copy of configuration files
to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config&lt;/code&gt; folder as they are changed on the repository folder, keep them in sync. I will 
try to explain line by line what I’m doing and how you may change it to fit your needs.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-make&quot; data-lang=&quot;make&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;CONFIG&lt;/span&gt;		&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;HOME&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;/.config/

&lt;span class=&quot;nv&quot;&gt;VIM&lt;/span&gt; 		&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;addprefix &lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;CONFIG&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;, &lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;wildcard nvim/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; nvim/&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;ZSH&lt;/span&gt;		&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;addprefix &lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;CONFIG&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;, &lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;wildcard zsh/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;ZSH_CONFIG&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;HOME&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;/.zshrc
&lt;span class=&quot;nv&quot;&gt;GIT&lt;/span&gt;		&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;HOME&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;/.gitconfig
&lt;span class=&quot;nv&quot;&gt;BREW&lt;/span&gt;		&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;HOME&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;/Brewfile
&lt;span class=&quot;nv&quot;&gt;BREW_ENV&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;HOME&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;/.brewenv
&lt;span class=&quot;nv&quot;&gt;MAC&lt;/span&gt;		&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;CONFIG&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;mac/install.sh
&lt;span class=&quot;nv&quot;&gt;NODE&lt;/span&gt;		&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;CONFIG&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;node/globals

&lt;span class=&quot;nv&quot;&gt;CREATE_TARGET_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Directory &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; was not found, creating...&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;.PHONY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;all mac brew git vim&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;| mac brew zsh git node vim;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;.SECONDEXPANSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;$(VIM)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$$(subst ${CONFIG}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,,&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; $$@)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@$(&lt;/span&gt;call CREATE_TARGET_DIR&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; 					 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Including &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; configuration to &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; 	&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
 		&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;					&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;							 

&lt;span class=&quot;nl&quot;&gt;.SECONDEXPANSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;$(ZSH)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$$(subst ${CONFIG}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,,&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; $$@)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@$(&lt;/span&gt;call CREATE_TARGET_DIR&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Including &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; configuration to &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;setup.sh&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; 	 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;@&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;CONFIG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; 	&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; 					 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;source &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;CONFIG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&apos;;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;                                &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
			&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;$${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;ZSH_CONFIG&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;$${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;ZSH_CONFIG&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                              &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;$(MAC)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mac/install.sh&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@$(&lt;/span&gt;call CREATE_TARGET_DIR&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;^&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;@&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@${&lt;/span&gt;@&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;$(GIT)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(wildcard git/*) &lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;./git/install.sh ./git/.gitconfig

&lt;span class=&quot;nl&quot;&gt;$(BREW)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(wildcard brew/*)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;./brew/install.sh
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; ./brew/Brewfile &lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;HOME&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;/Brewfile
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;BREW_ENV&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 								&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;$${&lt;/span&gt;HOMEBREW_PREFIX&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;/bin/brew bundle &lt;span class=&quot;nt&quot;&gt;--file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;HOME&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;/Brewfile &lt;span class=&quot;nt&quot;&gt;--force&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	./brew/setup.sh

&lt;span class=&quot;nl&quot;&gt;$(NODE)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;node/globals&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;xargs &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 4 npm &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; &amp;lt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;nf&quot;&gt;$(VIM)&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;nf&quot;&gt;$(GIT)&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;brew&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(BREW)&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;mac&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;nf&quot;&gt;$(MAC)&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(NODE)&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;zsh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;nf&quot;&gt;$(ZSH)&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;node/globals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;mac/install&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;Lines 1 to 10 are variables that hold the list of files.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The syntax &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(something)&lt;/code&gt; is used as the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${something}&lt;/code&gt;, which means you want to
interpolate the current value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;something&lt;/code&gt;, into its current value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(something ${other}...)&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(something $(other)...)&lt;/code&gt; tells make you are calling the 
function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;something&lt;/code&gt; passing the value of the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;other&lt;/code&gt; as its first argument (you may give 
more than one just separating them with spaces).&lt;/p&gt;

&lt;p&gt;The attribution symbol &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:=&lt;/code&gt; tells make I want these values to be assessed only one time while the 
file is being parsed; otherwise, if you use simply &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;, it means this value will be evaluated every
time you reference it.&lt;/p&gt;

&lt;p&gt;Note how it is desirable as I use these variables all over the place. I’m calling the special 
functions &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addprefix&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wildcard&lt;/code&gt; and doing expression expansions (getting everything 
recursively inside the directories using ** ).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addprefix&lt;/code&gt; as its name suggests, it adds a prefix for each item of a list.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wildcard&lt;/code&gt; returns a list of files fetched by the expressions expansions. This function accepts 
more than one argument.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, I’m getting all files from these directories and adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${CONFIG}&lt;/code&gt;, which in turns 
points to ${HOME}/.config/ (usually ~/.config).&lt;/p&gt;

&lt;p&gt;However, the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE_TARGET_DIR&lt;/code&gt;, on line 12, is used as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function&lt;/code&gt; I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; as it must
be evaluated every time it is called.&lt;/p&gt;

&lt;p&gt;On line 14, I used a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;directive&lt;/code&gt; called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.PHONY&lt;/code&gt;, which informs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipes&lt;/code&gt; its output 
should not be considered a valid file, or better, which ones do not produce an output file. On our 
Makefile, they are defined on lines 60-69 and are used only to tell make I want to run them when 
any file they depend on was changed. Note they use the variable with the list of files I got on 
lines 1-10.&lt;/p&gt;

&lt;p&gt;On line 16, I created a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipe&lt;/code&gt; called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all&lt;/code&gt;, which calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;in sequence&lt;/code&gt; the recipes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt;. Note I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:|&lt;/code&gt; to force &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; to execute in sequence.&lt;/p&gt;

&lt;p&gt;The first recipe inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Makefile&lt;/code&gt; is called by default whenever make is called without arguments;
in our file, it is the recipe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On lines 18-55 are the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipes&lt;/code&gt; for all the Makefile. Before I start explaining them I should give
a little introduction to how they are formed.&lt;/p&gt;

&lt;p&gt;A Makefile consists of a set of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipes&lt;/code&gt;. A recipe generally looks like this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;targets: prerequisites
   command
   command
   command
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;The targets are file names separated by spaces. Typically, there is only one per rule.&lt;/li&gt;
  &lt;li&gt;The commands are a series of steps typically used to make the target(s). These need to start with
a tab character, not spaces.&lt;/li&gt;
  &lt;li&gt;The prerequisites are file names separated by spaces. These files need to exist before the 
commands for the target are run. These are also called dependencies.  Each recipe can be called 
independently and represent a single file on the system. (fit not tagged as .PHONY)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let’s analyze the first recipe we have at lines 26-58.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.SECONDEXPANSION&lt;/code&gt; is a directive that tells Make to expand the variables contained into the 
following recipe more than once.  You may ask why?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On line 19; first, I declare the target from the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(VIM)&lt;/code&gt;, which we know is a list of 
files contained inside the ${CONFIG}/vim folder; these values are used as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt; parameters to the 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dependencies&lt;/code&gt; PLUS (it is essential) the CURRENT target which trigged the rule.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Translation: It creates a unique &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recipe&lt;/code&gt; for each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;target&lt;/code&gt; using only one dependency, that is, 
the target itself without the ${CONFIG} prefix.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On line 20, I call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function&lt;/code&gt; CREATE_TARGET_DIR, responsible for creating the target directory 
if it does not exist.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(@D)&lt;/code&gt;; it is an especial auto variable that expands to the directory of the 
current target.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note: You can declare variables as $(a), ${b} or $c inside Makefiles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now the variables:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$^&lt;/code&gt; expands to the first dependency of the current target (our case, it is the same file without
the ${CONFIG});&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$@&lt;/code&gt; extends to the target which fired the recipe;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${@F}&lt;/code&gt; same as before, but only its filename;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I must mention that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; before each recipe command; it tells Make to not print to the stdout the bash command 
before executing it.&lt;/li&gt;
  &lt;li&gt;Inside bash scripts, if you want to use bash variables, you must include an extra &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;, so it 
will be escaped and not interpreted as a Make variable itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See, it is possible to use the result of functions/variables inside targets and dependencies as 
actual values, so I use it a lot throughout the entire file.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;It was an easy task, and I’m thrilled with the results as I had to learn a lot to make it possible.
In the end, it was a clean solution that it will last a good time inside my workflow.&lt;/p&gt;

&lt;p&gt;You may also be interested in the final result &lt;a href=&quot;https://github.com/klaygomes/dotfiles&quot;&gt;in my public dotfiles repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/dotfiles-configuration/&quot;&gt;Using GNU Make as your Dotfiles manager&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on June 20, 2021.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[MiniReact: a tiny React-like library to see what happens under the hood]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/mini-react/" />
  <id>https://www.estacouveflor.com/mini-react</id>
  <published>2018-08-23T00:00:00+00:00</published>
  <updated>2018-08-23T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">A tiny React-like library I wrote as a take-home exercise, with class components, a virtual DOM, a synchronous setState and a simple diff-and-patch step.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#what-you-get&quot; id=&quot;markdown-toc-what-you-get&quot;&gt;What you get&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#two-words-before-we-start&quot; id=&quot;markdown-toc-two-words-before-we-start&quot;&gt;Two words before we start&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#writing-a-component&quot; id=&quot;markdown-toc-writing-a-component&quot;&gt;Writing a component&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#two-differences-from-react&quot; id=&quot;markdown-toc-two-differences-from-react&quot;&gt;Two differences from React&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-it-works-three-phases&quot; id=&quot;markdown-toc-how-it-works-three-phases&quot;&gt;How it works: three phases&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#constructing&quot; id=&quot;markdown-toc-constructing&quot;&gt;Constructing&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#patching&quot; id=&quot;markdown-toc-patching&quot;&gt;Patching&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#unmounting&quot; id=&quot;markdown-toc-unmounting&quot;&gt;Unmounting&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#events-without-leaking-listeners&quot; id=&quot;markdown-toc-events-without-leaking-listeners&quot;&gt;Events without leaking listeners&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tests&quot; id=&quot;markdown-toc-tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#running-it&quot; id=&quot;markdown-toc-running-it&quot;&gt;Running it&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;If you use React every day, you probably call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setState&lt;/code&gt; without thinking about what happens next. I had to think about it, because I wrote a small version of it as a take-home exercise for a job interview. It is called &lt;strong&gt;MiniReact&lt;/strong&gt;, and in this post I will show you what it does, how it is organized and where it is intentionally simpler than React.&lt;/p&gt;

&lt;p&gt;I published it to npm in August 2018, and you can find the whole code &lt;a href=&quot;https://github.com/klaygomes/mini-react&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-you-get&quot;&gt;What you get&lt;/h2&gt;

&lt;p&gt;MiniReact is not a complete React implementation, and it does not try to be. I wrote it with four ideas in mind: immutability, separation of concerns, unit tests and error handling. The README states the goal clearly: let you create trees of plain HTML elements and components, and add or remove attributes and event listeners on the fly.&lt;/p&gt;

&lt;p&gt;In practice, it gives you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Component&lt;/code&gt;, a base class for class components with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;props&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setState&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node&lt;/code&gt;, a factory that builds virtual DOM nodes from plain objects;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MiniReact.render&lt;/code&gt;, which mounts everything inside a real DOM element.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you build it, webpack outputs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public/mini-react.js&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libraryTarget: &apos;window&apos;&lt;/code&gt;, so these three names become globals in the browser. No JSX and no build step on your side.&lt;/p&gt;

&lt;h2 id=&quot;two-words-before-we-start&quot;&gt;Two words before we start&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;virtual DOM&lt;/strong&gt; is just a tree of plain JavaScript objects that describes what the page should look like. Creating objects is cheap; touching the real DOM is not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reconciliation&lt;/strong&gt; (or diffing and patching) is the process of comparing the old tree with the new one and changing only what is different in the real DOM.&lt;/p&gt;

&lt;p&gt;MiniReact does both, in a very small way.&lt;/p&gt;

&lt;h2 id=&quot;writing-a-component&quot;&gt;Writing a component&lt;/h2&gt;

&lt;p&gt;Here is the demo app that ships with the repo (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public/App.js&lt;/code&gt;), trimmed a bit. It is a small limit adjuster: a text input and a range slider that stay in sync.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;definedLimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;maxLimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nf&quot;&gt;setDefinedLimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;definedLimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;tagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;tagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;textContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Ajuste de limite&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;tagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;maxLimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;definedLimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;onchange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setDefinedLimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;And mounting it is one line in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public/index.html&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;MiniReact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;Notice the “blueprint” objects: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tagName&lt;/code&gt; is the HTML tag, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;children&lt;/code&gt; is a list of more blueprints (or plain strings), and every other key becomes an attribute. A key starting with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on&lt;/code&gt; becomes an event listener.&lt;/p&gt;

&lt;h2 id=&quot;two-differences-from-react&quot;&gt;Two differences from React&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setState&lt;/code&gt; only accepts a function.&lt;/strong&gt; You pass a function that receives the previous state and props and returns an object. That object is deep-merged into the current state:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nf&quot;&gt;setState &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;isFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;throwError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;state must be a function!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;previousState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;shallowClone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;shallowClone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mergeObjects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;previousState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__child&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;__patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;It is synchronous.&lt;/strong&gt; As you can see in the last line, the component re-renders and patches the DOM right there, inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setState&lt;/code&gt; call. React batches updates; MiniReact does not.&lt;/p&gt;

&lt;h2 id=&quot;how-it-works-three-phases&quot;&gt;How it works: three phases&lt;/h2&gt;

&lt;p&gt;The code is split into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/vdom&lt;/code&gt; (the virtual DOM) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/dom&lt;/code&gt; (everything that touches the real DOM). I followed a naming convention: modules whose name ends in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ing&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;constructing&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;patching&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unmounting&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rendering&lt;/code&gt;) have side effects. Everything else is meant to be pure.&lt;/p&gt;

&lt;h3 id=&quot;constructing&quot;&gt;Constructing&lt;/h3&gt;

&lt;p&gt;For each virtual node, MiniReact checks whether it is an element or a component. An element becomes a real DOM element with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;document.createElement&lt;/code&gt;, and its children are constructed recursively. A component gets instantiated, its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;render&lt;/code&gt; is called, and the result goes through the same process again. This is also where the component receives its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__patch&lt;/code&gt; function, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setState&lt;/code&gt; can update it later.&lt;/p&gt;

&lt;h3 id=&quot;patching&quot;&gt;Patching&lt;/h3&gt;

&lt;p&gt;This is the reconciliation part, and it is intentionally simple. Given the previous and next virtual node:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;if the tag changed (a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; became a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;span&lt;/code&gt;), the old node is thrown away and a new one is built;&lt;/li&gt;
  &lt;li&gt;otherwise, attributes are diffed. Removed attributes come out as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined&lt;/code&gt;, which removes them from the DOM:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;previousVNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;nextVNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;previousVNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;acc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;acc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;nextVNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;if the number of children is the same, each child is patched by position;&lt;/li&gt;
  &lt;li&gt;if it is different, the children are rebuilt from scratch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key&lt;/code&gt;s like in React, so reordering a list means rebuilding it. For a learning project, I think it is a fair trade.&lt;/p&gt;

&lt;h3 id=&quot;unmounting&quot;&gt;Unmounting&lt;/h3&gt;

&lt;p&gt;The cleanup phase: walk the old tree, remove DOM nodes from their parents and drop the references so the garbage collector can do its job.&lt;/p&gt;

&lt;h2 id=&quot;events-without-leaking-listeners&quot;&gt;Events without leaking listeners&lt;/h2&gt;

&lt;p&gt;One detail I like: MiniReact does not attach your handler directly. Each element gets a single proxy function, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onEvent&lt;/code&gt;, per event type, and the real handler is stored on the element itself:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onEvent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NODE_ATTR_PROPERTY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;When you re-render with a new arrow function, only the stored handler changes; the listener stays the same. When the handler becomes falsy, the listener is removed. There is a test for exactly that (“should remove event listener”).&lt;/p&gt;

&lt;h2 id=&quot;tests&quot;&gt;Tests&lt;/h2&gt;

&lt;p&gt;Unit tests were one of the goals from the start. There are 47 Jest test cases across four files, covering the utilities, the virtual node factory, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Component&lt;/code&gt; class and the DOM rendering and patching (using jsdom). The patching tests are the fun ones: they click an element and check that a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; flips to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;span&lt;/code&gt;, or that a child component is swapped for another.&lt;/p&gt;

&lt;h2 id=&quot;running-it&quot;&gt;Running it&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git clone https://github.com/klaygomes/mini-react
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;mini-react
npm &lt;span class=&quot;nb&quot;&gt;install
&lt;/span&gt;npm run dev   &lt;span class=&quot;c&quot;&gt;# opens http://localhost:3000&lt;/span&gt;
npm &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;The README asks for Node &amp;gt;= 8.11.3 and npm ~5.6.0.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;What started as an interview exercise made React’s behaviour feel less like magic: a tree of objects, a function that compares two trees, and a few careful DOM calls. If you are curious about how these libraries work, reading a small one is a good first step, and this one fits in a few files.&lt;/p&gt;

&lt;p&gt;The code is &lt;a href=&quot;https://github.com/klaygomes/mini-react&quot;&gt;on GitHub&lt;/a&gt;. Feel free to open it, break it, and tell me what you would do differently.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/mini-react/&quot;&gt;MiniReact: a tiny React-like library to see what happens under the hood&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on August 23, 2018.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[The small gotcha that made me feel I know something]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/the-funny-gotcha/" />
  <id>https://www.estacouveflor.com/the-funny-gotcha</id>
  <published>2018-02-01T00:00:00+00:00</published>
  <updated>2018-02-01T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">The moment I realized I was starting to get the Linux feeling</summary>
  <content type="html">
    &lt;p&gt;Did you ever remember when you realized that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; is a built-in command in &lt;strong&gt;bash&lt;/strong&gt;, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Well, we as humans tend to assume things, so I did for a long time. As I came from Windows, and my programming experience is with high-level languages, in the beginning, I just got the necessary to be able to do my job as a frontend engineer.&lt;/p&gt;

&lt;p&gt;So I learned how to create branch decisions using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;, which is a &lt;strong&gt;shell keyword&lt;/strong&gt;. I connected it with what I had learned in the past, associating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if [ commands ];&lt;/code&gt; as syntax constraint like the other languages and never worried about what I was doing; after all, I had my work done at the end.&lt;/p&gt;

&lt;p&gt;As time went by, I realized that I had to learn more about this language; well, you know, it is impossible to work with Linux &lt;em&gt;effectively&lt;/em&gt; without knowing it.&lt;/p&gt;

&lt;p&gt;So I decided to start from scratch, assuming I know &lt;strong&gt;nothing&lt;/strong&gt; about bash, it was a great decision, because with my mind open I started watching and reading basic tutorials; as a side note: it is sad how there is bad content on the internet, you have to take much care when you decide to learn new things because the chances you got misleading content(or just wrong) is high.&lt;/p&gt;

&lt;p&gt;Well, I was in luck when I found the &lt;a href=&quot;http://mywiki.wooledge.org/BashGuide&quot;&gt;Bash Guide&lt;/a&gt;, written by LHunath and GreyCat. They do a great job explaining what you need to know effortlessly.&lt;/p&gt;

&lt;p&gt;They were the first content where they take a step to make it clear that it is a command and it needs the parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt; as the last one.&lt;/p&gt;

&lt;p&gt;See what they say:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; executes the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; (remember, you don’t need an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; to run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; command!) with the arguments &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a, =, b&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; uses these arguments to determine what must be checked. In this case, it checks whether the string a (the first argument) is equal (the second argument) to the string b (the third argument), and if this is the case, it will exit successfully. However, since the string “a” is not equal to the string “b”, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; will not exit successfully (its exit code will be 1). if sees that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; terminated unsuccessfully and executes the code in the else block.
The last argument, “&lt;strong&gt;]&lt;/strong&gt;”, means nothing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt;, but it is required. See what happens when you omit it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;(credits http://mywiki.wooledge.org/BashGuide/TestsAndConditionals)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Until that moment, everything that I thought weird about bash started making sense. Before that, I never realized why I couldn’t write things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if[$1 -lt 10]&lt;/code&gt; (note I didn’t use spaces) or execute commands inside the brackets like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if [&quot;$1&quot; -eq $(cat file) ]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The simple fact that I know that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; is a command, like any normal bash program, and it &lt;em&gt;expects&lt;/em&gt; parameters to be passed, made me never make this kind of mistake again.&lt;/p&gt;

&lt;p&gt;I was so surprised by this little thing that I said to me even if I write anything to my blog again; it should be about it. Well, years later, here am I :)&lt;/p&gt;

&lt;p&gt;And you when you ever realized that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; is a command?&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/the-funny-gotcha/&quot;&gt;The small gotcha that made me feel I know something&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on February 01, 2018.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[GeoLocation: a take-home challenge built with React, Redux and Sagas]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/geo-location/" />
  <id>https://www.estacouveflor.com/geo-location</id>
  <published>2017-12-22T00:00:00+00:00</published>
  <updated>2017-12-22T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">How I turned a recruitment challenge into a small React, Redux and Next.js app that puts you and any website on a map, and the design decisions I wrote down along the way.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#the-challenge&quot; id=&quot;markdown-toc-the-challenge&quot;&gt;The challenge&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-stack&quot; id=&quot;markdown-toc-the-stack&quot;&gt;The stack&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-the-data-flows&quot; id=&quot;markdown-toc-how-the-data-flows&quot;&gt;How the data flows&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#validating-the-input&quot; id=&quot;markdown-toc-validating-the-input&quot;&gt;Validating the input&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#a-design-decision-i-left-in-the-code&quot; id=&quot;markdown-toc-a-design-decision-i-left-in-the-code&quot;&gt;A design decision I left in the code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-i-left-out&quot; id=&quot;markdown-toc-what-i-left-out&quot;&gt;What I left out&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#update-september-2026-running-it-today&quot; id=&quot;markdown-toc-update-september-2026-running-it-today&quot;&gt;Update, September 2026: running it today&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;If you ever had to solve a front-end take-home challenge, this post is for you. I will show how I
organized one: the stack I picked, how the data flows, and a couple of small decisions I left
written in the code so the reviewer (and now you) could understand why things are the way they are.&lt;/p&gt;

&lt;p&gt;The source code is on &lt;a href=&quot;https://github.com/klaygomes/geo-location&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-challenge&quot;&gt;The challenge&lt;/h2&gt;

&lt;p&gt;This was not a product. I built it for a job interview, as a take-home challenge. The repository started from a template
prepared by Avenue Code Recruitment (its first commits, from 2014 to 2017, are theirs), and my own
work went from December 18 to December 22, 2017.&lt;/p&gt;

&lt;p&gt;The story phrase in the template was simple:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;As a curious web surfer, I want to be able to locate both me and any website on a map.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In practice, the app had to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;show my own location on a map when I click “My location”, and clear it with “Reset location”;&lt;/li&gt;
  &lt;li&gt;accept a domain like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nytimes.com&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.g1.com.br&lt;/code&gt;, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://freegeoip.net/json/:host&lt;/code&gt;
and show where that website is hosted;&lt;/li&gt;
  &lt;li&gt;work on desktop, tablet and phone;&lt;/li&gt;
  &lt;li&gt;have at least 80% of the code covered by tests, meaningful commits and a descriptive README.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last item matters. The evaluation looked at the git history too, so I followed the
&lt;a href=&quot;https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#&quot;&gt;AngularJS commit convention&lt;/a&gt;
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;feat:&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fix:&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test:&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chore:&lt;/code&gt;…) and ended with 78 small commits instead of one big “done”.&lt;/p&gt;

&lt;h2 id=&quot;the-stack&quot;&gt;The stack&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;React&lt;/strong&gt; for the components, styled with &lt;strong&gt;styled-components&lt;/strong&gt; (CSS written inside JavaScript).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Redux&lt;/strong&gt; to keep the application state in one place.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Redux Saga&lt;/strong&gt; for side effects. A “side effect” here is anything that talks to the outside
world, like an HTTP request.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Next.js&lt;/strong&gt; for server-side rendering (SSR), which means the first HTML is produced by the
server instead of the browser.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Jest&lt;/strong&gt; and &lt;strong&gt;Enzyme&lt;/strong&gt; for tests.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Storybook&lt;/strong&gt;, a small catalog where each component can be viewed and played with in isolation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;how-the-data-flows&quot;&gt;How the data flows&lt;/h2&gt;

&lt;p&gt;Every component is “dumb”: it receives data through props and reports user actions through
callbacks. A higher-order component (a function that takes a component and returns a new one)
called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WithRedux&lt;/code&gt; connects them to the store:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;requestHostnameLocation &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actionsCreators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hostnameLocationFetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;requestMyLocation &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actionsCreators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;myLocationFetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;resetMyLocation &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actionsCreators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;myLocationReset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;When a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FETCH_*&lt;/code&gt; action is dispatched, a saga picks it up. Both “my location” and “website
location” hit the same API, so I used one generator and a small map to decide which action to
fire on success or failure:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetchLocation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetchLocation &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;actions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;actionMapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;axios&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;With no payload the URL is just the API root, which returns the caller’s own location. With a
hostname it returns the website’s location.&lt;/p&gt;

&lt;p&gt;The root saga uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;takeLatest&lt;/code&gt;, so if you click “Locate” twice quickly only the last request
wins. Errors got a single place too: one saga watches for any action whose type starts with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAIL&lt;/code&gt; and turns it into a message on screen.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;watchForErrors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;watchForErrors &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;take&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(({&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/^FAIL/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actionsCreators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;errorShow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;This way, a new request type gets error handling for free, as long as its failure action follows
the naming pattern.&lt;/p&gt;

&lt;h2 id=&quot;validating-the-input&quot;&gt;Validating the input&lt;/h2&gt;

&lt;p&gt;The form had to accept only domains, with or without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.&lt;/code&gt;. The validation is a single regular
expression in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utils/is-valid-domain.js&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;REG_URL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/^&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;a-zA-Z0-9&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\-&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.[&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;a-zA-Z&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;]{2,3}(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;a-zA-Z0-9&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)?&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;$/&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;REG_URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;If it fails, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;HostnameDispatcher /&amp;gt;&lt;/code&gt; component selects the text and shows “Please inform a
valid hostname” instead of sending the request.&lt;/p&gt;

&lt;h2 id=&quot;a-design-decision-i-left-in-the-code&quot;&gt;A design decision I left in the code&lt;/h2&gt;

&lt;p&gt;My last commit was only a comment, and I think it is the most interesting one. In
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;LocationTable /&amp;gt;&lt;/code&gt;, each row has an info icon with its own click handler. The easy way would be
to write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onClick={this.onRequestInformation.bind(this, &apos;city&apos;)}&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;render&lt;/code&gt;. The problem is that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bind&lt;/code&gt; creates a new function on every render, so a component that only re-renders when its
props change (a “pure” component) always sees a “new” prop and re-renders anyway.&lt;/p&gt;

&lt;p&gt;So I created all the handlers once, in the constructor:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// I know it should be easier/readeable to use this.onRequestInformatino.bind(this, param1, param2...)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// for each onClick, but it brings some performance implications.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// more info: https://medium.com/@esamatti/react-js-pure-render-performance-anti-pattern-fb88c101332f&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleOnRequestInformation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;descriptionTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;acc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;acc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onRequestInformation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lastUpdate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;onRequestInformation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;descriptionTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lastUpdate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;acc&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;As the commit message says: pure render optimized components can be very fast, but they require
you to treat data as immutable, and in JavaScript that can be challenging sometimes.&lt;/p&gt;

&lt;h2 id=&quot;what-i-left-out&quot;&gt;What I left out&lt;/h2&gt;

&lt;p&gt;The solution page listed what was missing, and I prefer to be upfront about it: fixing FOIT
(the flash of invisible text while web fonts load), caching API calls, more tests, webpack
optimization and i18n.&lt;/p&gt;

&lt;h2 id=&quot;update-september-2026-running-it-today&quot;&gt;Update, September 2026: running it today&lt;/h2&gt;

&lt;p&gt;The README points to a Heroku demo, a hosted Storybook and a coverage report. Those links no
longer work, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;freegeoip.net&lt;/code&gt; itself no longer answers, so the demo is not online anymore. The
code is still there: nine components have stories you can open with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run storybook&lt;/code&gt;, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run test:coverage&lt;/code&gt; generates the coverage report locally. Keep in mind the README asks for
Node 8.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;It was a small app, but a good excuse to put Redux Saga, SSR and Storybook together in a few
days and to practice writing commits someone else would read.&lt;/p&gt;

&lt;p&gt;If you are preparing for a challenge like this, feel free to browse the
&lt;a href=&quot;https://github.com/klaygomes/geo-location&quot;&gt;repository&lt;/a&gt; and the commit history. And if you would
have organized it differently, tell me in the comments.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/geo-location/&quot;&gt;GeoLocation: a take-home challenge built with React, Redux and Sagas&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on December 22, 2017.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Introduction to async and await (in Portuguese)]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/async-e-await/" />
  <id>https://www.estacouveflor.com/async-e-await</id>
  <published>2016-06-26T00:00:00+00:00</published>
  <updated>2016-06-26T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">A short introduction to async and await in .NET. My Portuguese translation of Stephen Cleary&apos;s article.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introduzindo-as-palavras-chaves&quot; id=&quot;markdown-toc-introduzindo-as-palavras-chaves&quot;&gt;Introduzindo as palavras-chaves&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#awaitables&quot; id=&quot;markdown-toc-awaitables&quot;&gt;Awaitables&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tipos-de-retorno&quot; id=&quot;markdown-toc-tipos-de-retorno&quot;&gt;Tipos de retorno&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#retornando-valores&quot; id=&quot;markdown-toc-retornando-valores&quot;&gt;Retornando valores&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#contexto&quot; id=&quot;markdown-toc-contexto&quot;&gt;Contexto&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#uma-resposta-simples&quot; id=&quot;markdown-toc-uma-resposta-simples&quot;&gt;Uma resposta simples:&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#reposta-complexa&quot; id=&quot;markdown-toc-reposta-complexa&quot;&gt;Reposta complexa:&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#evitando-o-contexto&quot; id=&quot;markdown-toc-evitando-o-contexto&quot;&gt;Evitando o Contexto&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#async-composition&quot; id=&quot;markdown-toc-async-composition&quot;&gt;Async Composition&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#orientações&quot; id=&quot;markdown-toc-orientações&quot;&gt;Orientações&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#próximos-passos&quot; id=&quot;markdown-toc-próximos-passos&quot;&gt;Próximos passos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;English readers:&lt;/strong&gt; this is my authorized Portuguese translation and adaptation of “&lt;a href=&quot;http://blog.stephencleary.com/2012/02/async-and-await.html&quot;&gt;Async and Await&lt;/a&gt;” by Stephen Cleary. The original is in English, so go read it there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Este artigo é uma tradução e adaptação autorizada do original “&lt;a href=&quot;http://blog.stephencleary.com/2012/02/async-and-await.html&quot;&gt;Async and Await&lt;/a&gt;”, de autoria do MVP Stephen Cleary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;introduzindo-as-palavras-chaves&quot;&gt;Introduzindo as palavras-chaves&lt;/h2&gt;
&lt;p&gt;Irei usar alguns conceitos que serão explicados posteriormente, por isso, acalme-se e concentre-se nesta primeira parte.&lt;/p&gt;

&lt;p&gt;Métodos assíncronos tem a seguinte aparência:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DoSomethingAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// No mundo real, nós enventualmente fariamos alguma coisa…&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Para este exemplo, vou apenas esperar de forma assícrona por 100ms.&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;A palavra-chave &lt;strong&gt;async&lt;/strong&gt; habilita a palavra-chave &lt;strong&gt;await&lt;/strong&gt; naquele método e modifica como o resultado é tratado. E isso é tudo que &lt;em&gt;async&lt;/em&gt; faz! Não faz com que ele rode em um &lt;em&gt;thread pool&lt;/em&gt; ou algum tipo de magia negra, a palavra-chave &lt;em&gt;async&lt;/em&gt; apenas habilita a palavra-chave &lt;em&gt;await&lt;/em&gt;(e gerencia o retorno dos métodos).&lt;/p&gt;

&lt;p&gt;O início de um método async é executado como qualquer outro, ou seja, roda de forma &lt;strong&gt;síncrona&lt;/strong&gt; até que ele alcance o primeiro &lt;em&gt;await&lt;/em&gt; (ou lance uma exceção).&lt;/p&gt;

&lt;p&gt;A palavra-chave &lt;strong&gt;await&lt;/strong&gt; é onde as coisas se tornam assíncronas. &lt;em&gt;await&lt;/em&gt; é como um &lt;strong&gt;operador unário&lt;/strong&gt;: Ele recebe um argumento simples, um &lt;em&gt;awaitable&lt;/em&gt; (uma operação assíncrona) e o examina para ver se ele já completou; se ele estiver completado, o método apenas continua(de forma síncrona) como um método normal, mas se o &lt;em&gt;await&lt;/em&gt; notar que o &lt;em&gt;awaitable&lt;/em&gt; ainda não completou, ele atua de forma assíncrona, pedindo para o &lt;em&gt;awaitable&lt;/em&gt; rodar o restante do método até que se complete e &lt;strong&gt;devolve à execução para quem chamou o método &lt;em&gt;async&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Mais tarde, quando o &lt;em&gt;awaitable&lt;/em&gt; completar, ele executará o restante do método &lt;em&gt;async&lt;/em&gt;. Se você usar a palavra-chave &lt;em&gt;await&lt;/em&gt; em um &lt;em&gt;awaitable&lt;/em&gt; padrão(tal como Task), o restante do método &lt;em&gt;async&lt;/em&gt; irá executar no &lt;strong&gt;contexto&lt;/strong&gt; que foi capturado antes do &lt;em&gt;await&lt;/em&gt; ter sido retornado.&lt;/p&gt;

&lt;p&gt;Gosto de pensar no &lt;em&gt;await&lt;/em&gt; como &lt;em&gt;&lt;strong&gt;a&lt;/strong&gt;synchronous &lt;strong&gt;wait&lt;/strong&gt;&lt;/em&gt;(espera assíncrona). Isso quer dizer que o método &lt;em&gt;async&lt;/em&gt; &lt;strong&gt;pausa&lt;/strong&gt; até que o &lt;em&gt;awaitable&lt;/em&gt; complete (então ele espera), mas a &lt;em&gt;thread&lt;/em&gt; atual não é &lt;strong&gt;bloqueada&lt;/strong&gt; (por isso ele é assíncrono);&lt;/p&gt;

&lt;h2 id=&quot;awaitables&quot;&gt;Awaitables&lt;/h2&gt;

&lt;p&gt;Como eu mencionei &lt;em&gt;await&lt;/em&gt; recebe um argumento – um &lt;em&gt;awaitable&lt;/em&gt; – que é uma operação assíncrona. Existem dois tipos disponíveis de &lt;em&gt;awaitables&lt;/em&gt; no Framework .NET: &lt;em&gt;Task&amp;lt;T&amp;gt;&lt;/em&gt; e &lt;em&gt;Task&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Há também outros &lt;em&gt;awaitable&lt;/em&gt;: métodos especiais tais como &lt;em&gt;Task.Yield&lt;/em&gt; que retornam &lt;em&gt;awaitables&lt;/em&gt; que não são Tasks e o &lt;em&gt;Runtime WinRT&lt;/em&gt; que possui tem um &lt;em&gt;awaitable&lt;/em&gt; não gerenciado. Você também pode criar o seu próprio (geralmente por razões de performance) ou usar métodos de extensão para fazer um tipo que não é &lt;em&gt;awaitable&lt;/em&gt; se tornar um. Isso é tudo que direi sobre como criar os seus próprios &lt;em&gt;awaitables&lt;/em&gt;, já que em todo o tempo que eu usei &lt;em&gt;async/await&lt;/em&gt; poucas vezes tive que escrever um para mim. Se você quiser saber mais sobre como escrever um personalizado, veja o &lt;a href=&quot;http://blogs.msdn.com/b/pfxteam/&quot;&gt;blog do time de parallel&lt;/a&gt; e o &lt;a href=&quot;https://codeblog.jonskeet.uk/category/async/&quot;&gt;blog do Jon Skeet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Um ponto importante sobre os &lt;em&gt;awaitable&lt;/em&gt; é: &lt;strong&gt;O tipo que é &lt;em&gt;awaitable&lt;/em&gt; e não o método&lt;/strong&gt;. Em outras palavras, você pode usar o &lt;em&gt;await&lt;/em&gt; em um resultado de um método &lt;em&gt;async&lt;/em&gt; que retorna uma &lt;em&gt;Task&lt;/em&gt;… Porque o método retorna uma Task, &lt;em&gt;não&lt;/em&gt; por que ele é &lt;em&gt;async&lt;/em&gt;. Logo, você também pode usar o &lt;em&gt;await&lt;/em&gt; no resultado de um método não assíncrono que retorna uma Task.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;NewStuffAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Use await e se divirta com a coisa nova&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MyOldTaskParallelLibraryCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Note que este método não é async então não podemos usar await aqui&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ComposeAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Nós podemos chamar o await em Tasks, não importando de onde elas vieram.      await NewStuffAsync();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MyOldTaskParallelLibraryCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p class=&quot;notice&quot;&gt;&lt;strong&gt;Dica&lt;/strong&gt;: Se você tem um método assíncrono muito simples, você pode escreve-lo sem usar a palavra-chave &lt;em&gt;await&lt;/em&gt; (ex. usando Task.FromResult). Se você puder escrever sem, &lt;strong&gt;faça&lt;/strong&gt; e também remova a palavra chave &lt;em&gt;async&lt;/em&gt;. Um método não &lt;em&gt;async&lt;/em&gt; que retorna um &lt;em&gt;Task.FromResult&lt;/em&gt; é mais eficiente que um método &lt;em&gt;async&lt;/em&gt; que retorna um valor.&lt;/p&gt;

&lt;h2 id=&quot;tipos-de-retorno&quot;&gt;Tipos de retorno&lt;/h2&gt;

&lt;p&gt;Métodos &lt;em&gt;async&lt;/em&gt; podem retornar &lt;em&gt;Task&amp;lt;T&amp;gt;&lt;/em&gt;, &lt;em&gt;Task&lt;/em&gt; e &lt;em&gt;void&lt;/em&gt;. Na maioria dos casos, você deverá retornar um &lt;em&gt;Task&amp;lt;T&amp;gt;&lt;/em&gt; ou &lt;em&gt;Task&lt;/em&gt; e &lt;strong&gt;void&lt;/strong&gt; apenas quando &lt;strong&gt;realmente&lt;/strong&gt; for necessário.&lt;/p&gt;

&lt;p&gt;Por que retornar &lt;em&gt;Task&amp;lt;T&amp;gt;&lt;/em&gt; ou &lt;em&gt;Task&lt;/em&gt;? Por que eles são &lt;em&gt;awaitables&lt;/em&gt; e &lt;em&gt;void&lt;/em&gt; &lt;strong&gt;não&lt;/strong&gt;.  Se você tem um método assíncrono que retorna uma &lt;em&gt;Task&lt;/em&gt;, você poderá passar o resultado para um &lt;em&gt;await&lt;/em&gt;, já com o &lt;em&gt;void&lt;/em&gt;, você não terá nada o que passar, em resumo, você só deve usar &lt;em&gt;void&lt;/em&gt; quando estiver escrevendo &lt;em&gt;event handlers&lt;/em&gt; assíncronos.&lt;/p&gt;

&lt;p class=&quot;notice&quot;&gt;&lt;strong&gt;Dica&lt;/strong&gt;: Você também pode usar &lt;em&gt;async void&lt;/em&gt; para outros tipos de ações, ex. um método único do tipo &lt;em&gt;static async void MainAsync()&lt;/em&gt; para aplicações de console. Porém, este uso do &lt;em&gt;async void&lt;/em&gt; tem seus próprios problemas; veja &lt;a href=&quot;http://blog.stephencleary.com/2012/02/async-console-programs.html&quot;&gt;Async Console Programs&lt;/a&gt;. O caso de uso principal para métodos &lt;em&gt;async void&lt;/em&gt; é para &lt;em&gt;event handlers&lt;/em&gt; onde a conclusão/retorno do método não é importante.&lt;/p&gt;

&lt;h2 id=&quot;retornando-valores&quot;&gt;Retornando valores&lt;/h2&gt;

&lt;p&gt;Métodos assíncronos retornando &lt;em&gt;Task&lt;/em&gt; ou &lt;em&gt;void&lt;/em&gt; não possuem um valor de retorno, já os métodos que retornam &lt;em&gt;Task&amp;lt;T&amp;gt;&lt;/em&gt; deve retornar um valor do tipo &lt;em&gt;T&lt;/em&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CalculateAnswer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// (Probably should be longer...)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Retorna um &quot;int&quot; não uma &quot;Task&amp;lt;int&amp;gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;É um pouco estranho de se acostumar, mas há &lt;a href=&quot;http://blog.stephencleary.com/2011/09/async-ctp-why-do-keywords-work-that-way.html&quot;&gt;boas razões&lt;/a&gt; por trás deste design.&lt;/p&gt;

&lt;h2 id=&quot;contexto&quot;&gt;Contexto&lt;/h2&gt;

&lt;p&gt;Em nossa introdução, eu mencionei que quando você usa a palavra-chave await em um tipo awaitable padrão, ele irá capturar o “contexto” e depois aplicá-lo ao restante do método, mas o que exatamente é este “Contexto”?&lt;/p&gt;

&lt;h3 id=&quot;uma-resposta-simples&quot;&gt;Uma resposta simples:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Se você está na &lt;em&gt;thread de UI&lt;/em&gt;, então o contexto será o de UI.&lt;/li&gt;
  &lt;li&gt;Se você estiver espondendo a uma requisição ASP.NET, então ele será o contexto da requisição.&lt;/li&gt;
  &lt;li&gt;Caso contrário, geralmente será o contexto do &lt;em&gt;thread pool&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;reposta-complexa&quot;&gt;Reposta complexa:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Se o &lt;em&gt;SynchronizationContext.Current&lt;/em&gt; não for &lt;em&gt;null&lt;/em&gt;, então ele será o atual &lt;em&gt;SynchronizationContext&lt;/em&gt;. (Os contexto de UI e requisição do asp.net são &lt;em&gt;SynchronizationContexts&lt;/em&gt;)&lt;/li&gt;
  &lt;li&gt;Caso contrário, será o TaskScheduler atual (TaskScheduler.Default é o contexto do thread pool).
O que isso quer dizer no mundo real?Uma coisa,  a captura e recuperação e dos contextos de UI/ASP.NET são feitos de forma transparente.&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;// Exemplo de WinForms (Funciona do mesmo jeito para WPF).&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadFileButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Uma vez que a gente espera assíncronamente, a thread de UI não é bloqueada pelo download do arquivo.&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadFileAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileNameTextBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Após a conclusão, nós retomamos no context de UI e podemos acessar facilmanete elementos de UI.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;resultTextBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;File downloaded!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Exemplo em ASP.NET&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MyButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Já que a gente está esperando de forma assíncrona, a thread do ASP.NET não é bloqueada pelo download do arquivo.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// isso permite que ela fique disponível para executar outros requests neste meio tempo.&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadFileAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Depois de finalizado, retomamos o context e podemos acessar os dados do request atual.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Nós poderemos estar em outra thread, mas nós teremos o mesmo context ASP.NET.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;File downloaded!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;Isso é ótimo para &lt;em&gt;event handlers&lt;/em&gt;, mas nem sempre será o que você irá precisar para maioria do código (que será boa parte código assíncrono que você escreverá).&lt;/p&gt;

&lt;h2 id=&quot;evitando-o-contexto&quot;&gt;Evitando o Contexto&lt;/h2&gt;

&lt;p&gt;Na maior parte do tempo, você não precisa voltar ao contexto principal. Boa parte dos métodos assíncronos são projetados com composição em mente: Eles usam o &lt;em&gt;await&lt;/em&gt; de outras operações, cada um representando uma operação assíncrona por si mesma (podendo ser compostas por outras). Neste caso, você pode dizer ao &lt;em&gt;awaiter&lt;/em&gt; para não capturar o contexto atual chamando &lt;em&gt;ConfigureAwait&lt;/em&gt; e passando &lt;em&gt;false&lt;/em&gt; para ele. Exemplo:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadFileAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Use HttpClient or whatever to download the file contents.&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileContents&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadFileContentsAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ConfigureAwait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Note that because of the ConfigureAwait(false), we are not on the original context here.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Instead, we&apos;re running on the thread pool.&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Write the file contents out to a disk file.&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WriteToDiskAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileContents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ConfigureAwait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// The second call to ConfigureAwait(false) is not *required*, but it is Good Practice.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// WinForms example (it works exactly the same for WPF).&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadFileButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Since we asynchronously wait, the UI thread is not blocked by the file download.&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadFileAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileNameTextBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Since we resume on the UI context, we can directly access UI elements.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;resultTextBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;File downloaded!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;O que é importante notar com este exemplo é cada &lt;em&gt;nível&lt;/em&gt; de chamada de um método assíncrono tem seu próprio contexto. &lt;em&gt;DownloadFileButton_Click&lt;/em&gt; inicia no contexto da UI, chama &lt;em&gt;DownloadFileAsync&lt;/em&gt;. &lt;em&gt;DownloadFileAsync&lt;/em&gt; também inicia no contexto da UI, mas então o deixa para trás ao chamar &lt;em&gt;ConfigureAwait(false)&lt;/em&gt;. O resto do método &lt;em&gt;DownloadFileAsync&lt;/em&gt; executa no contexto da &lt;em&gt;thread pool&lt;/em&gt;. Porém quando &lt;em&gt;DownloadFileAsync&lt;/em&gt; completa, o &lt;em&gt;DownloadFileButton_Click&lt;/em&gt; continua, ele, de fato, continua no contexto da UI.&lt;/p&gt;

&lt;p&gt;Uma boa regra a seguir é de sempre usar &lt;em&gt;ConfigureAwait(false)&lt;/em&gt; a menos que você saiba que realmente irá precisar do contexto.&lt;/p&gt;

&lt;h2 id=&quot;async-composition&quot;&gt;Async Composition&lt;/h2&gt;

&lt;p&gt;Até agora nós apenas consideramos composição serial: um método assíncrono aguarda por uma operação a cada tempo, mas também é possível iniciar várias operações e esperar por uma (ou todas) completarem. Você pode fazer isso iniciando operações, mas não usando await imediatamente.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DoOperationsConcurrentlyAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DoOperation0Async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DoOperation1Async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DoOperation2Async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Neste ponto, todas as três tarefas estão rodando ao mesmo tempo. &lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Agora a gente await todas elas de uma vez.&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WhenAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetFirstToRespondAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Chama dois web services; Pega a primeira resposta&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WebService1Async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WebService2Async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Await pelo primeiro a responder&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstTask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WhenAny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Retorna o resultado&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;Ao usar composição concorrente (Task.WhenAll ou Task.WhenAny), você pode executar operações concorrentes simples. Você também pode usar estes métodos junto com Task.Run para fazer computações simples em paralelo. Mas isso não é um substituto para a Task Parallel Liberay – qualquer operação que faça uso intensivo de CPU e operações paralelas devem fazer através da TPL.&lt;/p&gt;

&lt;h2 id=&quot;orientações&quot;&gt;Orientações&lt;/h2&gt;
&lt;p&gt;Leia o documento da &lt;a href=&quot;http://www.microsoft.com/download/en/details.aspx?id=19957&quot;&gt;Task-based asynchronous (TAP)&lt;/a&gt;. Ele é extremamente bem escrito e inclui informações sobre o design da api e uso apropriado das palavras chaves &lt;em&gt;async&lt;/em&gt; e &lt;em&gt;await&lt;/em&gt; assim como inclusão de eventos de cancelamento e progresso.&lt;/p&gt;

&lt;p&gt;Existem muitas novas técnicas compatíveis com &lt;em&gt;await&lt;/em&gt; que devem ser usadas ao invés das técnicas antigas onde há bloqueio da aplicação. Se você tem alguns desses antigos exemplos no seu código novo com async, você está fazendo isso errado:&lt;/p&gt;

&lt;table rules=&quot;groups&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Antigo&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Novo&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Descrição&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;task.Wait&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;await task&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Aguarda/await uma task completar.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Task.Result&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;await task&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Pega o resultado de uma task completada&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Task.WaitAny&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;await Task.WhenAny&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Aguarda/await que uma de uma coleção de tasks complete.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Task.WaitAll&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;await Task.WhenAll&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Aguarda/await que todas as tasks de uma coleção complete&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Thread.Sleep&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;await Task.Delay&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Aguarda/await por um periodo de tempo.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Task constructor&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Task.Run or TaskFactory.StartNew&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Cria uma task baseada em código&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;próximos-passos&quot;&gt;Próximos passos&lt;/h2&gt;
&lt;p&gt;Stephen Cleary publicou um artigo na MSDN intitulado &lt;a href=&quot;http://msdn.microsoft.com/en-us/magazine/jj991977.aspx&quot;&gt;Best pratices in Asynchronous Programming (Melhores práticas em programação assíncrona)&lt;/a&gt; que explica de forma mais completa as orientações sobre “evite void async”, “assíncrono por todo caminho” e “configure o contexto”.
A &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/hh191443.aspx&quot;&gt;documentação oficial da MSDN&lt;/a&gt; é muito boa; Eles incluem uma versão online do documento &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/hh873175.aspx&quot;&gt;Task-based Asynchronous Pattern&lt;/a&gt; que é excelente e cobre os designs dos métodos assíncronos. 
A equipe &lt;em&gt;async&lt;/em&gt; publicou uma faq sobre &lt;em&gt;async/await&lt;/em&gt;, um grande lugar para continuar aprendendo sobre &lt;em&gt;async&lt;/em&gt;. Eles possuem destaques dos melhores posts e vídeos por lá. E também qualquer &lt;a href=&quot;http://blogs.msdn.com/b/pfxteam&quot;&gt;blog post do Stephen Toub&lt;/a&gt; é bem instrutivo. 
E claro, outro recurso é o blog do &lt;a href=&quot;http://blog.stephencleary.com/&quot;&gt;Stephen Cleary&lt;/a&gt;.  Todo este material em inglês.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/async-e-await/&quot;&gt;Introduction to async and await (in Portuguese)&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on June 26, 2016.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Covariance and contravariance in C Sharp]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/covariancia-contravariancia/" />
  <id>https://www.estacouveflor.com/covariancia-contravariancia</id>
  <published>2016-06-18T00:00:00+00:00</published>
  <updated>2016-06-18T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">One more of those features you use without knowing it exists.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;First, we need to define what variance is, along with its daughters, covariance and contravariance. To start, you need to understand that the type systems of most object-oriented programming languages allow new types to be created from other ones using inheritance, and that these new types can be used anywhere the base types would be expected.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/heranca.png&quot; alt=&quot;Simple inheritance&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;If you have a class &lt;em&gt;Cat&lt;/em&gt; that inherits from &lt;em&gt;Animal&lt;/em&gt;, you can use it in any method that accepts only &lt;em&gt;Animal&lt;/em&gt; as a parameter:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Animal&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WagTail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Cat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Animal&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WagTail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wagging frantically&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WagTail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;nf&quot;&gt;Call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// &amp;lt;&amp;lt;--compiles without problems&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;This behavior is called &lt;strong&gt;Polymorphism&lt;/strong&gt;, and you have probably heard about it already, but what do you do if the method, instead of just one &lt;em&gt;Animal&lt;/em&gt;, expected a list of &lt;em&gt;Animal&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;When we are working with type containers (in plain words: classes that only exist as a kind of box shaped exclusively to give access to specific types), these metamorphoses start being called &lt;em&gt;variances&lt;/em&gt;, and they are classified into three subgroups: &lt;strong&gt;covariance&lt;/strong&gt;, &lt;strong&gt;contravariance&lt;/strong&gt;, and &lt;strong&gt;invariance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now that you know this exists, let’s dig a little deeper; look at the following example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Animal&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WagTail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Cat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Animal&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WagTail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wagging frantically&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cats&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()};&lt;/span&gt;
	&lt;span class=&quot;nf&quot;&gt;Call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// &amp;lt;&amp;lt;--cats, which is of type Cat[], is converted to Animal[], a more generic type&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WagTail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;In the example above, note that the &lt;em&gt;System.Array&lt;/em&gt; type, the container for the Animal and Cat types, allows its metamorphosis whenever the type it holds is a base type of the other &lt;em&gt;System.Array&lt;/em&gt;’s type; we call this mutation covariance.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/covariancia.png&quot; alt=&quot;Covariance direction&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In other words, covariance happens whenever a container object initialized with a more specialized type can be assigned to a container object that holds a more basic one.&lt;/p&gt;

&lt;p&gt;Contravariance, on the other hand, is the opposite, where only specialized types accept more basic types.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/contravariancia.png&quot; alt=&quot;Contravariance direction&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It doesn’t seem to make sense, but it does, and you have probably already used contravariance in your day-to-day work; look at this example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$&quot;Called with &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; type of &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Writter&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Writter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;_data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;Writter says &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;Action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;callLogAsString&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//&amp;lt;-- Log is of type Action&amp;lt;Object&amp;gt;, converted to Action&amp;lt;string&amp;gt;; note that string is more specific than object.&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;Action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Writter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;callLogAsWritter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;nf&quot;&gt;callLogAsString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;nf&quot;&gt;callLogAsWritter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Writter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
	
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;In the example above, starting from the signature of a generic method, it was possible to convert it to a more specific type.&lt;/p&gt;

&lt;p&gt;Now let’s see what problems these kinds of metamorphoses can get us into. In the first example, we saw that System.Array is covariant, which makes it possible for the following code to compile but fail miserably at runtime:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Camel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Animal&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WagTail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wagging gently&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DrinkWater&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Drinking 5 liters of water&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WagTail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Camel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;//&amp;lt;--here I will get a runtime error (ArrayTypeMismatchException)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;Note that it is &lt;strong&gt;safe to read&lt;/strong&gt; properties and call methods of covariant containers, but &lt;strong&gt;dangerous to write&lt;/strong&gt;. In the example above, the &lt;em&gt;Call&lt;/em&gt; method received an Array of Cats, but tried to write a Camel, which obviously doesn’t fit, causing a runtime error.&lt;/p&gt;

&lt;p&gt;In C#, starting from version 4, we can control the variance of our types using the &lt;em&gt;in&lt;/em&gt; and &lt;em&gt;out&lt;/em&gt; keywords.&lt;/p&gt;

&lt;p&gt;This control can only be done on generic interfaces or generic delegates; it is not allowed on classes and other types. The way the types are exposed is also controlled, in this last case to guarantee the safety of the data exposed by the containers. Look:
The in keyword defines types that are contravariant.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IKlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;IKlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Camel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;specificKlay&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Klay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;specificKlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Receive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;Although they are of different types, it is safe, since the method only knows about animals (which cat derives from), and don’t forget that the one doing the work will be Klay&lt;Animal&gt; and not Klay&lt;Camel&gt;.
The out keyword defines covariant types, which are only safe when read from the containers. That&apos;s why it is only possible to define covariant types as method return types:&lt;/Camel&gt;&lt;/Animal&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IKlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;IKlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genericKlay&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Klay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Camel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genericKlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;It is totally safe to read the type sent by the covariant generic type.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/covariancia-contravariancia/&quot;&gt;Covariance and contravariance in C Sharp&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on June 18, 2016.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[My new challenge: Learning F Sharp]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/meu-novo-desafio/" />
  <id>https://www.estacouveflor.com/meu-novo-desafio</id>
  <published>2016-06-16T00:00:00+00:00</published>
  <updated>2016-06-16T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">An index of the content I found on the internet about functional programming and FSharp.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#new-challenge&quot; id=&quot;markdown-toc-new-challenge&quot;&gt;New challenge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;h2 id=&quot;new-challenge&quot;&gt;New challenge&lt;/h2&gt;

&lt;p&gt;In July, I decided to challenge myself to learn something new; this time it will be the F# language. To do that, there is nothing better than starting by reading material we enjoy and practicing.&lt;/p&gt;

&lt;p&gt;The reason for this new challenge: besides strengthening my set of options as a solutions architect, I want to be able to apply these new concepts to the tools I already use.&lt;/p&gt;

&lt;p&gt;I started reading the book “The book of F# - Breaking free with managed functional programming” by Dave Fancher. This book has only 314 pages, and I liked the approach, since the author goes straight to the point; right in the first chapter he makes that clear by presenting a simple reverse Polish notation parser. That makes it not very suitable for those who have had little contact with the programming world.&lt;/p&gt;

&lt;p&gt;As I am still pretty green at this beginning and don’t have much to write about, I will start by translating the best content I find on the internet and publishing it here, without forgetting, of course, to give proper credit to its real authors. As I get more familiar with it, I will publish my own content about possible gotchas or random information about the language.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/meu-novo-desafio/&quot;&gt;My new challenge: Learning F Sharp&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on June 16, 2016.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Why we are staying with Microsoft's .NET stack]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/porque-nao-mudar-the-framework/" />
  <id>https://www.estacouveflor.com/porque-nao-mudar-the-framework</id>
  <published>2016-05-02T00:00:00+00:00</published>
  <updated>2016-05-05T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">Why I decided not to switch stacks when the opportunity came up inside the company.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#technical-motivations&quot; id=&quot;markdown-toc-technical-motivations&quot;&gt;Technical motivations.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cloud-infrastructure&quot; id=&quot;markdown-toc-cloud-infrastructure&quot;&gt;Cloud infrastructure&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#result&quot; id=&quot;markdown-toc-result&quot;&gt;Result&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;This year, we had the opportunity to take a look at, and decide whether it would be viable, moving from Microsoft technology to a Linux environment using Python. I decided to write this article as a summary of our meetings and of why I decided to keep using the Microsoft stack.&lt;/p&gt;

&lt;h2 id=&quot;technical-motivations&quot;&gt;Technical motivations.&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Advanced concepts about scalable applications are abstracted away from developers&lt;/strong&gt;. In the .NET framework, we have native support for multithreading and parallelism through syntactic sugar (async and await). Programmers don’t need to know about these more advanced techniques to make use of them. In Python, on the other hand, the project’s architecture and infrastructure need to be written with this in mind from the start.&lt;/p&gt;

&lt;p&gt;C#, being a language compiled at runtime, is by nature &lt;strong&gt;faster than interpreted languages&lt;/strong&gt;. Compared with Python, it can be up to 50,000% faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This can make the application harder to maintain&lt;/strong&gt;, since to work around this problem, Python allows CPU-heavy operations to be written in C++, which requires a professional who knows that language and the implications of its interoperability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is easier to maintain applications written in typed languages&lt;/strong&gt;. With a strongly typed language, even though productivity while developing new features may suffer compared with dynamic languages, this time is paid back during maintenance. A good part of development costs happens during maintenance; dynamic languages require programmers to be more disciplined and to know the environment they are developing in well, so that they produce more robust and easier-to-maintain applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compilation as a code quality tool&lt;/strong&gt;. One of the advantages of interpreted languages over compiled ones is the cost of compilation during the development workflow. However, it can turn into a disadvantage, since errors like syntax errors, or calls to properties or methods that don’t exist, are only caught when the code runs, which demands more effort on test coverage and, in the end, increases the development cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team maturity&lt;/strong&gt;. Today our team has great professionals with an excellent background in the Microsoft architecture; with a migration, we would need to adapt and wait for the learning curve. Remember: your team is only as good as your worst programmer.&lt;/p&gt;

&lt;h2 id=&quot;cloud-infrastructure&quot;&gt;Cloud infrastructure&lt;/h2&gt;

&lt;p&gt;Both Google’s and Microsoft’s solutions are excellent, highly scalable, cheap, and secure. Microsoft’s solutions have a price advantage for some offerings, for example: for a micro virtual machine, the minimum price charged on Google Cloud is around 130 dollars (450 reais), while on Microsoft’s platform it is 17 dollars. There is also the location of their data centers; Google doesn’t have servers in Brazil yet. However, it is possible that commercial agreements or implementation details make up for the amounts paid. In the current market, there are no advantages or disadvantages that decide the choice of one over the other; they are all integrated with their respective development environments, and both let you publish entire applications with one click.&lt;/p&gt;

&lt;h2 id=&quot;result&quot;&gt;Result&lt;/h2&gt;

&lt;p&gt;The new project starts in July, and we are going to build it in .NET and C#. The version chosen for development will be 4.6.1, MVC 5 / WebAPI 2, using SignalR.&lt;/p&gt;

&lt;p&gt;Right now, my team and I are planning the architecture, developing the infrastructure, and validating it on top of sketches with complex use cases. In the next articles, I will post updates with details on how it is turning out.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/porque-nao-mudar-the-framework/&quot;&gt;Why we are staying with Microsoft&amp;apos;s .NET stack&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on May 02, 2016.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Migrating from TFVC to Git]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/vamos-migrar-do-tfs-para-o-github/" />
  <id>https://www.estacouveflor.com/vamos-migrar-do-tfs-para-o-github</id>
  <published>2016-01-30T00:00:00+00:00</published>
  <updated>2016-04-18T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">How we migrated from TFVC to Git, from the point of view of a .NET developer</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#our-little-story&quot; id=&quot;markdown-toc-our-little-story&quot;&gt;Our little story&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#first-steps-with-git-for-a-tfvc-developer&quot; id=&quot;markdown-toc-first-steps-with-git-for-a-tfvc-developer&quot;&gt;First steps with GIT for a TFVC Developer&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#goodbye-workspaces&quot; id=&quot;markdown-toc-goodbye-workspaces&quot;&gt;Goodbye workspaces&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#branches-are-simpler&quot; id=&quot;markdown-toc-branches-are-simpler&quot;&gt;Branches are simpler&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#no-more-check-ins-or-check-outs&quot; id=&quot;markdown-toc-no-more-check-ins-or-check-outs&quot;&gt;No more Check ins or Check outs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#local-and-server-repositories&quot; id=&quot;markdown-toc-local-and-server-repositories&quot;&gt;Local and server repositories&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#commits-fetch-pull-push-and-sync&quot; id=&quot;markdown-toc-commits-fetch-pull-push-and-sync&quot;&gt;Commits, fetch, pull, push and sync&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#file-state-flow&quot; id=&quot;markdown-toc-file-state-flow&quot;&gt;File state flow&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#commit&quot; id=&quot;markdown-toc-commit&quot;&gt;commit&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#fetch&quot; id=&quot;markdown-toc-fetch&quot;&gt;fetch&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#pull&quot; id=&quot;markdown-toc-pull&quot;&gt;pull&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#push&quot; id=&quot;markdown-toc-push&quot;&gt;push&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#sync&quot; id=&quot;markdown-toc-sync&quot;&gt;sync&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;Almost 10 years later, we are going to start using GIT. Follow our story and see a small manual so you can use what you already know about TFVC to learn how to use GIT in Visual Studio. In this article I only talk about file versioning; the collaborative tools, checkin policy, issue tracker, etc. will have their turn as soon as we get used to GitHub.&lt;/p&gt;

&lt;h2 id=&quot;our-little-story&quot;&gt;Our little story&lt;/h2&gt;

&lt;p&gt;I remember as if it were yesterday the excitement of setting up the TFVC client; back then we were migrating from the infamous &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/3h0544kx%28v%3Dvs.80%29.aspx&quot;&gt;Microsoft SourceSafe&lt;/a&gt; to what was, at that time, the promise of better days at work.&lt;/p&gt;

&lt;p&gt;Team Foundation Version Control was beautiful; it came with the promise of being the ideal tool for versioning files in bigger projects, robust and fully configurable, and its wonderful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;merging&lt;/code&gt;, which really &lt;strong&gt;worked&lt;/strong&gt;, were a success (and still are) inside our team.&lt;/p&gt;

&lt;p&gt;We said goodbye to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\\DONEBY:&lt;/code&gt; annotations and to the hours lost with practically manual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;merges&lt;/code&gt;. The winds of change were whistling in our office.&lt;/p&gt;

&lt;p&gt;Almost 10 years later, once again driven by necessity, we are migrating, this time from our beloved companion TFVC to GIT. But why? It sounds silly, but the main reason is that it is not fast enough.&lt;/p&gt;

&lt;p&gt;Although there is no limit to the number of items you can have in the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;workspace&lt;/code&gt;, when this number grows, Visual Studio’s performance drops drastically; that is indisputable. Of course, there are &lt;a href=&quot;http://stackoverflow.com/questions/28022712/visual-studio-2013-tfs-slow&quot;&gt;ways to reduce this effect&lt;/a&gt;, but the fact is that there comes a moment when nothing helps anymore, and so we are forced to look for new options.&lt;/p&gt;

&lt;p&gt;Now GIT, besides being an excellent version control system, robust and maintained by a huge community, has as its main promise being &lt;a href=&quot;https://git-scm.com/about/small-and-fast&quot;&gt;extremely fast&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And it has been! Our initial tests showed that using it with Visual Studio will make our work countless minutes faster. A clear example is when we decide to switch from one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;branch&lt;/code&gt; to another; a process that in TFS took on average up to a full minute happens almost instantly with GIT&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;It proves to be a natural choice for those who got used to a product that is easy to use and just works.&lt;/p&gt;

&lt;h2 id=&quot;first-steps-with-git-for-a-tfvc-developer&quot;&gt;First steps with GIT for a TFVC Developer&lt;/h2&gt;

&lt;p&gt;Git is much simpler than TFVC, and the first thing you will notice when you start using it
will be its terminology, some slightly different concepts, and missing and/or extra features, which end up making everything look confusing; but don’t worry, below I list the main differences between the two.&lt;/p&gt;

&lt;h3 id=&quot;goodbye-workspaces&quot;&gt;Goodbye workspaces&lt;/h3&gt;

&lt;p&gt;A mandatory and very important feature in TFVC &lt;strong&gt;does not exist&lt;/strong&gt; in GIT. To start working with GIT you don’t need to create workspaces, configuring directories, file locations, permissions, etc. Just choose a directory on your computer, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clone&lt;/code&gt; the repository you want to work on, and get to work.&lt;/p&gt;

&lt;h3 id=&quot;branches-are-simpler&quot;&gt;Branches are simpler&lt;/h3&gt;

&lt;p&gt;It really shines here; unlike TFVC, which forces you to copy &lt;em&gt;all&lt;/em&gt; the files of the current project into a different directory for a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;branch&lt;/code&gt;, GIT is smart enough to manage by itself the differences between the files of each branch using the same directory.&lt;/p&gt;

&lt;h3 id=&quot;no-more-check-ins-or-check-outs&quot;&gt;No more Check ins or Check outs&lt;/h3&gt;

&lt;p&gt;Git has no concept of file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lock&lt;/code&gt;; you can edit and ‘submit’ any file at any time to the central repository on any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;branch&lt;/code&gt;&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, but be careful: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;checkout&lt;/code&gt; in GIT has &lt;a href=&quot;https://git-scm.com/docs/git-checkout&quot;&gt;another meaning&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This has an interesting effect: to avoid future headaches, from the very beginning teams find themselves obliged to agree among themselves and work following a certain pattern to make sure there are no conflict problems.&lt;/p&gt;

&lt;p&gt;Among them, the most known and used is &lt;a href=&quot;http://nvie.com/posts/a-successful-git-branching-model/&quot;&gt;git-flow&lt;/a&gt;, which basically uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;branches&lt;/code&gt; to organize the updates to the code base.&lt;/p&gt;

&lt;h3 id=&quot;local-and-server-repositories&quot;&gt;Local and server repositories&lt;/h3&gt;

&lt;p&gt;Just like TFVC has local and server repositories, so does GIT, but they are conceptually different.&lt;/p&gt;

&lt;p&gt;In TFVC, when you use the local repository option, on every operation (checkin, checkout, shelve, etc.) TFVC checks &lt;em&gt;the content of each file&lt;/em&gt; in the workspace against the files in the server repository; for server repositories, the check is only on the read-only flag.&lt;/p&gt;

&lt;p&gt;In GIT it is different: you will always work on your local repository, sending to the server only when the work is ready.&lt;/p&gt;

&lt;h3 id=&quot;commits-fetch-pull-push-and-sync&quot;&gt;Commits, fetch, pull, push and sync&lt;/h3&gt;

&lt;p&gt;In TFVC there are basically two ways to work with files:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check out&lt;/code&gt;, which basically tells TFVC that you want to edit the file, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check in&lt;/code&gt;, where you send the changes you made to the central repository, visible to everyone.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shelve&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unshelve&lt;/code&gt;, similar to the previous one, but the changes are available only to you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In GIT the workflow is different; first you need to understand that your files will always be in one of four different states:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;untracked&lt;/code&gt;: as the name says, these are files that git is not tracking. Files that were not present in the last commit and have not been &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;staged&lt;/code&gt; yet;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unmodified&lt;/code&gt;: files that were in the last commit and were not modified;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;modified&lt;/code&gt;: files that were in the last commit and were modified but have not been staged yet;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;staged&lt;/code&gt;: files that are ready to be part of the next commit;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;file-state-flow&quot;&gt;File state flow&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/images/lifecycle.png&quot; alt=&quot;File state flow&quot; /&gt;
&lt;small&gt;Where from and where to a file can ‘jump’ during its lifecycle, source: https://git-scm.com/&lt;/small&gt;&lt;/p&gt;

&lt;h4 id=&quot;commit&quot;&gt;commit&lt;/h4&gt;

&lt;p&gt;A good analogy would be to compare them with the Windows restore feature, where ‘restore points’ are saved before important changes are made to the system, allowing you, in case things go wrong, to go back to a safe version.&lt;/p&gt;

&lt;p&gt;Commits in GIT are an important tool; besides letting developers save their progress by marking safe points they can go back to if something goes wrong, when well done they can also be an excellent way to &lt;a href=&quot;https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit&quot;&gt;automate documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Don’t forget that &lt;strong&gt;only staged files&lt;/strong&gt; are recorded by the commit.&lt;/p&gt;

&lt;h4 id=&quot;fetch&quot;&gt;fetch&lt;/h4&gt;

&lt;p&gt;Downloads the named HEADs or tags from the server repository, along with their objects, updating your local repository WITHOUT doing a merge.&lt;/p&gt;

&lt;p&gt;A super simplification would be to think that the files on your computer have reference links to a commit version on the server. When this version changes, you need to update this reference before you can send new versions. What fetch does is download the updates that happened since the last fetch and save them in a ‘special area’ that you can inspect, if you want, before doing a merge.&lt;/p&gt;

&lt;h4 id=&quot;pull&quot;&gt;pull&lt;/h4&gt;

&lt;p&gt;Pull, besides fetching the files like fetch does, also does the merge automatically for you. See this example.&lt;/p&gt;

&lt;p&gt;Imagine this is the state of your repositories:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	  A---B---C master on the server
	 /
    D---E---F---G master &amp;lt;- local repository
	^
	origin/master last fetch (or pull)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After the PULL, git will update the references of commit G with B and C, which were made on the server, creating a new one from the merge called H.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	  A---B---C master on the server
	 /         \
    D---E---F---G---H &amp;lt;- local repository
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;push&quot;&gt;push&lt;/h4&gt;

&lt;p&gt;When you have finished your work, fixed that bug or feature, use this command to send your changes to the server repository. This command will take all the changes that were committed locally and send them to the server. But be careful: you can only ‘send’ if the local/remote references are up to date, so it is always a good idea to check using fetch.&lt;/p&gt;

&lt;h4 id=&quot;sync&quot;&gt;sync&lt;/h4&gt;

&lt;p&gt;Think of sync as everything said above, but done from a single user operation. It will do whatever is needed so that your local repository becomes equal to the remote one: fetching updates (fetch), merging (merge) and sending your changes (push), leaving some work for you to do only if there is a conflict.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Without a doubt GIT is an excellent tool that made our development cycle much more productive. Every day that goes by we learn more, and the easier its daily use gets. It really was an excellent decision that will last for a few more years.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Computer with 16GB of RAM, SSD, I7 processor and a dedicated 10MB fiber optic internet connection, using GitHub and Visual Studio Team Services. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;If you have write permission, of course. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/vamos-migrar-do-tfs-para-o-github/&quot;&gt;Migrating from TFVC to Git&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on January 30, 2016.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[karma-typescript-preprocessor2: running TypeScript tests in Karma without temp files]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/karma-typescript-preprocessor2/" />
  <id>https://www.estacouveflor.com/karma-typescript-preprocessor2</id>
  <published>2015-11-11T00:00:00+00:00</published>
  <updated>2015-11-11T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">How a small Karma plugin compiled TypeScript in memory with gulp-typescript and a single tsconfig.json, and why its name ends with a 2.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#first-a-few-words&quot; id=&quot;markdown-toc-first-a-few-words&quot;&gt;First, a few words&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-problem&quot; id=&quot;markdown-toc-the-problem&quot;&gt;The problem&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-to-use-it&quot; id=&quot;markdown-toc-how-to-use-it&quot;&gt;How to use it&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-one-opinion-it-had&quot; id=&quot;markdown-toc-the-one-opinion-it-had&quot;&gt;The one opinion it had&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-it-worked-inside&quot; id=&quot;markdown-toc-how-it-worked-inside&quot;&gt;How it worked inside&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#my-first-pull-request&quot; id=&quot;markdown-toc-my-first-pull-request&quot;&gt;My first pull request&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#where-it-ended-up&quot; id=&quot;markdown-toc-where-it-ended-up&quot;&gt;Where it ended up&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-i-take-from-it&quot; id=&quot;markdown-toc-what-i-take-from-it&quot;&gt;What I take from it&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;p&gt;In 2015, if you had TypeScript code and browser tests, you needed some glue in between. This post
is about the glue I wrote: &lt;a href=&quot;https://github.com/klaygomes/karma-typescript-preprocessor2&quot;&gt;karma-typescript-preprocessor2&lt;/a&gt;.
You will see what it solved, how to configure it, and how it worked inside.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A note on timing: I’m filing this post on the day version 1.0.0 went to npm, November 11th, 2015,
but I’m writing it looking back, so I will also tell you where the project ended up.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;first-a-few-words&quot;&gt;First, a few words&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Test runner&lt;/strong&gt;: a program that finds your tests, runs them and reports what passed and what
failed. &lt;a href=&quot;https://github.com/karma-runner/karma&quot;&gt;Karma&lt;/a&gt; is a test runner that runs your JavaScript
tests inside real browsers.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Transpile&lt;/strong&gt;: translate code from one language to another at the same level. TypeScript is
transpiled to JavaScript, because browsers only understand JavaScript.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Preprocessor&lt;/strong&gt;: in Karma, a plugin that transforms each file before it is sent to the browser.
Here, it takes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ts&lt;/code&gt; file and hands Karma the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.js&lt;/code&gt; version.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;/h2&gt;

&lt;p&gt;Karma can’t run a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ts&lt;/code&gt; file, so something has to compile it first.&lt;/p&gt;

&lt;p&gt;A preprocessor for that already existed on npm: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;karma-typescript-preprocessor&lt;/code&gt;, published by
Sergey Todyshev in 2013, described as “a karma-runner plugin to compile typescript files on the
fly”. Mine is not a fork of it; the git history starts from scratch. But the name was taken, so I
added a &lt;strong&gt;2&lt;/strong&gt; at the end. The README even says it: “note number &lt;strong&gt;2&lt;/strong&gt; at the end”. Both plugins
register the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typescript&lt;/code&gt; preprocessor name and read the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typescriptPreprocessor&lt;/code&gt;
section of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;karma.conf.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What mine does differently is written in the first line of its README:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Transpile files in memory using gulp-typescript. No temp files are generated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;

&lt;p&gt;Install it as a dev dependency:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ npm install karma-typescript-preprocessor2 --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then point Karma at it. This is the full example from the README:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// karma.conf.js&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;**/*.ts&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// Preprocessor will convert Typescript to Javascript&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;preprocessors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;**/*.ts&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;typescript&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;sourcemap&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// Use karma-sourcemap-loader&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;typescriptPreprocessor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// options passed to typescript compiler&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;tsconfigPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;./tsconfig.json&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// *obligatory&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;compilerOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// *optional&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;removeComments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// Options passed to gulp-sourcemaps to create sourcemaps&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;sourcemapOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;includeContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sourceRoot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;/src&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// ignore all files that ends with .d.ts (this files will not be served)&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;ignorePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;ts$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// transforming the filenames&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// you can pass more than one, they will be execute in order&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;transformPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// *optional&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;ts$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;[\/\\]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;[\/\\]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// remove directory test and change to /&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;The short version of each option:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsconfigPath&lt;/code&gt; is required. The plugin refuses to start without it.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compilerOptions&lt;/code&gt; lets you override (or add) anything from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsconfig.json&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ignorePath&lt;/code&gt; skips files you don’t want served, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.d.ts&lt;/code&gt; definition files.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transformPath&lt;/code&gt; renames the virtual path Karma sees; the example strips a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; folder so specs
can import modules from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sourcemapOptions&lt;/code&gt; is passed to gulp-sourcemaps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-one-opinion-it-had&quot;&gt;The one opinion it had&lt;/h2&gt;

&lt;p&gt;The plugin only accepts configuration through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsconfig.json&lt;/code&gt;. In the README’s words, “a lot of
problems with typos and references are completely solved, as compiler will use same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;basedir&lt;/code&gt; to
resolve files”.&lt;/p&gt;

&lt;h2 id=&quot;how-it-worked-inside&quot;&gt;How it worked inside&lt;/h2&gt;

&lt;p&gt;The whole plugin is a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.js&lt;/code&gt;. Three ideas carry it:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Compile the project, not the file.&lt;/strong&gt; When Karma starts, the plugin calls
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts.createProject(tsconfigPath, compilerOptions)&lt;/code&gt; from
&lt;a href=&quot;https://www.npmjs.com/package/gulp-typescript&quot;&gt;gulp-typescript&lt;/a&gt; and compiles everything once.
The output goes into a writable stream that keeps each compiled file in an in-memory buffer. Nothing
touches the disk. The README credits gulp-typescript’s incremental compilation for fast rebuilds.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A tiny state machine.&lt;/strong&gt; The plugin is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;idle&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compiling&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compilationCompleted&lt;/code&gt;. If Karma
asks for a file while a compilation is running, the request waits in a queue. When compilation
ends, the queue is drained and each file is served from the buffer.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Recompile on change.&lt;/strong&gt; Karma marks a changed file with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sha&lt;/code&gt;. When the plugin sees it, it
queues the request and triggers a new compilation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;my-first-pull-request&quot;&gt;My first pull request&lt;/h2&gt;

&lt;p&gt;This was my first open-source project, and I was really happy the day another contributor sent me a pull
request. It was &lt;a href=&quot;https://github.com/klaygomes/karma-typescript-preprocessor2/pull/2&quot;&gt;#2&lt;/a&gt;, opened by
&lt;a href=&quot;https://github.com/rich-j&quot;&gt;@rich-j&lt;/a&gt; on February 7th, 2016, and merged the next day. It added
sourcemap support through gulp-sourcemaps, because gulp-typescript ignores the sourcemap settings in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsconfig.json&lt;/code&gt;, and it made &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsconfigPath&lt;/code&gt; relative to Karma’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;basePath&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A few months later, &lt;a href=&quot;https://github.com/lelandmiller&quot;&gt;@lelandmiller&lt;/a&gt; sent
&lt;a href=&quot;https://github.com/klaygomes/karma-typescript-preprocessor2/pull/3&quot;&gt;#3&lt;/a&gt;, merged on May 21st, 2016.
It compared files by full path instead of file name, so two files with the same name in different
folders stopped colliding.&lt;/p&gt;

&lt;h2 id=&quot;where-it-ended-up&quot;&gt;Where it ended up&lt;/h2&gt;

&lt;p&gt;The last version on &lt;a href=&quot;https://www.npmjs.com/package/karma-typescript-preprocessor2&quot;&gt;npm&lt;/a&gt; is 1.2.1,
from June 19th, 2016. The repository got a few more commits until 2017 (a refactor and a fix for
default compiler options), but they were never published. If you read &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; today, be aware it
does not match what npm serves: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.js&lt;/code&gt; requires &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lodash.assignin&lt;/code&gt; while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; lists
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lodash.assign&lt;/code&gt;, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transformPath&lt;/code&gt; check throws when you pass an array.&lt;/p&gt;

&lt;p&gt;The ecosystem moved on too: Karma’s own README now says “Karma is deprecated and is not accepting
new features or general bug fixes”.&lt;/p&gt;

&lt;h2 id=&quot;what-i-take-from-it&quot;&gt;What I take from it&lt;/h2&gt;

&lt;p&gt;Two decisions still feel right to me: keeping compiled output in memory, so there is nothing to
clean up, and letting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsconfig.json&lt;/code&gt; be the single source of truth for the compiler.&lt;/p&gt;

&lt;p&gt;The code is about 200 lines and MIT licensed. If you are curious how a Karma plugin is wired
together (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$inject&lt;/code&gt; array, the factory, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;done&lt;/code&gt; callback), it is a quick read.
&lt;a href=&quot;https://github.com/klaygomes/karma-typescript-preprocessor2&quot;&gt;Take a look on GitHub&lt;/a&gt;, and if you
still have an old project running it, I would love to hear about it in the comments.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/karma-typescript-preprocessor2/&quot;&gt;karma-typescript-preprocessor2: running TypeScript tests in Karma without temp files&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on November 11, 2015.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[CALLs: how they use the stack (in Portuguese)]]></title>
  <link rel="alternate" type="text/html" href="https://www.estacouveflor.com/como-calls-fazem-uso-stack-post/" />
  <id>https://www.estacouveflor.com/como-calls-fazem-uso-stack-post</id>
  <published>2009-04-02T00:00:00+00:00</published>
  <updated>2009-04-02T00:00:00+00:00</updated>
  <author>
    <name>Cleiton Loiola</name>
    <uri>https://www.estacouveflor.com/</uri>
    <email>email@cleiton.dev</email>
  </author>
  <summary type="text">A small article about procedures (functions) and how they use the stack to pass variables. My Portuguese translation of a classic beginner tutorial.</summary>
  <content type="html">
    &lt;nav class=&quot;hidden&quot;&gt;
&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introdução&quot; id=&quot;markdown-toc-introdução&quot;&gt;Introdução&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ferramentas-necessárias&quot; id=&quot;markdown-toc-ferramentas-necessárias&quot;&gt;Ferramentas Necessárias&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#porque-usar-procedures&quot; id=&quot;markdown-toc-porque-usar-procedures&quot;&gt;Porque usar procedures?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#a-pilha&quot; id=&quot;markdown-toc-a-pilha&quot;&gt;A PILHA&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#procedures---suas-entranhas&quot; id=&quot;markdown-toc-procedures---suas-entranhas&quot;&gt;PROCEDURES - Suas entranhas&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#lendo-dados-da-stack&quot; id=&quot;markdown-toc-lendo-dados-da-stack&quot;&gt;Lendo dados da stack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/nav&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
    var toc = document.getElementById(&quot;markdown-toc&quot;);
    var destination = document.getElementById(&quot;toc-destination&quot;);
    if (!toc || !destination) return;
    destination.appendChild(toc);

    var links = Array.prototype.slice.call(toc.querySelectorAll(&quot;a[href^=&apos;#&apos;]&quot;));
    var headings = links
      .map(function (link) { return document.getElementById(decodeURIComponent(link.hash.slice(1))); })
      .filter(Boolean);
    if (!(&quot;IntersectionObserver&quot; in window) || headings.length === 0) return;

    var visible = new Set();
    var setActive = function (id) {
      links.forEach(function (link) {
        link.classList.toggle(&quot;is-active&quot;, decodeURIComponent(link.hash.slice(1)) === id);
      });
    };
    var observer = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) visible.add(entry.target);
        else visible.delete(entry.target);
      });
      var current = headings.filter(function (heading) { return visible.has(heading); })[0];
      if (!current) {
        current = headings.filter(function (heading) { return heading.getBoundingClientRect().top &lt; 0; }).pop();
      }
      if (current) setActive(current.id);
    }, { rootMargin: &quot;-96px 0px -55% 0px&quot; });
    headings.forEach(function (heading) { observer.observe(heading); });
  });
&lt;/script&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;English readers:&lt;/strong&gt; this is my 2009 Portuguese translation of a beginner’s tutorial on how CALLs use the stack. The original is in English at &lt;a href=&quot;http://www.woodmann.com/krobar/beginner/168.htm&quot;&gt;woodmann.com&lt;/a&gt;, so go read it there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/_//_                                                    
/`\//_|/_/ 
	_/ -.- .-.. .- -.-- __________________Assembly IA-32 
	---------------------------------------------
=-------- CALL&apos;s - Como elas fazem uso da Stack ----------= 
	--------------------------------------------- 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;introdução&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;Este pequeno artigo fala sobre procedures(funções) e como elas usam a pilha para passar variáveis. Ele poderá ser muito
util principalmente para iniciantes. Eu não acho que crackers experientes terão muito proveito deste, porém se você não sabe
como a pilha funciona, o que uma procedure faz e como os parametros são passados para ela, então este documento poderá ajuda-lo e muito. Eu também gostaria de avisar que todos nós somos responsáveis por nossas próprias ações. Eu não serei responsável por nenhum ato ilegal que seja tomado com o conhecimento providenciado aqui. Então, se ajeite em uma posição confortável divita-se :)&lt;/p&gt;

&lt;h2 id=&quot;ferramentas-necessárias&quot;&gt;Ferramentas Necessárias&lt;/h2&gt;

&lt;p&gt;Tudo que você vai precisará será:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Algum espaço em seu celebro&lt;/li&gt;
  &lt;li&gt;Um drink; Um long island-ice tea dá para o gasto:
    &lt;ul&gt;
      &lt;li&gt;4 dedos de rum,&lt;/li&gt;
      &lt;li&gt;4 dedos de tequila,&lt;/li&gt;
      &lt;li&gt;4 dedos de whiskey,&lt;/li&gt;
      &lt;li&gt;4   dedos de vodka,&lt;/li&gt;
      &lt;li&gt;Um pouco de suco de limão e preencha o resto com coca-cola. Uma delicia!&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;porque-usar-procedures&quot;&gt;Porque usar procedures?&lt;/h2&gt;

&lt;p&gt;Eu tenho certeza que você já se perguntou o que é uma 
procedure. Qual sua utilidade? Imagine que você esta desen-
volvendo um programa que tenha que escrever alguns caracteres 
na tela com uma certa frequencia por exemplo. Este texto não
será o mesmo todas as vezes, mas a rotina, o código para tra-
zer os caracteres a tela será sempre o mesmo.&lt;/p&gt;

&lt;p&gt;Sendo assim, para fazer isso,você teria que escrever o mesmo código
repetida vezes para cada mensagem que você desejasse exibir 
na tela, porém há uma maneira mais fácil. Apenas escreva o 
código uma vez, logo após lhe de um nome, uma referencia, como por 
exemplo “write_to_screen” e então, a parti de agora tudo o que 
você precisa fazer é chamar esta função. Mas espere, há outro
problema: Nos temos diferente mensagens, então, nos iremos 
precisar de uma variável, algo como MSG que guardaria a 
mensagem que nos queremos imprimir e é claro nos teremos 
que passa-la a função. Esta tarefa se pareceria assim, caso 
fosse escrito em uma linguagem de alto nível como C++.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Exemplo:
	write_to_screen(LPSTR *msg);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mas como seria em Assembly? Seria mais ou menos assim:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Exemplo:
	push 	MSG				;insiro MSG na pilha
	call	write_to_screen	;chamo a procedure
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Este exemplo mostra dois tópicos que foram explicados neste 
tutorial. O que uma chamada a procedure é e porque você precisa
 passar variáveis
para ela. Agora que você sabe para que serve uma procedure e o 
que ela tem de melhor, talvez você esteja
confuso por causa do push, então nossa próxima etapa é falar 
um pouco mais sobre a pilha.&lt;/p&gt;

&lt;h2 id=&quot;a-pilha&quot;&gt;A PILHA&lt;/h2&gt;

&lt;p&gt;A pilha é uma estrutura que guarda valores. Estes valores
sempre possuem 4 bytes (= 1 DWORD) de comprimento. Ela funciona
em LIFO, sigla para Last In First Out que em português quer dizer
O primeiro que entra é o ultimo a sair.&lt;/p&gt;

&lt;p&gt;Isso quer dizer que um valor
que foi recentemente colocado na pilha será removido primeiro. Há apenas dois
comandos, instruções, para trabalhar com a pilha. estes são chamados push e pop.
push insere um valor na pilha e pop remove este valor.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Exemplo:

push a		Pilha= {a}
push b		Pilha= {a,b}
push c		Pilha= {a,b,c}
pop eax		Pilha= {a,b} eax = c
pop ebx		Pilha= {a} eax = c; ebx = b
push eax   	Pilha= {a,c} eax = c; ebx = b
push 5		Pilha= {a,c,5} eax = c; ebx = b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mas push e pop também fazem coisas adicionais. para entender, nós precisamos primeiro
dá uma olhada para o registrador &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt; (Apontador de pilha). Este registrador sempre terá uma 
referencia para o inicio da pilha. ou melhor o ultimo valor que foi colocado lá. a pilha sempre cresce de um valor alto de memória para um baixo,
então se você incluir um valor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt; será subtraido por 4, se você remover um valor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt; será incrementado por 4.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Exemplo:

ESP = 7E0000; EAX = 01020304
: ...
:7DFFF0 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
:7E0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00

Este é o estado inicial da pilha preenchido com 78563421.

Agora se você inserir EAX na pilha você terá:

ESP = ESP - 4 = 7DFFF0                      ESP Aqui
: ...                                       |
:7DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
:7E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00

Como você pode ver, o apontador de pilha é ajustado
e o valor é escrito na posição correta da memória.


pop ebx

Agora você removeu o valor:

ESP = ESP + 4 = 7E0000		EBX = 01020304

:7DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
:7E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
		|
		ESP aponta para cá.
		Note que o valor removido não foi modificado!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;É claro qu evocê também pode adcionar ou subtrair algo de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt;.
Vamos ver o que acontece se nós adcionarmos 1 a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;INC ESP ; ESP = ESP + 1 = 7E0001

:7DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
:7E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
		   |
		   ESP agora aponta para cá.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vamos agora remover um valor:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pop EBX
ESP = ESP + 4 = 7E0005
:7DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
:7E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
					   |
					   ESP agora aponta para cá.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;E &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EBX&lt;/code&gt; ficou com o valor 00785634. Note que após esta operação a pilha ficou
“fora de ordem”, então você deve sempre apenas adcionar multiplos de 4 a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora que você sabe como a pilha funciona e o que ela faz, vamos analisar as procedures
mais profundamente:&lt;/p&gt;

&lt;h2 id=&quot;procedures---suas-entranhas&quot;&gt;PROCEDURES - Suas entranhas&lt;/h2&gt;

&lt;p&gt;Como você viu, a pilha é um lugar ideal para guardar valores. Vamos agora dá uma nova olhada
ao nosso pequeno primeiro exemplo que mostramos anteriormente. Agora com o nosso novo conheicmneot
podemos entender o que acontece e té mesmo perceber um bug sério.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;push MSG              ; Não irá funcionar, já que a pilha só pode guadar 4 bytes!
call write_to_screen  ; então a procedure irá ler o valor de MSG da pilha
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Fica claro que termos que passar o endereço de MSG ao invés de seu valor. Nos podemos fazer
isso facilmente com com o comando(instrução) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LEA EAX, MSG&lt;/code&gt;. AX agora possui o endereço de MSG. Logo após nos 
o inserimos com &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUSH EAX&lt;/code&gt;.  Vamos transcrever este processo e ver o que realmente esta acontecendo:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Antes do PUSH:

 dados: EAX = 00000000
	  :00450000 31 32 33 34 35 36 37 38-39 30 00 00 00 00 00 00   1234567890......

 pilha: ESP = 007E0000
	  :007DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
	  :007E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00

Depois do PUSH:

	 :00412l00 LEA EAX, MSG  ; nada muda exeto que EAX agora vale 00450000
	 :00412104 push eax	  ; os dados continuam no lugar, porém a pilha muda
          ; pilha: ESP = 007DFFFC                         ............ address
          ;      :007DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 45 00
          ;      :007E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
			     :00412105 call write_to_screen
          ; insere a sequqencia na tela.
		  ; short break ---
			     :00412110 próxima instrução...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mas o que a instrução call irá fazer? Ela irá fazer algo muito importante. Ela irá automáticamente 
salvar o endereço dá próxima instrução na pilha. Mas porque? Porque esta é uma chamada a procedure e 
não um JMP e depois que a procedure tiver feito seu trabalho, o programa deve continuar de onde 
parou antes da rotinar se chamada. Ou seja, isto é tudo que call é. Ser responsável em salvar o endereço 
da próxima instrução na pilha para que o PC saiba onde por onde prosseguir.
Vamos ver como a pilha se parece depois de encontrar uma instrução call&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Exemplo:

	pilha: ESP = 007DFFF8             ........... endereço de retorno salvo na stack
		 :007DFFF0 00 00 00 00 00 00 00 00-10 21 41 00 00 00 45 00
		 :007E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;e o controle de execução pulará para onde call aponta. Sendo assim, sempre que você entra
em uma procedure você tem no topo da pilha o endereço de retorno. Agora existe apenas um 
questão a resolver: Como a procedure ler os dados da pilha?&lt;/p&gt;

&lt;h2 id=&quot;lendo-dados-da-stack&quot;&gt;Lendo dados da stack&lt;/h2&gt;

&lt;p&gt;Esta é a parte mais interessante e há várias formas de se fazer, a primeira possibilidade
é retirar o valor de retorno usando pop e salvar em algum lugar, depois retirar o valor
dos dados restantes também usando pop e depois reincluir usando push o endereço de retorno.
Esta tarefa pode ser complicada especiamente se você tem muitos valores em uma chamada 
enorme, o que forçará você a salvar os valores novamente na stack por que você não pode
guarda-los todos em um registrador de dados. Pode funcionar para pequenas chamadas com 
poucos parametros.&lt;/p&gt;

&lt;p&gt;Então qual seria outro jeito? É fácil, basta você salvar EBP na stack
e depois guadar o endereço da stack dentro de EMP usando a instrução &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov EBP, ESP&lt;/code&gt; 
agora você pode endereçar todas as variáveis que são relativas a EBP  através de
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov eax, [EBP+20]&lt;/code&gt;, desta forma você terá maior controle da stack, você também poderá
continuar usando a stack normalmente na chamada tendo que apenas ter certeza que o valor
de retorno estará no topo da stack que você salvou em EBP quando você sair da chamada.&lt;/p&gt;

&lt;p&gt;Vamos olhar este exemplos simples que eu extrai de um MP3 CD Maker com o Win32DASM:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;beginning of the call
:004301A1 push ebp                    ; ebp foi salvo
:004301A2 mov ebp, esp                ; agora ebp aponta para o top da stack
									; você não precisa mais se preocupar com pushes e pops
									; por que você acessa os paramentros usando EBP como referencia agora
:004301A4 mov eax, dword ptr [ebp+08] ; é igual a pop eax, pop eax mas você perderia o valor de retorno
:004301A7 push esi                    ; salva outro valor
.
. call routine unimportant.
. leaving the call
:004301FF pop esi                     ; recupera  esi
:00430200 pop ebp                     ; recupera o ponteiro de base original
:00430201 ret                         ; agora o endereço de retorno esta no topo da stack
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;notice&quot;&gt;&lt;strong&gt;Dica&lt;/strong&gt; Você pode ver algo como &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov eax, [ebp+10]&lt;/code&gt;, agora você renomear a variável &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ebp+10]&lt;/code&gt; por que ela sempre apontará para o mesma chamada. Em uma chamada protegida com nome e serial, por exemplo, você poderia dizer que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ebp+10]&lt;/code&gt; e o nome e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ebp+14]&lt;/code&gt; é o serial. Isso fará com que programas e especialmente deadlistings muito mais fáceis de serem lidas. 
Agora com todo este conhecimento você já pode dá uma olhada em alguns codesnippets extraídos com o Win32DASM.&lt;/p&gt;

&lt;p&gt;Tradução por Cleiton Gomes em 02/04/2009, artigo original:
http://www.woodmann.com/krobar/beginner/168.htm&lt;/p&gt;

&lt;p&gt;.EOF&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.estacouveflor.com/como-calls-fazem-uso-stack-post/&quot;&gt;CALLs: how they use the stack (in Portuguese)&lt;/a&gt; was originally
published by Cleiton Loiola at &lt;a href=&quot;https://www.estacouveflor.com/&quot;&gt;Esta couve flor&lt;/a&gt; on April 02, 2009.&lt;/p&gt;
  </content>
</entry>

</feed>
