<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Wes Souza</title>
    <description>The latest articles on Forem by Wes Souza (@wes).</description>
    <link>https://forem.com/wes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F138714%2Fc81364c1-232d-4818-8a59-4b1faf7a68c2.jpeg</url>
      <title>Forem: Wes Souza</title>
      <link>https://forem.com/wes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/wes"/>
    <language>en</language>
    <item>
      <title>'B' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'A'.</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Sun, 15 Jan 2023 21:23:12 +0000</pubDate>
      <link>https://forem.com/wes/b-is-assignable-to-the-constraint-of-type-t-but-t-could-be-instantiated-with-a-different-subtype-of-constraint-a-2l38</link>
      <guid>https://forem.com/wes/b-is-assignable-to-the-constraint-of-type-t-but-t-could-be-instantiated-with-a-different-subtype-of-constraint-a-2l38</guid>
      <description>&lt;p&gt;This error has plagued me for years now. And &lt;a href="https://stackoverflow.com/a/70392066/572647"&gt;thanks to Inigo I finally understood the problem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;TL;DR: When you use &lt;code&gt;T extends A&lt;/code&gt; in a generic declaration, you require &lt;code&gt;T&lt;/code&gt; to be &lt;em&gt;at least&lt;/em&gt; &lt;code&gt;A&lt;/code&gt;, but it can have more properties (by being a different subtype).&lt;/p&gt;

&lt;p&gt;The problem arises when you want to &lt;em&gt;create&lt;/em&gt; an object that conforms to &lt;code&gt;T&lt;/code&gt; thinking it can just conform to &lt;code&gt;A&lt;/code&gt;. You can't, because &lt;code&gt;T&lt;/code&gt; can require additional or more specific properties than &lt;code&gt;A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This happens a lot when we create &lt;a href="https://beta.reactjs.org/learn/reusing-logic-with-custom-hooks"&gt;React Hooks&lt;/a&gt; that handle generic objects and arrays.&lt;/p&gt;

&lt;p&gt;One solution is to pass a callback function to the generic that knows how to translate something like &lt;code&gt;A&lt;/code&gt; to &lt;code&gt;T&lt;/code&gt;, given what your generic function expects to handle.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Code
&lt;/h1&gt;

&lt;p&gt;Suppose we are creating a hook to abstract filtering options for a &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/combobox/"&gt;combobox&lt;/a&gt;, having a disabled "No results found" option if there is no result for the search:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SelectOption&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useComboboxFilter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;SelectOption&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;filterValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;filteredOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;filteredOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filterValue&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filterValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filterValue&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;filteredOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;filteredOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No results found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;filteredOptions&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;
  Note for React devs
  &lt;br&gt;
Because this is an example, I didn't properly optimize the code. A proper React Hook should wrap &lt;code&gt;filteredOptions&lt;/code&gt; and the return object in a &lt;code&gt;useMemo&lt;/code&gt;:&lt;br&gt;

&lt;pre&gt;&lt;code&gt;&lt;span&gt;function&lt;/span&gt; &lt;span&gt;useComboboxFilter&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt; &lt;span&gt;extends&lt;/span&gt; &lt;span&gt;SelectOption&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
  &lt;span&gt;options&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;T&lt;/span&gt;&lt;span&gt;[];&lt;/span&gt;
  &lt;span&gt;filterValue&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}):&lt;/span&gt; &lt;span&gt;{&lt;/span&gt; &lt;span&gt;filteredOptions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;T&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt; &lt;span&gt;}&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
  &lt;span&gt;const&lt;/span&gt; &lt;span&gt;filteredOptions&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;useMemo&lt;/span&gt;&lt;span&gt;(()&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
    &lt;span&gt;let&lt;/span&gt; &lt;span&gt;filteredOptions&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;filterValue&lt;/span&gt;
      &lt;span&gt;?&lt;/span&gt; &lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;filter&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;option&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt;
          &lt;span&gt;option&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;includes&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;filterValue&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
        &lt;span&gt;)&lt;/span&gt;
      &lt;span&gt;:&lt;/span&gt; &lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;

    &lt;span&gt;if&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;filterValue&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;&lt;span&gt;filteredOptions&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
      &lt;span&gt;filteredOptions&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;
        &lt;span&gt;{&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;"&lt;/span&gt;&lt;span&gt;No results found&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;disabled&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;true&lt;/span&gt; &lt;span&gt;},&lt;/span&gt;
      &lt;span&gt;];&lt;/span&gt;
    &lt;span&gt;}&lt;/span&gt;

    &lt;span&gt;return&lt;/span&gt; &lt;span&gt;filteredOptions&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
  &lt;span&gt;},&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;filterValue&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;

  &lt;span&gt;return&lt;/span&gt; &lt;span&gt;useMemo&lt;/span&gt;&lt;span&gt;(()&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;({&lt;/span&gt; &lt;span&gt;filteredOptions&lt;/span&gt; &lt;span&gt;}),&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;filteredOptions&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/p&gt;

&lt;h1&gt;
  
  
  The Problem
&lt;/h1&gt;

&lt;p&gt;If you &lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAyhA2EDGwDyZgEsD2A7KAvFAN4BQUUuAhgLYQBcUAzsAE6a4DmA3OVAG5V4AVwbM2HTlAA+lYfHi8KAE0xMqAI0TLGG7NkRVcvAL69SAM2G4UOfMKYQAwthp69ADwBimeMAisADwAKlAQHv64ykywCMhoGHYAfAAUYKzYYEyMZBSZWHjZUMEA2gC6SlAWvv6sAGpCoows7FymAJQ5VTUBEMroBbhFpWVQJiR8iMDdfr39iYWEUOmZTAB01bP1jRB8FAD8yxlZa-l265u1KSlneO2ESVC3uGvUdGscSCLKEExpxxcetsRBB2u09lBGCsTs8mOYKJgLFB-qsNkCGiCoAAyLFQACElzmA3Oa0QXGAAAt7rkKDNan1iYsiCUIRRiJRaGIAEQAOWwUFYv3kwBiFmw1mUXIANAIdoxcPJ4DLVOotH1GGxRGMpRCKnwTKQ+ILgMJWPh2YTBfNBjEzKQTEA"&gt;check this code with the TypeScript compiler&lt;/a&gt;, you will get this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type '{ name: string; value: null; disabled: true; }'
is not assignable to type 'T'.
  '{ name: string; value: null; disabled: true; }' is 
  assignable to the constraint of type 'T', but 'T' could
  be instantiated with a different subtype of constraint
  'SelectOption'. ts(2322)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a cryptic error message: it properly describes the problem without helping the reader understand how this happened or what they actually did wrong.&lt;/p&gt;

&lt;p&gt;The problem here is quite simple: &lt;code&gt;{ name: string; value: null; disabled: true; }&lt;/code&gt; satisfies &lt;code&gt;SelectOption&lt;/code&gt;, but because &lt;code&gt;T&lt;/code&gt; could be a different subtype of &lt;code&gt;SelectOption&lt;/code&gt;, that is, a type with slightly different requirements, your generic function can't know what it is to &lt;strong&gt;create a new version of it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A clear problem for our example is: imagine the generic type &lt;code&gt;T&lt;/code&gt; we created requires an &lt;code&gt;id&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type SelectOptionWithId = {
  id: string;
} &amp;amp; SelectOption;

const myFilter = useComboboxFilter&amp;lt;SelectOptionWithId&amp;gt;({
  options: [],
  filterValue: "bla",
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result &lt;code&gt;myFilter&lt;/code&gt; in this case will have an object &lt;em&gt;without &lt;code&gt;id&lt;/code&gt;&lt;/em&gt;, because the generic hook doesn't know it needs to add that property.&lt;/p&gt;

&lt;p&gt;Because the generic code doesn't know &lt;code&gt;T&lt;/code&gt;, you can only create a new version of &lt;code&gt;SelectOption&lt;/code&gt;. To fix this, you need a way to transform a &lt;code&gt;SelectOption&lt;/code&gt; object into &lt;code&gt;T&lt;/code&gt;, which only your non-generic code can provide.&lt;/p&gt;

&lt;h1&gt;
  
  
  One Solution
&lt;/h1&gt;

&lt;p&gt;Because inside &lt;code&gt;useComboboxFilter&lt;/code&gt; you only know about &lt;code&gt;SelectOption&lt;/code&gt;, and you only care about the &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt; and &lt;code&gt;disabled&lt;/code&gt; properties of it, you can create a required function parameter that translate a partial &lt;code&gt;SelectOption&lt;/code&gt; into any T:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useComboboxFilter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;SelectOption&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;createOption&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SelectOption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disabled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;filterValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;filteredOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;filteredOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filterValue&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filterValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filterValue&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;filteredOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;filteredOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createOption&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No results found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;filteredOptions&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAyhA2EDGwDyZgEsD2A7KAvFAN4BQUUuAhgLYQBcUAzsAE6a4DmA3OVAG5V4AVwbM2HTlAA+lYfHi8KAE0xMqAI0TLGG7NkRVcvAL69SAM2G4UOfMKYQAwthp69ADwBimeMAisADwAKlAQHv64ykywCMhoGHYAfAAUYKzYYEyMZBSZWHjZUMEA2gC6SlBIrBBU-ugFuIwpfHmJeIwACphIANaBcIgoDXYANFAARNR0EzKTgiIQs7ITqupaEMoTSXwAlIRJxZUWvv6sAGpCoows7FymuzlQJ34BmyOFjKVlUCYkfIhgM9Tm9lB9cDEiOlMkwAHQvM6XRatKAAfig0KysPydjhCICKRSOLw+wIh2JuFh0wgsI4SBEyggTDSGSx+IuVwgu12KMYmLhFKY5gomAsUBZMPhII5iygADI5VAAITs97tCGwxBcYAAC32uQowNeNTB6shUBKKIo-Nh1Vq9XVKQNhsN1MYEwActgoDUmPJgDELNhrFtRlbDQtrnIFGGXS61pptIw2KJY3GTLs0xQKnwTKQ+DVgMJWPhiEazmrGjEzKQ80A"&gt;The error is gone!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you then use your generic &lt;code&gt;useComboboxFilter&lt;/code&gt; with a subtype of &lt;code&gt;SelectOption&lt;/code&gt;, you must make sure the generic function can create a new object that satisfies that type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SelectOptionWithId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;SelectOption&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createOption&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SelectOption&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SelectOptionWithId&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFilter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useComboboxFilter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="nx"&gt;createOption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;filterValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bla&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that with the &lt;code&gt;createOption&lt;/code&gt; property, TypeScript infers &lt;code&gt;SelectOptionWithId&lt;/code&gt; for &lt;code&gt;myFilter&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;If you want to learn more about generics and other neat TypeScript features, be sure to check &lt;a class="mentioned-user" href="https://dev.to/mattpocockuk"&gt;@mattpocockuk&lt;/a&gt;'s &lt;a href="https://www.youtube.com/@mattpocockuk"&gt;YouTube videos&lt;/a&gt; and his &lt;a href="https://www.totaltypescript.com"&gt;Total TypeScript online course&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>generics</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Next Twitter</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Sun, 20 Nov 2022 23:50:59 +0000</pubDate>
      <link>https://forem.com/wes/the-next-twitter-20ij</link>
      <guid>https://forem.com/wes/the-next-twitter-20ij</guid>
      <description>&lt;p&gt;The world is not happy with Twitter. Lots of really bad decisions are being pushed by its arrogant new leadership, both in a hurry and in public. This it a unique opportunity to witness what bad management can do to teams and products on an entire company scale.&lt;/p&gt;

&lt;p&gt;Twitter has been, for better or worse, the world’s most public megaphone. It is where we as a collective go vent, broadcast, and have meaningful conversations with all sorts of people, all in the open.&lt;/p&gt;

&lt;p&gt;The web never lacked good platforms for communication. Long before Twitter a multitude of self hosted platforms helped communities flourish, keep in touch, and share knowledge. Forums, Reddit, heck even mailing lists are still used as public hosts of community discourse.&lt;/p&gt;

&lt;p&gt;What made Twitter unique, in my perspective, was twofold: there was a limit, and it was all public.&lt;/p&gt;

&lt;h2&gt;
  
  
  People Want Less
&lt;/h2&gt;

&lt;p&gt;If there is a societal trend today, it is short-form content presented in an infinite collection. People don’t need to invest their time reading a long article or watching a long video. They can easily glance at a piece of text, image or video and decide if it is worth consuming or skipping to the next one. &lt;sup&gt;[1]&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Twitter limited us to 140 characters. Instagram photos have always been 1080 pixels wide. Vine videos couldn’t be longer than 6.5 seconds, and TikTok once limited them to 1 minute.&lt;/p&gt;

&lt;p&gt;These limitations not only help us judge if the content deserves attention, it makes content very easy to produce.&lt;/p&gt;

&lt;p&gt;Platforms can then evolve and have the first post as an introduction for more. A very common practice on Twitter is appending “A thread 🧵👇” at the end of the first tweet in a series of replies, where authors entice people to dive deeper into a subject. &lt;sup&gt;[2]&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Threads were a natural evolution for the tweet limitation. On Instagram you can add multiple photos and videos in one post, and TikTok expanded video length up to 10 minutes long. Vine never did this, and it’s not around anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  People Want More
&lt;/h2&gt;

&lt;p&gt;The platform, while still promoting brief content, must also be massive and entice the user’s sense of meaningful participation and potential to grow.&lt;/p&gt;

&lt;p&gt;Twitter gives everyone an opportunity to write anything that can go viral. Posts are public, searchable and open to anyone’s reaction by default. Even if the majority of user content isn’t amplified, the potential that it can motivate people to write and engage more by retweeting and replying.&lt;/p&gt;

&lt;p&gt;This broadcast characteristic also attracts famous people to join the platform and bring their content and opinions, giving yet another reason for more people to engage. Large accounts can reach millions of people for free, and the common folk gets a direct communication channel. &lt;sup&gt;[3]&lt;/sup&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  But Wait, There’s More
&lt;/h2&gt;

&lt;p&gt;While I do believe that Twitter’s success can be associated with those two pillars, it is undenyable that many other factors played significant roles for the company to become as relevant as it is today.&lt;/p&gt;

&lt;p&gt;Twitter has been around for a very long time. It evolved very slowly, making careful product decisions&lt;sup&gt;[4]&lt;/sup&gt;. It attracted many big players: artists, companies, governments. Its web and mobile apps are very user friendly and responsive. Its infrastructure got extremely reliable handling the immense amount of generated content. It became so mainstream it borrowed the “@“ from email to itself.&lt;/p&gt;

&lt;p&gt;Most of these are chicken-and-egg scenarios. It might take years for your product to actually find its place in history. You can’t build it and expect success without important users, which might not be there at frist. You shouldn’t invest in infrastructure when you don’t need it.&lt;/p&gt;

&lt;p&gt;What one can do from the start, and hopefully for the lifetime of the company, is invest in good product decisions and user experiences. Needless to say, evidence shows Twitter completely abandoned the former.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Next Twitter
&lt;/h2&gt;

&lt;p&gt;To me, &lt;em&gt;The Next Twitter&lt;/em&gt; includes all of the above. It needs to provide a good amount of short-form content that can be expanded, important users that can raise engagement and bring more users to the platform, the best user experience possible on both the web and mobile devices, and good people making decisions guided by their users and their vision, not their guts.&lt;/p&gt;

&lt;p&gt;It might be the case that Twitter itself collapses, ressurects and becomes its next self. Only time will tell.&lt;/p&gt;




&lt;p&gt;Cover image generated by OpenAI.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;br&gt;
  [1] To be clear here: I don't believe this is a good practice, but an abuse of our limited attention. Many aspects of social media products are not tailored to our wellbeing, but to making sure we engage and buy products.&lt;br&gt;
&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;br&gt;
  [2] I also want point out that this might be the key difference between TikTok and YouTube. TikTok presents the TV channel experience: content already plays, and you are able to skip it and therefore tune the algorithm to offer you better videos. YouTube presents you a catalog of thumbnails and titles, which you then have to choose from.&lt;br&gt;
&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;br&gt;
  [3] This phenomenon also applies to brands, where customer service is often much better via Twitter than traditional ways, such as phone calls.&lt;br&gt;
&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;br&gt;
  [4] I feel this started to shift by the time they introduced Fleets. Many new smaller features started to appear and bloat the product surrounding the main timeline. Twitter has been completely musked today, and it is sad that product.&lt;br&gt;
&lt;/small&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>frontend</category>
      <category>ux</category>
    </item>
    <item>
      <title>tRPC: Move Fast and Break Nothing – useReactNYC</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Sat, 05 Nov 2022 17:03:38 +0000</pubDate>
      <link>https://forem.com/wes/trpc-move-fast-and-break-nothing-usereactnyc-3g08</link>
      <guid>https://forem.com/wes/trpc-move-fast-and-break-nothing-usereactnyc-3g08</guid>
      <description>&lt;p&gt;TypeScript is extremely popular nowadays but making sure the front end and back end speak the same schema is still a challenge. tRPC tries to help with that. In this talk, we're going to explore what tRPC is, how it compares with other solutions, and dive deep into a demo application showcasing its power to help keep types in sync on your entire application.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Recorded at a useReactNYC meetup on August 2022.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Simple React State Management</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Tue, 30 Jun 2020 17:39:55 +0000</pubDate>
      <link>https://forem.com/wes/simple-react-state-management-29g</link>
      <guid>https://forem.com/wes/simple-react-state-management-29g</guid>
      <description>&lt;p&gt;A good state system aims to be concise, easy to scale, and easy to debug. State is very unique per project, so a "one size fits all" framework is very unlikely to ever exist. &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt;, &lt;a href="https://mobx.js.org/README.html"&gt;MobX&lt;/a&gt;, &lt;a href="https://github.com/davidkpiano/xstate"&gt;XState&lt;/a&gt;, &lt;a href="https://www.apollographql.com/"&gt;Apollo&lt;/a&gt; and &lt;a href="https://relay.dev/"&gt;Relay&lt;/a&gt; are some great frameworks, but they all have compromises.&lt;/p&gt;

&lt;p&gt;Instead of utilizing a framework, we can use small libraries and apply strong concepts to guide our own code. The result is a robust and easy to debug codebase. Pure JavaScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  Action Flow and Immutability
&lt;/h2&gt;

&lt;p&gt;Two concepts that go hand in hand are &lt;strong&gt;action flow&lt;/strong&gt; and &lt;strong&gt;immutability&lt;/strong&gt;. Actions are the only place where the state is allowed to mutate - which helps to keep the state predictable. When mutating the state, we always replace object references with new ones instead of altering the original object, preventing side effects on methods that already are operating with the data elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://immerjs.github.io/immer"&gt;Immer&lt;/a&gt; is a small library that helps us write object manipulations that look like traditional code, but preserve the original state of the object. Here's an example of an action updating state using Immer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;produce&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;immer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;authenticateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loginUser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;produce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;stateDraft&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;stateDraft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;produce&lt;/code&gt; function takes a callback that receives a draft version of the object we want to mutate. Every operation inside of the callback is applied to the draft, preserving the original object state.&lt;/p&gt;

&lt;p&gt;We then update the reference to that object so that future references retrieve new data.&lt;/p&gt;

&lt;p&gt;We can build a library that wraps &lt;code&gt;produce&lt;/code&gt;, and helps us create new state objects and emits an event whenever there is a mutation. Other parts of our software can then be aware of that change and react accordingly.&lt;/p&gt;

&lt;p&gt;You can take a look at an example on the &lt;a href="https://github.com/WesSouza/immer-state/blob/master/src/StateManager.ts"&gt;StateManager.ts file&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Portability by Separation of Concerns
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Separation_of_concerns"&gt;separation of concerns&lt;/a&gt; principle helps the state stay concise on its operations. The goal is to allow developers to understand and alter it with little effort. We can group files that are relative to a specific concern, such as "authentication". Only those files are allowed to read from and write to that part of the state object.&lt;/p&gt;

&lt;p&gt;This centralizes the manipulation of that part of the state in one place, and any changes happen very close to each other. This reduces the cognitive load and keeps the code organized.&lt;/p&gt;

&lt;p&gt;Here's an example file structure for an authentication flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src/state
  |- /authentication/actions.js .... Log in, log out, forgot password,
  |                                  calls fetch user after login
  |- /authentication/selectors.js .. Is the user logged in?
  '- /user/actions.js .............. Fetch user, uses authentication
                                     selector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Hooks
&lt;/h2&gt;

&lt;p&gt;Hooks allows us to subscribe to the mutation events the state machine emits, using &lt;code&gt;useEffect&lt;/code&gt; for the event subscription and &lt;code&gt;useState&lt;/code&gt; to handle new renders.&lt;/p&gt;

&lt;p&gt;Referencing our StateManager.ts example from before, combined with &lt;a href="https://github.com/WesSouza/immer-state/blob/master/src/hooks/useSelector.ts"&gt;hooks/useSelector.ts&lt;/a&gt;, we can read and mutate our state with ease:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userLogout&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state/user/actions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state/user/selectors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state/user/store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;UserWelcome&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Not logged in.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userLogout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Logout&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can read more about it at my &lt;a href="https://github.com/WesSouza/immer-state"&gt;WesSouza/immer-state reference repository&lt;/a&gt;, which contains a simple proof of concept for this system.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Writing Good Pull Requests: A Primer</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Tue, 18 Feb 2020 23:00:00 +0000</pubDate>
      <link>https://forem.com/wes/opening-a-pr-a-primer-4kgc</link>
      <guid>https://forem.com/wes/opening-a-pr-a-primer-4kgc</guid>
      <description>&lt;p&gt;Pull Requests are the main path to add code to any open source project, as well as many closed source ones. They are opportunities to add new features, fix bugs, or bring improvements to the quality of the project.&lt;/p&gt;

&lt;p&gt;Before contributing to a project, it’s important to pay careful attention to its contribution rules. An ideal pull request has a clear title, a concise body, and well-defined commits. Below are some suggestions for opening a good pull request for any type of project.&lt;/p&gt;

&lt;h1&gt;
  
  
  Read the Contributing.md File
&lt;/h1&gt;

&lt;p&gt;Before anything, it is important to understand the contribution rules. What is the expected code style? Should you rebase commits from &lt;code&gt;master&lt;/code&gt; before pushing, or should you merge your branch[1]? How are the commit messages formatted? These and other rules are often laid out in a document named &lt;code&gt;CONTRIBUTING.md&lt;/code&gt;, on the root folder of the project, or in a &lt;code&gt;docs&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Read the document thoroughly and follow its guidelines.&lt;/p&gt;

&lt;h1&gt;
  
  
  Scope of Work
&lt;/h1&gt;

&lt;p&gt;Make sure your pull request refers to a single scope of work, one clear goal. This will make it easier to follow and reason about.&lt;/p&gt;

&lt;p&gt;If you are fixing three bugs, it’s better to open three isolated pull requests. PRs that depend on each other are a bit more complicated[2].&lt;/p&gt;

&lt;h1&gt;
  
  
  Commits
&lt;/h1&gt;

&lt;p&gt;Commits are how Git keeps track of code history. For a pull request, the most important aspect of a commit is to isolate part of your change so it has a smaller, more manageable cognitive load. This only applies to larger pull requests, and can vary a lot.&lt;/p&gt;

&lt;p&gt;You can see it as a recipe, where you break your work down into smaller pieces.&lt;/p&gt;

&lt;p&gt;Let’s consider an example: you need to fix a bug in a library function in the code, by introducing a new required parameter to it. That function is used in many places in the codebase, which will also need to change to work with the new function signature. You will also want to update the function’s tests, to make sure that parameter works as intended.&lt;/p&gt;

&lt;p&gt;We can split this up into two separate commits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update the library function including a new parameter;&lt;/li&gt;
&lt;li&gt;Update the code to adhere to the changed function signature.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This way, a person reading the pull request can separate what changed as part of what step on your recipe, and verify each step independently.&lt;/p&gt;

&lt;p&gt;If we mix the steps, it might be easy to miss the changes in the library among its use changes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Commit Messages
&lt;/h1&gt;

&lt;p&gt;Every commit message on your branch is important to understand what the commit changed. First of all, check the contribution guidelines for instructions on how to format and phrase the commit messages. Some projects use a rebase and fast-forward merge strategy, which means your commit messages will go as-is to the master branch.&lt;/p&gt;

&lt;p&gt;If the rules on the branch commit messages are open, make sure to keep them aligned with the guidelines. Most guidelines ask the message to be short, in the present tense, imperative mood, and not end with punctuation.&lt;/p&gt;

&lt;p&gt;In our example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fix binaryToString not working, introduce encoding parameter&lt;/li&gt;
&lt;li&gt;Update usage of binaryToString across the code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;See how we’ve used "update" instead of "updated" or "updating". This makes the messages more uniform, and usually shorter.&lt;/p&gt;

&lt;h1&gt;
  
  
  Pull Request Title
&lt;/h1&gt;

&lt;p&gt;Your pull request title is how other people will find your contribution. It represents the main intent of your proposed changes, so it should represent it well. Try to apply the same guides from the commit messages into the PR title.&lt;/p&gt;

&lt;p&gt;You can highlight side-effects of your change can in the body instead, to keep the title concise. In our example, we can use:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fix binaryToString not working&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This title highlights the intent of the pull request. The code contained in this pull request is all related to achieving this goal.&lt;/p&gt;

&lt;h1&gt;
  
  
  Pull Request Body
&lt;/h1&gt;

&lt;p&gt;The pull request body is your opportunity to have a conversation with the reviewers. Describe your changes and reasoning in detail, and match the commits with the proposed change explanation.&lt;/p&gt;

&lt;p&gt;It is where you can argue about decisions you took to achieve the proposed change in the title. It can also be a place to mention alternatives you didn’t take or would be willing to take if requested.&lt;/p&gt;

&lt;p&gt;My ideal pull request body has the following structure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A paragraph describing the main changes in detail&lt;/li&gt;
&lt;li&gt;A list of steps taken to achieve those changes&lt;/li&gt;
&lt;li&gt;Considerations about the approach taken and other available options&lt;/li&gt;
&lt;li&gt;Linked external resources&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first item is mandatory, the remaining ones are optional. They depend on the extent of your changes. Use your best judgement.&lt;/p&gt;

&lt;p&gt;Sometimes extra assets can make a huge difference. If there is a visual change, add a screen capture or video that highlights the changes. It is a great way to convey the effects of the changes.&lt;/p&gt;

&lt;p&gt;In our example, we could say:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This fixes all cases where `binaryToString` stopped fooing, by making explicit
the need of the necessary encoding. 

It:
- Fixes `binaryToString`, and adds a new encoding parameter
- Updates usage of `binaryToString` across the code to pass the correct encoding
  parameter

`binaryToString` used to infer the encoding, which used an unsupported
feature[1] that was unsafe and caused problems in some situations[2]. In order
to avoid the issue, we will stop inferring the encoding and instead require it
to be passed down.

1: https://example.org/encoding-detection
2: https://example.org/issues-with-encoding
Jira: ABC-123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here we are free to write the text on any form, as long as it’s concise and reasonable to the reviewer.&lt;/p&gt;

&lt;p&gt;You should remember that we are speaking to another person who is seeing that change for the first time. We must be careful to not make assumptions about the reader’s knowledge of the matter, by always providing enough context.&lt;/p&gt;




&lt;p&gt;Writing a perfect pull request is not possible, but we can make efforts to write ones that are as good as possible. Some key takeaways are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always follow the contributing guidelines;&lt;/li&gt;
&lt;li&gt;Limit the affected scope so your intent is clear;&lt;/li&gt;
&lt;li&gt;Be concise on your text and commit intent;&lt;/li&gt;
&lt;li&gt;Provide context about your decisions;&lt;/li&gt;
&lt;li&gt;Detail alternatives and visual examples of the changes, if possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember: reviewers are people. They are trying to understand your point. They might not have as much knowledge as you about your intents.&lt;/p&gt;

&lt;p&gt;I hope this helps you make sure your pull request gets approved and merged in no time!&lt;/p&gt;




&lt;p&gt;&lt;small&gt;&lt;ol&gt;
  &lt;li&gt;
&lt;a&gt;&lt;/a&gt;You can read more about &lt;a href="https://hackernoon.com/git-merge-vs-rebase-whats-the-diff-76413c117333"&gt;the difference between merge and rebase in this article on Hacker Noon&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
&lt;a&gt;&lt;/a&gt;There isn’t a standard way on git to point out that one branch depends on another. You can open multiple PRs where they all have the commits they are dependent on, which might be confusing for reviewers since those changes are not described by that PR; or open PRs that are merging your code into a parent PR branch instead of &lt;code&gt;master&lt;/code&gt;, but remember those branches are not protected, so restrictions might not apply. This is, for sure, a topic for an entire new article.&lt;/li&gt;
&lt;/ol&gt;&lt;/small&gt;&lt;/p&gt;




&lt;p&gt;&lt;small&gt;Thanks to &lt;a href="https://twitter.com/dfosco"&gt;Daniel Fosco&lt;/a&gt;, &lt;a href="https://twitter.com/jgashe"&gt;Jay Ashe&lt;/a&gt; and &lt;a href="https://twitter.com/IISResetMe"&gt;Mathias Jessen&lt;/a&gt; for the help revising this content.&lt;br&gt;Photo by &lt;a href="https://unsplash.com/photos/mG28olYFgHI"&gt;Ross Findon&lt;/a&gt; on Unsplash.&lt;br&gt;
&lt;/small&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>productivity</category>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>Bringing Components to Legacy Code</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Mon, 01 Jul 2019 23:49:54 +0000</pubDate>
      <link>https://forem.com/wes/bringing-components-to-legacy-code-2m00</link>
      <guid>https://forem.com/wes/bringing-components-to-legacy-code-2m00</guid>
      <description>&lt;p&gt;Not all systems allow the code to take over the entire rendering of your app. Sometimes you want to modernize and scale your code using libraries such as React on systems that already have a lot of legacy interactive code, or a CMS that must controls what is rendered in the page.&lt;/p&gt;

&lt;p&gt;This talk shows techniques to adopt an existing environment so modern libraries can coexist with existing environments, where the DOM dictates the components it needs.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Recorded at a ReactNYC meetup on September 2017.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>components</category>
      <category>talks</category>
      <category>meetup</category>
    </item>
    <item>
      <title>Web developers: with SwiftUI, would you consider learning Swift?</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Mon, 03 Jun 2019 19:41:49 +0000</pubDate>
      <link>https://forem.com/wes/web-developers-with-swiftui-would-you-consider-moving-to-native-development-3ce1</link>
      <guid>https://forem.com/wes/web-developers-with-swiftui-would-you-consider-moving-to-native-development-3ce1</guid>
      <description>&lt;p&gt;Apple just announced &lt;a href="https://developer.apple.com/xcode/swiftui/"&gt;SwiftUI&lt;/a&gt;, a "simple way to build user interfaces across all Apple platforms with the power of Swift".&lt;/p&gt;

&lt;p&gt;It's a declarative way to create native views. It's very similar to component systems such as React and Flutter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--azWxr5Of--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer.apple.com/xcode/swiftui/images/example-syntax-light-large_2x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--azWxr5Of--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer.apple.com/xcode/swiftui/images/example-syntax-light-large_2x.jpg" alt="Swift UI code example" width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are you curious about it? Would you consider jumping into native development?&lt;/p&gt;

&lt;p&gt;What if they release a version for the web?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Edit: Changed title to reflect "learning Swift" instead of moving to Apple's iOS platform. Cross-platform is also diversity.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>swift</category>
      <category>wwdc</category>
      <category>swiftui</category>
    </item>
    <item>
      <title>Why I Became, and still am, a Web Developer</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Thu, 30 May 2019 20:05:32 +0000</pubDate>
      <link>https://forem.com/wes/why-i-became-and-still-am-a-web-developer-1k3</link>
      <guid>https://forem.com/wes/why-i-became-and-still-am-a-web-developer-1k3</guid>
      <description>&lt;p&gt;Once upon a time, my young self opened Notepad, entered many characters, saved as an &lt;code&gt;.html&lt;/code&gt; file, opened it on Internet Explorer, and saw magic happen. It was life-changing.&lt;/p&gt;

&lt;p&gt;Eighteen years later, and I'm making a living out of the same principles. HTML, CSS and JavaScript. Working for a product agency with amazing clients. Building native mobile apps, front-end websites, back-end systems. Living in the city I always dreamed of.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hello World
&lt;/h1&gt;

&lt;p&gt;When I was 15 years old, I got internet access at home. &lt;a href="https://en.wikipedia.org/wiki/Dial-up_Internet_access"&gt;Dial-up&lt;/a&gt;, something around 40 kilobits per second. That's &lt;em&gt;five KiB per second&lt;/em&gt;. That was what was available in my town at that time.&lt;/p&gt;

&lt;p&gt;There was no Firefox. Google was barely a search engine (I'm from Brazil, we used &lt;a href="https://pt.wikipedia.org/wiki/Yahoo!_Cad%C3%AA%3F"&gt;another search "engine"&lt;/a&gt; at that time). There was only Internet Explorer and Netscape Navigator. And websites were always &lt;em&gt;"best viewed on Internet Explorer"&lt;/em&gt;, so it was what I used.&lt;/p&gt;

&lt;p&gt;I then took a computer introduction course, one that taught "professional computer skills" like Windows 98 and Office 97. And the last book was "web". We barely got to start it and the course was over, but it intrigued me.&lt;/p&gt;

&lt;p&gt;It was easy to create documents, style them, and – most importantly – add behavior to them.&lt;/p&gt;

&lt;h1&gt;
  
  
  Fast Learning Curve
&lt;/h1&gt;

&lt;p&gt;To get started with web development, one needs only a text editor and a web browser. All popular operating systems come preinstalled with both. And you don't need to compile the code, just save and run.&lt;/p&gt;

&lt;p&gt;The syntaxes involved are also not very cryptic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: purple"&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"alert('Hello!')"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Say Hello!
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's &lt;em&gt;much&lt;/em&gt; more complexity to all of them, but it's undeniable that with a few concepts, and a few lines of code, anyone can create something already very robust, if compared to other platforms.&lt;/p&gt;

&lt;p&gt;On a native platform, in general, you often need to download an IDE and a compiler, then write code for the behavior, use a visual editor for the visual interface, and write bindings between both. Then you need to compile and run.&lt;/p&gt;

&lt;h1&gt;
  
  
  "I Made Something!"
&lt;/h1&gt;

&lt;p&gt;The friendlier the entry point of a technology is, the more people feel comfortable experimenting with it. And if you can use that technology to build something that works, the experience is extremely satisfying.&lt;/p&gt;

&lt;p&gt;Given the fast learn curve of web development, and the fact that the tools are simple and readily available, it's not a surprise that JavaScript, HTML and CSS are &lt;a href="https://insights.stackoverflow.com/survey/2019#technology"&gt;the most popular languages in the development community&lt;/a&gt; nowadays.&lt;/p&gt;

&lt;p&gt;And regardless if it's a &lt;a href="https://wes.dev/archive/2014"&gt;quirky terminal emulator&lt;/a&gt;, or a very useful &lt;a href="https://subwayti.me"&gt;nearby subway time table&lt;/a&gt;, it's always fun to see your creations come to life.&lt;/p&gt;

&lt;h1&gt;
  
  
  "I'm Learning!"
&lt;/h1&gt;

&lt;p&gt;The web is not just a set of rules to create, style, add behavior to, and link documents (although it started as one). It provides numerous tools so creators can produce a myriad of complex user experiences, from a website with comments, to an entire social network.&lt;/p&gt;

&lt;p&gt;All of this involves an extensive list of APIs that allow web browsers to transform text files into rich experiences such as playing videos, making music, capturing the user's webcam, and much more.&lt;/p&gt;

&lt;p&gt;All of this is not only standardized, but also continuously changing through developments by its working group bodies: &lt;a href="https://www.w3.org"&gt;W3C&lt;/a&gt;, &lt;a href="https://whatwg.org"&gt;WHATWG&lt;/a&gt; and &lt;a href="https://www.ecma-international.org/memento/tc39-rf-tg.htm"&gt;Ecma TC39&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because of that, you can choose to become a specialist on &lt;em&gt;many&lt;/em&gt; very different realms. For example, you can dedicate time to learn about &lt;a href="https://www.w3.org/WAI/standards-guidelines/wcag/"&gt;accessibility&lt;/a&gt;, which is an increasingly important pillar of software development today.&lt;/p&gt;

&lt;h1&gt;
  
  
  "I'm Meeting Great People!"
&lt;/h1&gt;

&lt;p&gt;One of the most fascinating things to me is how friendly, inclusive and supportive the web development community can be. There are a huge number of local meetups all over the world, great conferences that span across a number of topics.&lt;/p&gt;

&lt;p&gt;One recent example was &lt;a href="https://reactjsgirls.com"&gt;ReactJS Girls&lt;/a&gt;, a conference focused on React development that had only women speakers. Diversity has been a big problem for the software development industry, where &lt;a href="https://insights.stackoverflow.com/survey/2019#developer-profile-_-developer-role-and-gender"&gt;92% of surveyed developers on StackOverflow&lt;/a&gt; identify as men in 2019.&lt;/p&gt;

&lt;p&gt;The conference idea was to showcase women talent, and it delivered. It was extremely fun, full of great, entertaining and informative talks, and  met many great developers there, from all over the world.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://www.youtube.com/playlist?list=PLfrHCOIcmSupF372EGlyi3l4y2R7F8A3q"&gt;watch all the talks at YLD's YouTube channel&lt;/a&gt;, and if you're into React development (or any component-based system), &lt;a href="https://www.youtube.com/watch?v=vot0nJJ2Qdo&amp;amp;list=PLfrHCOIcmSupF372EGlyi3l4y2R7F8A3q&amp;amp;index=4"&gt;Jenn Creighton's The How and Why of Flexible React Components&lt;/a&gt; is a must-watch.&lt;/p&gt;

&lt;p&gt;But, as in any group, there are Hundreds of Niche places where you can find angry, aggressive developers that prefer to insult rather than help. But let's not focus on them.&lt;/p&gt;

&lt;h1&gt;
  
  
  Moving Forward
&lt;/h1&gt;

&lt;p&gt;Find your passion. Find the passion inside your passion. And keep improving.&lt;/p&gt;

&lt;p&gt;My specialties are software architecture and state management. I really enjoy an organized codebase that allows people to easily move around areas they're not familiar with and be able to easily add to them. I also really like to understand a product's business rules inside and out and apply them to the state management of the app in a robust way.&lt;/p&gt;

&lt;p&gt;But there are multiple different areas in the web that span knowledge across all of HTML, CSS and JavaScript. You can become an expert in animation, DOM manipulation, a certain framework or library, accessibility, unit or automation testing, continuous integration and delivery, and much, much more.&lt;/p&gt;

&lt;p&gt;That's why I really recommend &lt;a href="https://learntocodewith.me/posts/coding-mentor/"&gt;finding yourself a mentor&lt;/a&gt;. Other places you can look for mentors are the &lt;a href="https://dev.to/listings/mentors"&gt;DEV Community&lt;/a&gt; and &lt;a href="https://mentors.codingcoach.io"&gt;Coding Coach&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I love the web because it's welcoming, inclusive, and fun. And there's always something new to learn on it.&lt;/p&gt;




&lt;p&gt;If you want to reach me, my DMs on &lt;a href="https://twitter.com/messages/compose?recipient_id=7354582"&gt;Twitter&lt;/a&gt; and &lt;a href="https://dev.to/wes"&gt;DEV&lt;/a&gt; are always open.&lt;/p&gt;

</description>
      <category>career</category>
      <category>maker</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>how2: Using GPG on macOS without GPGTools</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Tue, 15 Jan 2019 16:16:21 +0000</pubDate>
      <link>https://forem.com/wes/how2-using-gpg-on-macos-without-gpgtools-428f</link>
      <guid>https://forem.com/wes/how2-using-gpg-on-macos-without-gpgtools-428f</guid>
      <description>&lt;p&gt;I don’t like GPGTools. I want GPG on macOS. Every tutorial has some obsolete part. Here’s what I did.&lt;/p&gt;




&lt;p&gt;GPGTools installs a lot of things that I don’t want to use. I just want to sign my commits on GitHub and save my GPG key in macOS keychain.&lt;/p&gt;

&lt;p&gt;There are two main dependencies to achieve that, gnupg contains the GPG tools to generate keys and sign things, as well as an agent to do agent things; and pinentry-mac which is the part of GPGTools that prompts for your key password and stores it on the OS keychain.&lt;/p&gt;

&lt;h3&gt;
  
  
  GPG Setup
&lt;/h3&gt;

&lt;p&gt;Before anything, install &lt;a href="https://brew.sh"&gt;Homebrew&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After that, install the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;gnupg pinentry-mac
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the output of the install command, which will tell you the location of the &lt;code&gt;pinentry-mac&lt;/code&gt; program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;==&amp;gt; Caveats
==&amp;gt; pinentry-mac
You can now set this as your pinentry program like

~/.gnupg/gpg-agent.conf
    pinentry-program /some/path/here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to configure gpg-agent to use pinentry-mac by creating a file ~/.gnupg/gpg-agent.conf, pointing to the correct pinentry-mac program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Connects gpg-agent to the OSX keychain via the brew-installed&lt;/span&gt;
&lt;span class="c"&gt;# pinentry program from GPGtools. This is the OSX 'magic sauce',&lt;/span&gt;
&lt;span class="c"&gt;# allowing the gpg key's passphrase to be stored in the login&lt;/span&gt;
&lt;span class="c"&gt;# keychain, enabling automatic key signing.&lt;/span&gt;
pinentry-program /usr/local/bin/pinentry-mac
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Apple Silicon Macs, Homebrew uses a different path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pinentry-program /opt/homebrew/bin/pinentry-mac
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let’s generate your first key. I recommend using RSA and RSA, a key size of 4096, and not having the key expire. Remember to &lt;a href="https://xkcd.com/936/"&gt;choose a strong password&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--full-generate-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, sign a test message so pinentry-mac can store your password in the keychain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt; | gpg &lt;span class="nt"&gt;--clearsign&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should open a dialog prompting your password. Remember to check “Save in Keychain”.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting to GitHub
&lt;/h3&gt;

&lt;p&gt;First, copy your private key to add to GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--export&lt;/span&gt; &lt;span class="nt"&gt;--armor&lt;/span&gt; your@email.here | pbcopy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And paste it in &lt;a href="https://github.com/settings/gpg/new"&gt;GitHub’s Settings &amp;gt; SSH and GPG keys &amp;gt; New GPG key&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Second, configure your git environment to use signed commits. I’ve done it globally. First obtain your public GPG keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gpg &lt;span class="nt"&gt;--list-secret-keys&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;...&lt;span class="o"&gt;)&lt;/span&gt;
sec   rsa2048 2019-01-15 &lt;span class="o"&gt;[&lt;/span&gt;SC]
      YOUR_GPG_KEY_APPEARS_HERE
uid           &lt;span class="o"&gt;[&lt;/span&gt;ultimate] Your Name &amp;lt;your@email.here&amp;gt;
ssb   rsa2048 2019-01-15 &lt;span class="o"&gt;[&lt;/span&gt;E]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; commit.gpgsign &lt;span class="nb"&gt;true
&lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.signingkey YOUR_GPG_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, commit something with the-S argument to make sure it’s signed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Testing GPG signature"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Troubleshooting
&lt;/h3&gt;

&lt;p&gt;Things you can try if things are not working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Kill gpg-agent&lt;/span&gt;
killall gpg-agent

&lt;span class="c"&gt;# Run gpg-agent in daemon mode&lt;/span&gt;
gpg-agent &lt;span class="nt"&gt;--daemon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/photos/lmFJOx7hPc4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Micah Williams&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/padlock?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gpgtools</category>
      <category>gpg</category>
      <category>git</category>
      <category>howto</category>
    </item>
    <item>
      <title>Keeping Control of the Front-end</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Mon, 15 Feb 2016 08:00:00 +0000</pubDate>
      <link>https://forem.com/wes/keeping-control-of-the-front-end-ag7</link>
      <guid>https://forem.com/wes/keeping-control-of-the-front-end-ag7</guid>
      <description>&lt;p&gt;At Booking.com, hundreds of developers and designers contribute daily to our codebase, which leads to potential complications with code discoverability, maintenance, and reuse. In this post, we’re going to focus on the client-side aspect of these challenges, and introduce some of the techniques we use to tackle them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prefixing and Namespacing
&lt;/h3&gt;

&lt;p&gt;Because of the size of our codebase and the number of people introducing changes to it daily, it can be difficult to maintain unique identifiers for all of our pages’ components.&lt;/p&gt;

&lt;p&gt;Both &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript"&gt;JavaScript&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS"&gt;Cascading Style Sheets&lt;/a&gt; make use of identifiers to work properly, by means of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var"&gt;variable names&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en/docs/Web/Guide/CSS/Getting_started/Selectors"&gt;selectors&lt;/a&gt; respectively, both on a global execution scope.&lt;/p&gt;

&lt;p&gt;Let’s start with JavaScript. We make use of &lt;a href="https://www.2ality.com/2011/04/modules-and-namespaces-in-javascript.html"&gt;namespaces&lt;/a&gt;, which are object properties of a global variable. (We also implement modules, which will be discussed later in the article.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The only global variable&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="c1"&gt;// The search namespace&lt;/span&gt;
&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="c1"&gt;// Check-in date of the search&lt;/span&gt;
&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checkIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Travel purpose of the search&lt;/span&gt;
&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;travelPurpose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;business&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, B.search is the namespace we're using to visually identify our code. Notice how travelPurpose has its scope within search, clarifying its context and meaning.&lt;/p&gt;

&lt;p&gt;CSS is different. Because CSS doesn’t provide a scalable way of grouping selectors, we make use of prefixes instead. We also make sure all selectors are as specific as possible — to prevent collisions. For example, in our files we already have about 4,000 class selectors containing the term item in their declaration.&lt;/p&gt;

&lt;p&gt;Imagine the following simple case: a list of facilities on the hotel page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"facilities"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Wi-Fi&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Breakfast&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That might interfere with another team's work that is adding a universal menu on the website's header.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On both cases, .item will have specific CSS rules that could be overridden, thus generating unexpected results. Sometimes these interactions happen on a specific page that was beyond the scope of the developer's tests.&lt;/p&gt;

&lt;p&gt;To prevent these conflicts we often use prefixing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hp-facilities"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hp-facilites__facility"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Wi-Fi&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hp-facilites__facility"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Breakfast&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we invest so much into experimentation through A/B testing, a considerable amount of code becomes irrelevant when its related experiment expires.&lt;/p&gt;

&lt;p&gt;Because we want to avoid &lt;a href="https://en.wikipedia.org/wiki/Software_rot"&gt;code rot&lt;/a&gt; in our codebase, we want to keep only the parts that we actually need, and those irrelevant pieces of code must be removed periodically. Being able to quickly search the code for a specific token, such as a CSS class name, is a key requirement for this clean up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Control of Execution
&lt;/h3&gt;

&lt;p&gt;It is very important that our JavaScript code runs in a controlled fashion. Our code needs to be &lt;em&gt;precise&lt;/em&gt; by only executing when it is necessary for a certain feature, page, or event. It also needs to be &lt;em&gt;robust&lt;/em&gt;, preventing interference between unrelated features.&lt;/p&gt;

&lt;p&gt;Suppose we have three script files concatenated, and the resulting file is added to every page on our website.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// from tooltip.js&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.tooltip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addTooltip&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// from available_rooms.js&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#prices .price&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;scrollTop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// from sticky_user_bar.js&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;scroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.user_bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;top&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollTop&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any part that fails will prevent the next part from executing. For instance, if there is no element on the page that matches #prices .price there will be an error stopping everything else from executing, breaking the user bar behavior.&lt;/p&gt;

&lt;p&gt;Also, there might be code that shouldn't be running, which is undesirable. In the example, if no element matches .user_bar on the page, the scrolling event is still monitored, wasting CPU cycles.&lt;/p&gt;

&lt;p&gt;To mitigate this, we chose to develop an internal flow controller that provides an execution control API based on &lt;a href="https://github.com/amdjs/amdjs-api/blob/master/AMD.md"&gt;AMD&lt;/a&gt;, built on top of &lt;a href="https://github.com/jrburke/almond"&gt;Almond&lt;/a&gt;. It uses setTimeout to provide a separate context, which then isolates failures and prevents the blockage of the main thread.&lt;/p&gt;

&lt;p&gt;As a bonus, because the code is wrapped, we can easily &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Console/profile"&gt;label those calls for profiling&lt;/a&gt; and find features that might be wasting resources.&lt;/p&gt;

&lt;p&gt;This also helps isolate the experimented part of our A/B testing, making it easy to find and clean up failed tentatives, as mentioned in the previous section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restricting Your Execution
&lt;/h3&gt;

&lt;p&gt;While CSS code avoids clashes by using namespaces, JavaScript should not leak behavior to DOM elements or to other unrelated components in the same page.&lt;/p&gt;

&lt;p&gt;Part of that problem can be prevented by following well-established coding principles, such as avoiding global variables (enforced by using the &lt;a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Strict_mode"&gt;strict mode&lt;/a&gt;), modularizing the specific parts of your code, and so forth.&lt;/p&gt;

&lt;p&gt;We also encourage our teams to develop context specific software to avoid side-effects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.destination&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, every form element will have a submit event handler attached to it. Also, it searches the entire document DOM tree for the .destination selector, which might stop working as soon as someone inadvertently adds an element that matches the same selector.&lt;/p&gt;

&lt;p&gt;An even better approach stresses specifying targets in more detail, aiming to only affect what needs to be affected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.js-searchbox-form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.js-destination-input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this scenario, the class names are clear and specific, and the code will only look for elements inside of its own form, preventing possible leaking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modularization
&lt;/h3&gt;

&lt;p&gt;Having multiple teams working independently at the same time allows different development styles across the codebase. One developer might like wrapping her own code on &lt;a href="https://benalman.com/news/2010/11/immediately-invoked-function-expression/"&gt;IIFE&lt;/a&gt;, and another might prefer the &lt;a href="https://addyosmani.com/resources/essentialjsdesignpatterns/book/#prototypepatternjavascript"&gt;prototype pattern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While this is not a problem if the code is achieving a simple task, more complex solutions might become too big to understand, to manipulate, or to maintain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;showTheGallery&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotelId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="cm"&gt;/* Here goes 31415 lines of code involving all event handlers, the overlay behind the gallery, capturing the keyboard events to navigate and close the gallery, logic to preload the images, logic to center the main image relative to another element, scrolling of the thumbnails, obtaining the images from a specific variable in the code, showing the gallery, etc. */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;showTheGallery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, parts of the code can become too complicated and isolated, making it difficult to understand and debug. It also prevents any kind of reusability.&lt;/p&gt;

&lt;p&gt;However, we can break the code into smaller blocks that serve a specific purpose, as described in the &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY&lt;/a&gt; principle as "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;photo-gallery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;component-maker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dom-position&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dom-scroll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;env-variables&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image-preload&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keyboard-events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;overlay&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Tying them all together nicely, exporting an extensible component&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, every dependency is self-contained, specific enough, and totally reusable by others, and the resulting object allows quick extension and behavior changing, so the original code can be adapted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;p&gt;Following the principles of restricting the behavior of your code to exactly where you want it to run, and the fact that we want to build a modularized and reusable codebase, we developed a simple solution called &lt;strong&gt;B.components&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The principle behind it is to add behavior to one or more DOM nodes. It only executes the code when the element exists, and allows one component to extend the features of another, facilitating reusability.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;data-component=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Alert&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we add behavior to a specific button in the code. The JavaScript doesn't need to know which exact element to target in the document, since it's the button that requests a behavior, not the other way around.&lt;/p&gt;

&lt;p&gt;The code receives a pointer to the DOM node, and can perform the necessary action, such as listening to click events on this reference and triggering an alert window.&lt;/p&gt;

&lt;p&gt;The benefit of this approach is its DOM-based flexibility. We might change every aspect of the HTML, and even add more elements, while preserving the same behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;data-component=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Alert Anchor&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;data-component=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Alert Span&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use AMD as the foundation to store the component definitions as modules, the same setTimeout technique mentioned before for containing the execution, and to create a new instance for each component definition found in the DOM or any specified node.&lt;/p&gt;

&lt;p&gt;This solution frees us from knowing exactly what to do when rendering dynamic HTML on the page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;templateCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Complex HTML structure&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templateCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// We added tooltips, so initialize them&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.tooltip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;tooltip&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// We also added a lightbox, but that uses another API&lt;/span&gt;
&lt;span class="nx"&gt;LightboxFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addLightbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#lightbox-a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lightbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;options&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Did we forget something? Did some API change?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is all replaced by a one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templateCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;appendTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;loadComponents&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method $.fn.loadComponents will take care of finding the necessary components, and each component will be given the opportunity to initialize itself, all under the same predictable API.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Big Picture
&lt;/h3&gt;

&lt;p&gt;Because we are a big company with hundreds of developers, we exercise care so that our contributions leave our code better than we found it, keeping it more maintainable in the long run.&lt;/p&gt;

&lt;p&gt;Organizing and namespacing our CSS and JavaScript blocks helps to make our code easily findable and robust. Controlling our executed code scope and only running it when really necessary makes it predictable and fast. Thinking about modules and UI components ensures we are able to quickly understand and reuse our solutions. All of this is done while keeping a good sense of community and respect for each other.&lt;/p&gt;

&lt;p&gt;These are just some of the techniques we adopted and created at Booking.com to help us deal with the challenges of growth.&lt;/p&gt;

&lt;p&gt;The important lesson is to always look a the big picture, never assume you are in a perfectly controlled environment.&lt;/p&gt;

&lt;p&gt;Code must be resilient.&lt;/p&gt;

</description>
      <category>components</category>
      <category>development</category>
      <category>jquery</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Small Things to Make Others Happy</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Sun, 01 Mar 2015 08:00:00 +0000</pubDate>
      <link>https://forem.com/wes/cool-things-make-people-happy-3pci</link>
      <guid>https://forem.com/wes/cool-things-make-people-happy-3pci</guid>
      <description>&lt;p&gt;Working for a couple of big companies as &lt;a href="http://www.mtv.com.br/"&gt;MTV&lt;/a&gt;, &lt;a href="http://www.univision.com/"&gt;Univision&lt;/a&gt; and &lt;a href="http://www.booking.com/"&gt;Booking.com&lt;/a&gt; gave me a glimpse of what it is to deploy my code to a huge amount of users, and also share it with a lot of other developers and designers.&lt;/p&gt;

&lt;p&gt;It made me learn a lot, and I’ve compiled this list of small positive actions that can potentially improve everyone’s daily routine.&lt;/p&gt;

&lt;p&gt;Most of this makes more sense if applied in big organizations, due to the nature of having multiple people responsible for multiple aspects of a product or even multiple products.&lt;/p&gt;

&lt;h2&gt;
  
  
  Daily Life
&lt;/h2&gt;

&lt;p&gt;The first part of the presentation revolves around common abstract ideas that I feel should be reinforced.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep Calm and Don’t Rush Your Commits
&lt;/h3&gt;

&lt;p&gt;Rushed coding is a potential for undetected problems. Avoid rushing your commit just so that it makes the next deployment, from my experience nobody dies if your code is one day late.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn
&lt;/h3&gt;

&lt;p&gt;Part of what makes us hackers is that we love to learn. And dealing with MSIE 8 is no excuse to stop in ECMAScript 3 and stop improving your knowledge.&lt;/p&gt;

&lt;p&gt;It is also a good opportunity to expand your horizons. If you’re a designer with weak JavaScript coding abilities, seek training. Same thing for front end developers that do not code properly in their company’s back end language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teach
&lt;/h3&gt;

&lt;p&gt;Knowledge should always be shared. Teaching makes you understand that subject better, because you only truly understand something if you can explain it to someone else.&lt;/p&gt;

&lt;p&gt;Teaching improves your communication skills, spreads knowledge to your company’s community, and gives you karma points among your colleagues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Embrace User Experience
&lt;/h3&gt;

&lt;p&gt;Whenever creating a feature, do put the user in the center of your design. Do not solve using the quickest available solution, be it because of it being technically difficult, or just easier to couple with the current design.&lt;/p&gt;

&lt;p&gt;From a design perspective this applies to every small enhancement that in the end culminates in a messed up visual experience. Because every new addition has to conform to the current design, and the first design was never conceptualized with all these new additions, the end experience is most of the times a mess. There are times to rethink the whole user experience.&lt;/p&gt;

&lt;p&gt;From a developer perspective this applies to lazy solutions that work but do not make immediate sense to the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your Code Is Not Yours
&lt;/h3&gt;

&lt;p&gt;And by that I don’t mean your code is your company’s property. It is, don’t get me wrong, but my point is that your code is shared with a number of other developers and sometimes designers.&lt;/p&gt;

&lt;p&gt;You have to be aware that you’ll hardly work in the same team forever, and that your software will certainly be changed and maintained by a number of different people throughout time.&lt;/p&gt;

&lt;p&gt;And how many times you got back to your own code from the previous day and thought “what the fuck was I doing here?”&lt;/p&gt;

&lt;p&gt;Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. Code for readability. –John F. Woods&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep it Simple
&lt;/h3&gt;

&lt;p&gt;This is a mantra for every applicable aspect of your life. If you’re creating code, designing a new feature, talking about a new technology, creating a new database table, or even an entire new product, you should always aim for simplicity.&lt;/p&gt;

&lt;p&gt;This goes together with code maintainability, because if you think into small, simple pieces instead of a huge chunk of interconnected functions you have more chances of having an understandable code file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Value Others’ Opinions
&lt;/h3&gt;

&lt;p&gt;Do not assume you have the best solution at all cases. This is part of life, but is greatly enhanced in technology, since we have to come up with solutions frequently, we tend to ignore others’ opinions and shove our solution down everybody’s throats.&lt;/p&gt;

&lt;p&gt;Ponder what you are changing and involve people in your decisions before deploying your new code. Be it as a simple code review by a trusted colleague, or by an e-mail thread to the company’s developers list.&lt;/p&gt;

&lt;h3&gt;
  
  
  Engage in the Community
&lt;/h3&gt;

&lt;p&gt;In big organizations, there is a huge chance that a lot of other people do the same kind of job that you do, and then it is your responsibility to gather together and talk.&lt;/p&gt;

&lt;p&gt;This is extremely useful for sharing experiences, discussing new technologies, and determine technical steps — like moving to SCSS, using Browserify, implementing ES5 shims.&lt;/p&gt;

&lt;p&gt;This also brings people together and engages people.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Talking about more concrete things, these are my recommendations about HMTL, CSS and JavaScript coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tabs vs. Spaces
&lt;/h3&gt;

&lt;p&gt;I don’t care if you use tabs or spaces, but you must respect the current file settings. Set up your file editor to detect and use whatever the opened file has, and make sure you are not mixing up.&lt;/p&gt;

&lt;p&gt;Specially when copying code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;a&amp;gt;&lt;/span&gt;
Drunk code.
 &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explain Your Code
&lt;/h3&gt;

&lt;p&gt;We are not in 1980 anymore, your methods, variable and class names can be bigger and more descriptive. Other people must understand what your code does without reading extensive documentation or attending a workshop you give.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;wat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// what is a?&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// what is c?&lt;/span&gt;
  &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// where the fuck did d come from?&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// oh dear.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Don’t Style #ids or elements
&lt;/h3&gt;

&lt;p&gt;Styling ids are bad because they are technically unique for one element, and this restricts reuse of styling.&lt;/p&gt;

&lt;p&gt;And big companies rarely have omnipresent design guidelines, so one &amp;lt;button&amp;gt; is potentially very different across components, so never style the element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* surprise interference! */&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lower Your Specificity
&lt;/h3&gt;

&lt;p&gt;In order to prevent a proliferation of !important shit, keep your CSS selectors specificity as low as possible.&lt;/p&gt;

&lt;p&gt;This also reduces the chances of CSS interference between teams, since generic class names can be used at any time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* what the specificity hell */&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nf"&gt;#header&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="nc"&gt;.menu&lt;/span&gt; &lt;span class="nc"&gt;.item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* hmm, peace */&lt;/span&gt;
&lt;span class="nc"&gt;.header-menu__item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prefix
&lt;/h3&gt;

&lt;p&gt;Whenever you create a new component, try to prefix every class name with it. The syntax becomes very verbose, which is actually good for consistency, self-explanatory code and small specificity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* component */&lt;/span&gt;
&lt;span class="nc"&gt;.searchbox&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* component + something */&lt;/span&gt;
&lt;span class="nc"&gt;.searchbox-input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* parent component + state */&lt;/span&gt;
&lt;span class="nc"&gt;.searchbox.-active&lt;/span&gt; &lt;span class="nc"&gt;.searchbox-input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Template is Not Backend
&lt;/h3&gt;

&lt;p&gt;Business logic and complex coding should be in the back end. If the template engine you use provide ways to program like ifs, loops, variable setting, never use them to create an algorithm in the template code.&lt;/p&gt;

&lt;p&gt;It is always weird, hard to understand, and very fragile.&lt;/p&gt;

&lt;h3&gt;
  
  
  git diff is Our Friend
&lt;/h3&gt;

&lt;p&gt;If you use git and have a master branch that is always deployable, you need to be very careful before pushing your code changes.&lt;/p&gt;

&lt;p&gt;Doing a git diff before committing, or git show before pushing, gives you a last chance to see if you forgot to remove test code, or if there was a bad merge you need to fix, before breaking things for everyone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope you found something useful from these points. I know I would be much happier if everyone I work with followed them.&lt;/p&gt;

</description>
      <category>code</category>
      <category>webdev</category>
      <category>css</category>
      <category>scalability</category>
    </item>
    <item>
      <title>From Brazil to Amsterdam</title>
      <dc:creator>Wes Souza</dc:creator>
      <pubDate>Wed, 28 Jan 2015 08:00:00 +0000</pubDate>
      <link>https://forem.com/wes/from-brazil-to-amsterdam-5jc</link>
      <guid>https://forem.com/wes/from-brazil-to-amsterdam-5jc</guid>
      <description>&lt;h4&gt;
  
  
  What I’ve learned after eight months living in the Netherlands
&lt;/h4&gt;

&lt;p&gt;In this beginning of 2015 I commemorated the eighth month of my arrival in Amsterdam. I was found by a &lt;a href="http://grnh.se/qyn5hc" rel="noopener noreferrer"&gt;Booking.com&lt;/a&gt; recruiter on May of the previous year, and after three interviews, 33 hours in airplanes and the usual bureaucracy, immigrated to the Netherlands with a permanent contract.&lt;/p&gt;

&lt;p&gt;I had &lt;strong&gt;never&lt;/strong&gt; thought that I would be living in Amsterdam. If you know me, you’re well aware where my heart is.&lt;/p&gt;

&lt;p&gt;Now, eight months later, I already go everywhere on &lt;a href="http://instagram.com/p/re84GAmtcd/" rel="noopener noreferrer"&gt;my bike&lt;/a&gt;¹, fell miserably by getting both wheels on a tram track, smoked &lt;em&gt;tolerated&lt;/em&gt; pot², saw a day with &lt;a href="http://en.wikipedia.org/wiki/Summer_solstice" rel="noopener noreferrer"&gt;16 hours of sunlight&lt;/a&gt;, had a barbecue on &lt;a href="https://www.google.com/maps/@52.3572862,4.8861256,358a,20y,279.78h,70.01t/data=!3m1!1e3" rel="noopener noreferrer"&gt;Vondelpark&lt;/a&gt;, took &lt;a href="http://instagram.com/p/wrf21KGtdc/" rel="noopener noreferrer"&gt;a&lt;/a&gt; &lt;a href="http://instagram.com/p/wqV0xZmteG/" rel="noopener noreferrer"&gt;lot&lt;/a&gt; &lt;a href="http://instagram.com/p/onM0IxGtWE/" rel="noopener noreferrer"&gt;of&lt;/a&gt; &lt;a href="https://www.facebook.com/photo.php?fbid=10205027328467876" rel="noopener noreferrer"&gt;incredibly&lt;/a&gt; &lt;a href="https://www.facebook.com/photo.php?fbid=10205188949588303" rel="noopener noreferrer"&gt;beautiful&lt;/a&gt; &lt;a href="https://www.facebook.com/photo.php?fbid=10205678822794827" rel="noopener noreferrer"&gt;pictures&lt;/a&gt;, went on a road trip to &lt;a href="http://en.wikipedia.org/wiki/Munich" rel="noopener noreferrer"&gt;Munich&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Cologne" rel="noopener noreferrer"&gt;Cologne&lt;/a&gt;, learned to play Tennis Table, met incredible people — some even became friends –, et cetera.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AJnAGRzSFv7OGewfTkBQtgw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AJnAGRzSFv7OGewfTkBQtgw.jpeg"&gt;&lt;/a&gt;Panorama view from my first apartment in Jordaan&lt;/p&gt;

&lt;h3&gt;
  
  
  The good
&lt;/h3&gt;

&lt;p&gt;Amsterdam is beautiful. It is a huge metropolitan city, with small and very tight historically preserved buildings, it feels cozy with nearby services — &lt;a href="http://en.wikipedia.org/wiki/Albert_Heijn" rel="noopener noreferrer"&gt;the same market&lt;/a&gt; every 2 blocks — but still full of big brand stores, tourists and life everywhere.&lt;/p&gt;

&lt;p&gt;I was biking to work when it hit me: I really lik living here. It was a good weather, I was cycling peacefully, the landscape was gorgeous. There’s nowhere else in the world that combines all of this.&lt;/p&gt;

&lt;h3&gt;
  
  
  The tricky
&lt;/h3&gt;

&lt;p&gt;The biggest challenge for people that come from warmer areas is the winter. It’s cold, it rains, and there are 80 Km/h winds, sometimes all together, because fuck you.&lt;/p&gt;

&lt;p&gt;Customer service is also a pain point for most people. Here it’s normal to spend a lot of money on a 0900 customer call, only to get a condescending “sorry, I cannot help you at all”.&lt;/p&gt;

&lt;p&gt;And don’t expect to learn Dutch so quickly. Besides being very difficult, &lt;a href="http://en.wikipedia.org/wiki/English_in_the_Netherlands" rel="noopener noreferrer"&gt;90% of the Dutch population speak English&lt;/a&gt;, and they often respond in English if they see you trying to speak poor Dutch.&lt;/p&gt;

&lt;h3&gt;
  
  
  The learnings
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;I am an expat, and expats are everywhere.&lt;/strong&gt; The Dutch government is very open to accepting foreign people to live here. And this is partially explained by the &lt;a href="http://www.dutchnews.nl/news/archives/2015/01/the-netherlands-has-a-shortage-of-it-workers.php/" rel="noopener noreferrer"&gt;shortage of IT workers in the country&lt;/a&gt;. There are a lot of expat specialized services, from &lt;a href="http://www.iamsterdam.com/en/expatcenter" rel="noopener noreferrer"&gt;the migration process&lt;/a&gt; to &lt;a href="http://www.expat-mortgages.nl/" rel="noopener noreferrer"&gt;buying a house&lt;/a&gt;. And you get a ton of books and brochures to ease the transitions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everything can be very cheap or very expensive&lt;/strong&gt; , for instance a good beer bottle costs around € 0,80 on the supermarket, but the rent of a small one bedroom apartment can be as high as € 1500. Overall that’s the only higher-than-normal expense, the rest is very reasonable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forget converting currencies&lt;/strong&gt; because you’ll get insane. My Brazilian friends say &lt;em&gt;“quem converte não se diverte”&lt;/em&gt;, something like “people that convert have no fun at all”, and that is true. It doesn’t make sense going back to your own country’s currency and comparing what you once spent there and here, you have to balance the absolute numbers, from your salary to your budget. And in the end you’ll see that things are surprisingly fair.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The city is not a mess of drunk and disorderly people.&lt;/strong&gt; Although there are a &lt;strong&gt;lot&lt;/strong&gt; of tourists, specially on the weekends, and drugs are tolerated², everything runs like clockwork. The city is constantly cleaned, public transportation is rarely crowded, and you rarely smell marijuana. The biggest mess happens on new years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And people go crazy on new years.&lt;/strong&gt; Seriously, it is &lt;a href="http://en.wikipedia.org/wiki/Fireworks#Dutch_fireworks_festivals" rel="noopener noreferrer"&gt;the &lt;em&gt;only&lt;/em&gt; period that fireworks are allowed&lt;/a&gt;, so people go nuts! I’ve seen them throwing firecrackers from apartment windows directly into walking people on the streets, lighting boxes of big explosives and watching very closely, kicking bottles with rockets that someone else left, making it fly into the crows at the Dam. It is terrifying and awesome at the same time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dutch people are born in their bicycles.&lt;/strong&gt; Of course I’m kidding, but there’s no weather that can hold them back. They’ll be riding in heavy rain on a windy cold day, with an umbrella in a hand and a phone in the other. And they are above everything, if you’re a pedestrian, you’ll be screamed at for being in the way. And it helps a lot that the city is completely levelled. The biggest hills we have to cycle are some canal bridges, and the highest places in the country are actually shared with Belgium and Germany.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parks. Parks everywhere.&lt;/strong&gt; There are &lt;a href="http://www.amsterdam.info/parks/" rel="noopener noreferrer"&gt;about 30 parks&lt;/a&gt; in Amsterdam, together with squares, a myriad of museums, night clubs and pubs, you’ll find something to do every time of the day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s a great place for your children.&lt;/strong&gt; Most of the Brazilians that moved here are married with young children, and it’s amazing how much their kids can learn, and how much the government is involved. From free health care and constant care monitoring, to the fact they’ll learn at least three languages (Dutch, English and their native), it is certainly a very good boilerplate for a world citizen.&lt;/p&gt;

&lt;h3&gt;
  
  
  And so much more
&lt;/h3&gt;

&lt;p&gt;It’s impossible to resume everything in a post, it would be a book, and I bet many people already wrote one.&lt;/p&gt;

&lt;p&gt;Ping me on &lt;a href="https://twitter.com/WesleydeSouza" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.facebook.com/wesley.souza" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt; if you have suggestions for a complimentary post to this one.&lt;/p&gt;

&lt;p&gt;And I can really vouch for Booking.com for recruiting and helping people move here. If you’re interested in working here, they have &lt;a href="http://grnh.se/qyn5hc" rel="noopener noreferrer"&gt;a lot of openings from frond end and back end developers, to data scientists, UX designers, and many other&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;¹ Of course if the temperature is above 10˚C, and within a certain range.&lt;/p&gt;

&lt;p&gt;² Nothing is really legal in the Netherlands, just tolerated.&lt;/p&gt;

</description>
      <category>expat</category>
      <category>netherlands</category>
      <category>travel</category>
      <category>amsterdam</category>
    </item>
  </channel>
</rss>
