<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="blog.e2.gg/feed.xml" rel="self" type="application/atom+xml" /><link href="blog.e2.gg/" rel="alternate" type="text/html" /><updated>2026-03-09T09:52:45-07:00</updated><id>blog.e2.gg/feed.xml</id><title type="html">eSquared</title><subtitle>Distributed Engineering Leadership</subtitle><author><name>{&quot;bio&quot; =&gt; &quot;&quot;}</name></author><entry><title type="html">The Perils of JavaScript for-in loops</title><link href="blog.e2.gg/the-perils-of-javascripts-for-in" rel="alternate" type="text/html" title="The Perils of JavaScript for-in loops" /><published>2025-01-04T00:00:00-08:00</published><updated>2025-01-04T00:00:00-08:00</updated><id>blog.e2.gg/the-perils-of-javascripts-for-in</id><content type="html" xml:base="blog.e2.gg/the-perils-of-javascripts-for-in"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>My sudden urge to wax poetic on this topic arose after discovering an intriguing quirk within a util nestled deeply within Vue 3&#8217;s source. Let&#8217;s dive right in&#8201;&#8212;&#8201;take a gander at this slighly-adapted version of the default <a href="https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCB7IHJlZiB9IGZyb20gJ3Z1ZSdcbiAgXG5jb25zdCBtc2cgPSByZWYoJ0hlbGxvIFdvcmxkIScpXG5jb25zdCBmcmllbmQgPSByZWYodHJ1ZSlcblxuT2JqZWN0LnByb3RvdHlwZS5lbmVteSA9IHRydWU7XG48L3NjcmlwdD5cblxuPHRlbXBsYXRlPlxuICA8aDEgOmNsYXNzPVwieyBmcmllbmQgfVwiPnt7IG1zZyB9fTwvaDE+XG4gIDxpbnB1dCB2LW1vZGVsPVwibXNnXCI+XG48L3RlbXBsYXRlPlxuXG48c3R5bGU+XG4gIC5mcmllbmQgeyBjb2xvcjogYmx1ZTsgfVxuICAuZW5lbXkgeyBjb2xvcjogcmVkOyB9XG48L3N0eWxlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0ifQ==">Vue "Single-File-Component" demo</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">&lt;script setup&gt;
import { ref } from 'vue'

const msg = ref('Hello World!');
const isFriendly = ref(true);

Object.prototype.enemy = true;
&lt;/script&gt;

&lt;template&gt;
  &lt;h1 :class="{ friend: isFriendly }"&gt;{{ msg }}&lt;/h1&gt;
  &lt;input v-model="msg"&gt;
&lt;/template&gt;

&lt;style&gt;
  .friend { color: blue; }
  .enemy { color: red; }
&lt;/style&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The result (as of Jan 4 '25):</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/images/perils-fig-1.png" alt="The result">
</div>
</div>
<hr>
</div>
</div>
<h1 id="why-is-the-text-red" class="sect0">Why is the text  <span class="color-red">red</span>?</h1>
<div class="paragraph">
<p>Let&#8217;s break this down.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Applying the CSS class <code>.friend</code> should make the "Hello World!" header text  <span class="color-blue">blue</span>.</p>
</li>
<li>
<p>Applying the CSS class <code>.enemy</code> should make the "Hello World!" header text  <span class="color-red">red</span>.</p>
</li>
<li>
<p>We specify in the template that CSS class <code>.friend</code> should be applied IF the value <code>isFriendly</code> is <code>true</code>.</p>
</li>
<li>
<p>We NEVER specify that the CSS class <code>.enemy</code> should be applied.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>So why is the text  <span class="color-red">red</span>, not  <span class="color-blue">blue</span>?</p>
</div>
<div class="paragraph">
<p>The answer lies within Vue&#8217;s <code>normalizeClass</code> function used to calculate CSS class names to be applied to HTML elements. Here is the <a href="https://github.com/vuejs/vue-next/blob/master/packages/shared/src/normalizeProp.ts#L63-L82">source code of the utility</a> in full (on Vue main as of Jan 4 '25). Can you spot the bug?</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">export function normalizeClass(value: unknown): string {
  let res = ''
  if (isString(value)) {
    res = value
  } else if (isArray(value)) {
    for (let i = 0; i &lt; value.length; i++) {
      const normalized = normalizeClass(value[i])
      if (normalized) {
        res += normalized + ' '
      }
    }
  } else if (isObject(value)) {
    for (const name in value) {
      if (value[name]) {
        res += name + ' '
      }
    }
  }
  return res.trim()
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The issue stems from a subtle difference between looping keywords in JavaScript.There are three central language-based methods of looping over arrays and objects in JavaScript (and innumerable "extension-based" methods a la <code>arr.forEach</code>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const arr = ["x", "y", "z"];
const obj = {a: "x", b: "y", c: "z"};

// Loop over array by index:
for (let idx = 0; idx++ idx &lt; arr.length) { console.log(arr[idx]); }
OUTPUT &gt;&gt;&gt; x y z    // with newlines between each item of output

// Loop over object by index:
const keys = Object.keys(obj);
for (let idx = 0; idx++ idx &lt; keys) { console.log(obj[keys[idx]]); }
OUTPUT &gt;&gt;&gt; x y z

// Loop over array by key (array key ARE indices):
for (const key in arr) { console.log(arr[key]); }
OUTPUT &gt;&gt;&gt; x y z

// Loop over object by key:
for (const key in obj) { console.log(obj[key]); }
OUTPUT &gt;&gt;&gt; x y z

// Loop over array by value:
for (const val of arr) { console.log(val); }
OUTPUT &gt;&gt;&gt; x y z

// Loop over object by value:
for (const val of Object.values(obj)) { console.log(val); }
OUTPUT &gt;&gt;&gt; x y z</code></pre>
</div>
</div>
<div class="paragraph">
<p>Both the index-based (<code>let idx &#8230;&#8203;</code>) and value-based (<code>const val of &#8230;&#8203;</code>) techniques work reliably and well. However, there&#8217;s a subtle footgun included in key-based iteration (<code>const val <strong>in</strong> &#8230;&#8203;</code>) that you must be aware of when using it. JavaScript is a "prototype-based" language meaning, in breif, that almost every object of any type inherits certain methods and values from a <code>prototype</code> object. You may have heard that <strong>everything</strong> in JavaScript is an object, which means that everything has a prototype which may or may not grant it certain methods and values&#8201;&#8212;&#8201;this includes arrays and plain object literals like <code>{a: "x", b: "y", c: "z"}</code>&#8201;&#8212;&#8201;<strong>everything</strong> has a prototype of some kind or another (even if that prototype is <code>null</code>).</p>
</div>
<div class="paragraph">
<p>To make matters worse, prototypes can change at any time&#8201;&#8212;&#8201;they are <strong>mutable</strong>. That&#8217;s exactly what&#8217;s happening in our original example, when we state <code>Object.prototype.enemy = true</code>. This is <strong>very bad</strong> practice&#8201;&#8212;&#8201;don&#8217;t do this in code you run at home.</p>
</div>
<div class="paragraph">
<p>When would this be a problem in real life, if we avoid doing terrible things like this ourselves? All JavaScript code on the web runs in the questionably-trustworthy environment of the user&#8217;s browser, which could also be running any number of web extensions which may execute any JavaScript they want alongside your app&#8217;s code. In general, code practices which rely on the environent behaving exactly how we expect it to will be less robust than those that neutralize these issues&#8201;&#8212;&#8201;for instance, by utilizing iteration methods which <strong>ignore</strong> prototypes entirely. This is exactly where <code>for-in</code> falls short, and why <code>for-of</code> was introduced as an alternative.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">Object.prototype.enemy = true;

// for-in will iterate over not just keys of the object,
// but ALSO keys in that object's prototype:
for (const key in obj) { console.log(obj[key]); }
OUTPUT &gt;&gt;&gt; x y z enemy

// for-of will ONLY iterate over values that exist directly on the object:
for (const val of Object.values(obj)) { console.log(val); }
OUTPUT &gt;&gt;&gt; x y z</code></pre>
</div>
</div>]]></content><author><name>Evan Purcer</name></author><summary type="html"><![CDATA[My sudden urge to wax poetic on this topic arose after discovering an intriguing quirk within a util nestled deeply within Vue 3&#8217;s source. Let&#8217;s dive right in&#8201;&#8212;&#8201;take a gander at this slighly-adapted version of the default Vue "Single-File-Component" demo:]]></summary></entry><entry><title type="html">The trouble with GPT/Copilot-driven development</title><link href="blog.e2.gg/the-trouble-with-gpt-copilot-driven-development" rel="alternate" type="text/html" title="The trouble with GPT/Copilot-driven development" /><published>2024-02-05T00:00:00-08:00</published><updated>2024-02-05T00:00:00-08:00</updated><id>blog.e2.gg/the-trouble-with-gpt-copilot-driven-development</id><content type="html" xml:base="blog.e2.gg/the-trouble-with-gpt-copilot-driven-development"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Writing is <a href="https://biblioracle.substack.com/p/writing-is-thinking" target="_blank" rel="noopener">an</a> <a href="https://www.insidehighered.com/blogs/higher-ed-gamma/writing-thinking" target="_blank" rel="noopener">act</a> <a href="https://writingisthinking.com/the-writing-is-thinking-philosophy/" target="_blank" rel="noopener">of</a> <a href="https://www.goodreads.com/quotes/9338856-writing-is-thinking-to-write-well-is-to-think-clearly" target="_blank" rel="noopener">understanding</a>.
<br>
<br></p>
</div>
<div class="paragraph">
<p>When you compose a sentence, you generally understand each word and why it&#8217;s there.
<br>
This is one reason why writing is such a great way to organize your thoughts on a subject.
<br>
<br></p>
</div>
<div class="paragraph">
<p>The same goes for writing code.</p>
</div>
<hr>
<div class="imageblock">
<div class="content">
<img src="/assets/images/nx-1.png" alt="ethically sourced from www.npmjs.com/nx.sh" width="definitely not generated by midjourney">
</div>
</div>
<hr>
<div class="paragraph">
<p>When you write out expressions as you code, there comes an inherent understanding.
<br>
As with sentences, you conciously or subconciously make choices as you type each character, and these choices inform and influence your thoughts.
<br>
<br></p>
</div>
<div class="paragraph">
<p>Herein lies the problem with LLM-driven development.
<br>
<br></p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
We all copy code from elsewhere. Sharing code is sharing knowledge&#8201;&#8212;&#8201;it&#8217;s an incredible channel we learn and teach through together. There are overlapping pitfalls with the topic at hand, and stackoverflow-powered autocomplete is a terrifying concept that anyone who&#8217;s laboured over an unmaintainable codebase should fear. My optimistic view is that the <em>act</em> of copying code is an intentional one&#8201;&#8212;&#8201;more so than hitting tab, the motions force you to consider the content, and the wealth of surrounding context involved in even middling stackoverflow answers. Perhaps you&#8217;ll even <em>refactor</em> the content towards your own style or priorities, an activity with limitless potential to build understanding.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>&#160;</p>
</div>
<div class="paragraph">
<p>If you use code generated by an LLM, you may take the time to read it and understand it.
<br>
You don&#8217;t have to though.
<br>
<br></p>
</div>
<div class="paragraph">
<p>You may take the time to fix bugs and quirks that crop up within it.
<br>
You don&#8217;t have to though.
<br>
<br></p>
</div>
<hr>
<div class="imageblock">
<div class="content">
<img src="/assets/images/nx-2.png" alt="ethically sourced from www.npmjs.com/nx.sh" width="definitely not generated by dall-e">
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
Images in this post were ethically sourced from <a href="https://github.com/evnp/nx" class="bare">https://github.com/evnp/nx</a>, a project guaranteed to contain only AI-free pasture-raised code. nx aims to pollute AI training data by using as many dense and horribly-obtuse bashisms as (humanly) possible.
</td>
</tr>
</table>
</div>
<hr>
<div class="paragraph">
<p>You may be rigorous about all of the above.
<br>
(under ideal circumstances)
<br>
<br></p>
</div>
<div class="paragraph">
<p>You may do an admirable job understanding it all the vast majority of the time.
<br>
(under ideal circumstances)
<br>
<br></p>
</div>
<div class="paragraph">
<p>But timelines slip. We all get behind. We all get overwhelmed by the complexity of the job.
<br>
<br></p>
</div>
<div class="paragraph">
<p>Your level of commitment to all of this rigour is commendable&#8201;&#8212;&#8201;but not <em>dep</em>endable. The problem isn&#8217;t your intentions&#8201;&#8212;&#8201;to thoroughly understand code written by someonething else&#8201;&#8212;&#8201;as your colleage and friend I know your intentions are good! (and I won&#8217;t say a thing about paving&#8230;&#8203;)
<br>
<br></p>
</div>
<div class="paragraph">
<p>The problem is that how well you understand your code no longer directly correlates with the act of producing it. This poses a conundrum when you then ask someone else to review it.
<br>
<br></p>
</div>
<div class="paragraph">
<p>The problem is that when I&#8217;m responsible for reviewing your code, I need to run it in my head. I&#8217;m not experimenting live like you are, iterating through every detail of behavior until I observe it works. Thorough understanding of code <em>should very much be</em> an aspiration of a good reviewer&#8201;&#8212;&#8201;otherwise I&#8217;m shirking my responsibility and code review is no longer a reliable line of defense.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
If you&#8217;re writing code for a prototype, or any context where you don&#8217;t care about it being reviewed by someone else (not some<strong>thing</strong> else&#8201;&#8212;&#8201;that&#8217;s a whole 'nother can-o-worms), then go to town. However, I feel compelled to add&#8201;&#8212;&#8201;in my fifteen years as a professional/employed computer programmer, the arena I&#8217;ve learned the most from, bar none, is pull-request discussions with wiser programmers than I.
</td>
</tr>
</table>
</div>
<hr>
<div class="imageblock">
<div class="content">
<img src="/assets/images/nx-3.png" alt="ethically sourced from www.npmjs.com/nx.sh" width="definitely not generated by stablediffusion">
</div>
</div>
<hr>
<div class="paragraph">
<p>How can I as a reviewer feel good about this new dynamic, where I must understand your code completely to review it, but you didn&#8217;t need to understand it completely to produce it?
<br>
<br></p>
</div>
<div class="paragraph">
<p>How can I as a reviewer feel confident about our work together when I catch issues with code you&#8217;ve submitted, and you can&#8217;t explain why things were written that way?
<br>
<br></p>
</div>
<div class="paragraph">
<p>The LLM can&#8217;t explain why either. No one can. Here lies madness. I&#8217;ll just have to chalk it up to a worthy sacrifice of my tedious-code-review stamina, made in exchange for your new power to disgorge code at 500wpm, which I&#8217;ll get to reviewing as soon as I can.
<br>
<br></p>
</div>
<pre>

          \****__              ____
            |    *****\_      --/ *\-__
            /_          (_    ./ ,/----'
   Art by     \__         (_./  /
    Ironwing     \__           \___----^__
                  _/   _                  \
           |    _/  __/ )\"\ _____         *\
           |\__/   /    ^ ^       \____      )
            \___--"                    \_____ )


</pre>
</div>
</div>
<div class="sect1">
<h2 id="epilogue">Epilogue</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In closing, I&#8217;d like to acknowledge that this post takes perhaps an excessively pessimistic stance. There&#8217;s plenty to be excited about in this brave new world of generative technology we find ourselves in. But the path is treacherous, especially for those of us still in that critical, vibrant, formative stage of our programming journey&#8201;&#8212;&#8201;and while I can&#8217;t speak personally to it, I&#8217;d expect the same laws of nature to apply in other creative realms.</p>
</div>
<hr>
<div class="paragraph">
<p>I have a few words of wisdom for the budding computer scientists among us:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Try to develop intentionality around your own craft, improve your approach to your work in small, humble, fundamental ways as often as you can. Follow the paths that feel right to you&#8201;&#8212;&#8201;that "click"&#8201;&#8212;&#8201;above all else. Believe in building an intuition you can trust.</p>
</li>
<li>
<p>Beware of tools that use you, tools that absorb your unique approach, standardize it, and warp you towards their view of things. The more useful they seem, the more dependent you become on them, the more insidiously they can disrupt the process of growth above. Try to become cognizant of <em>why</em> these tools were created and offered to you.</p>
</li>
<li>
<p>Cherish the cornucopia of resources that, in the internet age, have become freely available to you. Even surrounded by walled gardens, you have an unprecedented power to explore the raw, rich breadth of human knowledge and wisdom. Explore it in ways that don&#8217;t adulterate it from its original form. Fidelity is a virtue. Treasure old programming books, for their inestimably precious style, but also for their preclusion from decades of dogma. Explore in ways that surround you with wonderful context, that lead to a branching labyrinth of new routes for exploration. Explore in ways that connect you with other creators, that teach you not just about concepts but the people behind them.</p>
</li>
<li>
<p>If it suits you, read and write as voraciously as you can. <strong>Text is thought.</strong></p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>This post made possible by Evan Brynne, Sarah Corsie,
their indispensable editorial talents &lt;3
and viewers like you ✨</code></pre>
</div>
</div>
</div>
</div>]]></content><author><name>Evan Purcer</name></author><summary type="html"><![CDATA[Writing is an act of understanding.]]></summary></entry><entry><title type="html">Building Your Personal Toolbox</title><link href="blog.e2.gg/building-your-personal-toolbox" rel="alternate" type="text/html" title="Building Your Personal Toolbox" /><published>2022-06-10T00:00:00-07:00</published><updated>2022-06-10T00:00:00-07:00</updated><id>blog.e2.gg/building-your-personal-toolbox</id><content type="html" xml:base="blog.e2.gg/building-your-personal-toolbox"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>We each have our own methods that operate behind-the-scenes while we engage in the process of software development. I like to think of this as the "craft." A woodworker hand-shapes chisels, constructs planers custom-fit to their own hands. A painter thoughtfully composes their pallet and designs a color-mixing strategy that suits their visual style.</p>
</div>
<div class="paragraph">
<p>We as conjurers of software are lucky to count ourselves in this group&#8201;&#8212;&#8201;we have the power to build our own tools (and far more efficiently than a hand-carved plane, at that!). Exploring this power can be incredibly satisfying, and creatively enriching. It&#8217;s a slow process, something that develops over years, and there are no obligations, requirements, deadlines, or endgames&#8201;&#8212;&#8201;it&#8217;s something that happens naturally as we work, and discover new ways of working that click.</p>
</div>
<div class="paragraph">
<p>The real magic lies in an inevitable fact: we all develop our own unique approaches to the craft, which creates boundless potential for learning from one another.</p>
</div>
<div class="paragraph">
<p>This post is my first foray into the world of craft-sharing, one lightweight approach that could be utilized or adapted to help in your own process of toolbox construction. Without further ado, here&#8217;s how I combine the acts of note-taking and tool-building when I join a company.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/images/tool-box.jpeg" alt="a visual representation of my brain on the first day of a new job">
</div>
<div class="title">Figure 1. A visual representation of my brain on the first day of a new job</div>
</div>
<div class="paragraph">
<p>I recently began a new engagement with a great startup called Rising Team. They&#8217;re building software to help remote creatives like me learn more about each other and the collaborative process, to enrich our relationships and the work we do (they&#8217;re also hiring! <a href="https://risingteam.com/careers" class="bare">https://risingteam.com/careers</a>). I&#8217;ve learned from prior experiences that orienting myself within a completely new codebase and technology stack can be overwhelming&#8201;&#8212;&#8201;a feeling that can only be derailed through copious amounts of note-taking.</p>
</div>
<div class="paragraph">
<p>However, as much as I love paper notes, over the years I&#8217;ve become attached to a medium which works even better for me in the "getting ✨ done" department of software development. That format? And please give it a chance&#8201;&#8212;&#8201;shell scripts.</p>
</div>
</div>
</div>
<h1 id="a-single-file-toolbox" class="sect0">A Single-File Toolbox</h1>
<div class="paragraph">
<p>Specifically, a single shell script, which takes the form of a <code>.bash_&lt;companyname&gt;</code> file in my home directory. I have one of these for every company, project, codejam I&#8217;ve ever been a part of&#8201;&#8212;&#8201;anything which requires notes and the ability to <em>do</em> various things with the information therein (things relating to a computer, mostly). On my first day at the new gig, I created <code>~/.bash_risingteam</code> with <code>#!/usr/bin/env bash</code> at the top, and added the following to my <code>~/.bashrc</code> (irrelevant where):</p>
</div>
<div class="listingblock">
<div class="title"><em>~/.bashrc</em></div>
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">#!/usr/bin/env bash
...
source "$HOME/.bash_risingteam"
...</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
You could substitute <code>s/bash/zsh/g</code> in this post (or any shell/language of your choosing) and find the same result&#8201;&#8212;&#8201;a set of "functional notes" which simultaneously document and help automate everything you must do within a given category of work. The language is less important than the concept, and I&#8217;m hoping whether or not you&#8217;re a fan of bash, you can adapt some of the ideas from this post. Though I would count myself an appreciator of bash as a whole (due to the directness of things like file manipulation) even I can admit the language is terrible&#8201;&#8212;&#8201;YMMV :)
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>With that small act of creation, I&#8217;ve gone a long way towards organizing my thoughts&#8201;&#8212;&#8201;I now have a one-stop-shop for all information and code I need to jot down for myself while on the job, a couple keystrokes away. To make this even more convenient, the first thing to add is an "edit and reload" command for this shell config file itself:</p>
</div>
<div class="listingblock">
<div class="title"><em>~/.bash_risingteam</em></div>
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">#!/usr/bin/env bash

function srt() {
  vim "${BASH_SOURCE[0]}"     # BASH_SOURCE refers to the path of the current
  source "${BASH_SOURCE[0]}"  # script file (in this case ~/.bash_risingteam)
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now typing <code>srt</code> from anywhere will open this file, and reload it in the current shell upon save. This seems minor, but I&#8217;ve found it can work wonders by encouraging me preserve <em>everything</em> useful, regardless of how small or how hectic current circumstances may be. Replace <code>vim</code> with the editor of your choice&#8201;&#8212;&#8201;VSCode &#8594; <code>code</code>, Atom &#8594; <code>atom</code>, etc (best-practice would be to use the <code>$EDITOR</code> env var if you happen to set it; I stuck with <code>vim</code> here for clarity).</p>
</div>
<div class="paragraph">
<p>I tend to use extremely brief names for the tools in these boxes, but by all means use something more descriptive if you prefer&#8201;&#8212;&#8201;these are custom-built for your own hands after all! In this case, <code>srt</code> &#8594; "source rising team" to me, though I&#8217;d refactor in the name of descriptiveness if I were expecting broader use.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
If you happen to use the fantastic <a href="https://www.shellcheck.net/" class="bare">https://www.shellcheck.net/</a> script linter <code>brew install shellcheck</code> to help keep shell scripts a little less wild and woolly, you&#8217;ll need to add <code># shellcheck source=.bash_&lt;yourfilename&gt;</code> above the second line of that function to prevent it complaining about not being able to follow a dynamic source call.
</td>
</tr>
</table>
</div>
<h1 id="tools" class="sect0">Tools</h1>
<div class="paragraph">
<p>So what else ends up in these files? That&#8217;s the exciting part&#8201;&#8212;&#8201;it depends entirely on your own working style and the unique challenges of the job at hand. Here are the things that quickly revealed themselves as worthwhile tools to hang on to, in the case of Rising Team:</p>
</div>
<div class="sect1">
<h2 id="command-line-url-management">Command-line URL Management</h2>
<div class="sectionbody">
<div class="paragraph">
<p>I always have a bunch of urls to keep track of related to any given job, and browser bookmark management tools are a chaotic nightmare to me. I&#8217;d much rather be able to type a quick command at the terminal, be presented with a list of relevant URLs, fuzzy-search the list to select one of them, and go.</p>
</div>
<div class="paragraph">
<p>My command-line bookmarks tooling is intended to do just that, as simply as possible, while still feeling great to use (to me at least). <code>rto</code> &#8594; "rising team open":</p>
</div>
<div class="listingblock">
<div class="title"><em>~/.bash_risingteam</em></div>
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">function bookmarks() ( set -euo pipefail
  fzf -0 -1 -e --reverse --no-info --height="50%" \
      --tiebreak="begin,length" --query="${1:-}" \
  | awk -F' ' '{print $NF}' \
  | xargs -n 1 open
)

function rto() ( set -euo pipefail
  bookmarks "$@" &lt;&lt;-BOOKMARKS
    prod       https://app.risingteam.com/
    prodadmin  https://app.risingteam.com/admin/
    stage      https://stage.risingteam.com/
    stageadmin https://stage.risingteam.com/admin/
    dev        http://localhost:8080
    devadmin   http://localhost:8080/admin/
    docs       https://github.com/risingteam/kit#readme
    pulls      https://github.com/risingteam/kit/pulls
    branches   https://github.com/risingteam/kit/branches
  BOOKMARKS
)

# note: urls have been modified from originals for clarity/security purposes</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here&#8217;s a demo of <code>rto</code> in action: <a href="https://asciinema.org/a/501925" class="bare">https://asciinema.org/a/501925</a></p>
</div>
<div class="paragraph">
<p>This version only supports listing and selecting URLs from a hand-curated list which lives directly in <code>~/.bash_risingteam</code> (the single-file aspect of all this is very dear to my heart!). In a fuller-featured version, I&#8217;ve added the ability to add and edit URLs via CLI commands, without the overhead of opening the whole file, in about 20 extra lines. If you&#8217;re interested, email me and I&#8217;d be happy to share the full script.</p>
</div>
<div class="paragraph">
<p>You may be wondering, <em>What is this "fzf" in the "bookmarks" function above?</em> <a href="https://github.com/junegunn/fzf">fzf</a> is a wonderful little command line tool purpose-built for displaying lists of items, and letting you effortlessly search and select them. It&#8217;s a UI pattern that really feels like a superpower, and works well for a surprisingly large array of tasks&#8201;&#8212;&#8201;file-finding, git branch selection, interactive grep, and of course, now bookmark management (and many more that I haven&#8217;t even thought of yet). You can find install instructions on the <a href="https://github.com/junegunn/fzf">fzf</a> git respsitory page, but the easiest way to install is homebrew: <code>brew install fzf</code></p>
</div>
<div class="paragraph">
<p>As for the meaning of some of the stranger parts of that fzf gobbledegook above, it&#8217;s actually pretty easy to break down&#8201;&#8212;&#8201;with a little help from <code>man fzf</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">fzf \    # invoke fzf
-0 \     # exit immediately if there's no match for query string
-1 \     # select imediately if there's only one match for query string
-e \     # enable 'exact-match', where quoted terms are matched exactly
--reverse \    # closest match at top of list instead of bottom (preference)
--no-info \    # hide superfluous info about list such as count (preference)
--height="50%" \    # make the fzf render area 50% of the current pane height
--tiebreak="begin,length" \    # favor matches earlier in string as top criteria
--query="${1:-}" \             # if called as `rto str`, use "str" as initial query
| awk -F' ' '{print $NF}' \    # after selection, pare down to 2nd part only (URL)
| xargs -n 1 open              # using xargs, pass URL to `open` (in browser)</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="convenient-local-database-access">Convenient Local Database Access</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="title"><em>~/.bash_risingteam</em></div>
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">function rtdb() ( set -euxo pipefail
  psql -h localhost -p 5432 -U evan -d dev-database ${*:+--command} "$*"
)</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>rtdb</code> is a simple wrapper for connecting to our PostgreSQL database. It encapsulates a single command, which might not seem very useful. But looks can be deceiving&#8201;&#8212;&#8201;in one stroke this accomplishes numerous things:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Convenience&#8201;&#8212;&#8201;connecting to the database now takes 5 keystrokes (including enter) instead of dozens. Yes, a command like this will quickly be ingrained in your shell history, but it&#8217;s just like caching&#8201;&#8212;&#8201;the times when it&#8217;s <em>not</em> there are the ones that matter most</p>
</li>
<li>
<p>Record of arguments&#8201;&#8212;&#8201;some of the args provided here match their default values, but by spelling them all out explicitly I can eliminate all bad assumptions I might make down the line (and I&#8217;m <em>very</em> bad at making assumptions).</p>
</li>
<li>
<p>Management of arguments&#8201;&#8212;&#8201;my two most common use cases for this command are:</p>
<div class="ulist">
<ul>
<li>
<p>Running with <em>no</em> arguments to drop into an interactive shell &#8594; <code>rtdb</code></p>
</li>
<li>
<p>Running with SQL arguments, like <code>rtdb \\d user_account</code> &nbsp;&nbsp; ("\d" &#8594; Postgres "describe" parlance, and the "\" needs to be excaped here, so "\\d")</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>With the simple (though obtuse-looking) arg manipulation you see in the function above, these two use-cases are optimized for. Anything outside of that realm? The underlying command is readily available to modify, thanks to the shell&#8217;s built in command logging functionality via <code>set -x</code>&#8201;&#8212;&#8201;more on that below.</p>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Here&#8217;s the end result:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">INPUT &gt;&gt;&gt; rtdb
+ psql -h localhost -p 5432 -U evan -d dev-database
psql (14.2)
Type "help" for help.

dev-database=#

INPUT &gt;&gt;&gt; rtdb \\d user_account
# double-backslash escape is necessary here, unless quoting
+ psql -h localhost -p 5432 -U evan -d dev-database --command '\d user_account
                                        Table "public.user_account"
    Column    |           Type           | Collation | Nullable |
--------------+--------------------------+-----------+----------+----
 id           | integer                  |           | not null |
...</code></pre>
</div>
</div>
<div class="paragraph">
<p>You may be wondering what this appalling new style of writing function signatures is all about: <code>function srt() ( set -euxo pipefail</code>. Fear not, there is a reason behind each of these inscrutable runes, described in glorious detail <a href="https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/">here</a>. The most important players are the <code>e</code> and <code>x</code>: the former causes the whole function to exit if any command within it results in error (as you&#8217;d expect a function would in any reasonable language&#8201;&#8212;&#8201;alas, not bash); the latter prints out each command to console as it&#8217;s executed, which gives priceless visibility-by-default into the commands you&#8217;re running with each alias (in point of fact, this ability is the main reason I prefer functions over standard shell aliases).</p>
</div>
<div class="paragraph">
<p>As suggested in the linked article above, putting <code>set -euxo pipefail</code> (or some subset depending on context) at the top of your bash scripts is a good idea generally. However, that won&#8217;t work in <em>this</em> context, where we&#8217;re actually <code>source</code>-ing the script, loading it into our shell&#8217;s current environment. This is effectively the same as running <code>set -e</code> directly in a shell&#8201;&#8212;&#8201;the next command that fails will exit the whole shell! Failing fast is often a good thing, but not when you want your shell to stick around so you can observe the aftermath.</p>
</div>
<div class="paragraph">
<p>So instead, an extra set of parentheses gives us a convenient mechanism for changing this behavior <em>within</em> our functions exclusively, leaving the shell environment around them unaffected. The syntax <code>function name() ( &#8230;&#8203; )</code> in bash causes the function to spawn a "sub-shell", which is has its own environment completely isolated from your main shell. Within this environment, <code>set -euxo pipefail</code> does what we want and doesn&#8217;t make the front fall off. The result:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">INPUT &gt;&gt;&gt; rtdb
+ psql -h localhost -p 5432 -U evan -d dev-database</code></pre>
</div>
</div>
<div class="paragraph">
<p>It gives me a sense of calm to see the fully-constructed commands spelled out right after invoking the short alias version. It&#8217;s a constant reassurance in an otherwise chaotic, complex mental environment&#8201;&#8212;&#8201;<em>Everything is working as intended, and all this nuance will be easy to reference if you need it, just a few finger-twerks away</em>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Worth noting that sometimes <code>set -euxo pipefail</code> doesn&#8217;t make sense, for instance when <code>source</code>-ing other files with the function, which will cause a large amount of output to be printed. This is why I left it off of the <code>srt</code> function above. Right tool &#8594; right job and all that.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="company-specific-path-additions">Company-specific $PATH additions</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="title"><em>~/.bash_risingteam</em></div>
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh"># make `rt` command universally available:
export PATH="$PATH:$HOME/risingteam/scripts"</code></pre>
</div>
</div>
<div class="paragraph">
<p>Rising Team has a toolbox of their own, in the form of an <code>rt</code> script which lives at the root of the main repository. This adds that command to my <code>$PATH</code>, so calling <code>rt</code> from anywhere can provide access to the Rising Team library of commands.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="development-server-management-persistence">Development Server Management + Persistence</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="title"><em>~/.bash_risingteam</em></div>
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">function rts() ( set -euxo pipefail
  local backend="cd ~/risingteam; pipenv run ./scripts/rt server dev"
  local frontend="cd ~/risingteam/frontend; npm start"
  tmex risingteam --reattach -p "${backend}" "${frontend}"
)</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here&#8217;s a demo of <code>rts</code> in action: <a href="https://asciinema.org/a/501703" class="bare">https://asciinema.org/a/501703</a></p>
</div>
<div class="paragraph">
<p><code>rts</code> is a little dev-server wrangler, which every single project I work on seems to end up calling for. It starts two servers&#8201;&#8212;&#8201;backend and frontend&#8201;&#8212;&#8201;in side-by-side <a href="https://tmuxguide.readthedocs.io/">tmux</a> panes. The 2-in-1 aspect isn&#8217;t even the main draw here&#8201;&#8212;&#8201;once this command is run, the server session can be easily closed and the servers will keep running in the background. Combining the two commands into one view just reduces the number of things to think about, things that can go wrong out of sight. Running <code>rts</code> ("rising team server") again at any later point will re-attach to the same session, without restarting anything.</p>
</div>
<div class="paragraph">
<p>This all works with brevity, thanks to a small tool I created a few years back called <a href="https://www.npmjs.com/package/tmex">tmex</a> <code>npm install -g tmex</code>. All <a href="https://www.npmjs.com/package/tmex">tmex</a> does is transform a series of commands (frontend and backend server commands, in this case) into a much more convoluted <a href="https://tmuxguide.readthedocs.io/">tmux</a> incantation, and executes it&#8201;&#8212;&#8201;the same effect could be accomplished easily through <a href="https://tmuxguide.readthedocs.io/">tmux</a> directly (or if that&#8217;s not your cup of tea, <a href="https://www.gnu.org/software/screen/">GNU Screen</a>). However, as number of commands grows the <a href="https://tmuxguide.readthedocs.io/">tmux</a> syntax quickly becomes unwieldy; with <a href="https://www.npmjs.com/package/tmex">tmex</a> (a minimalist but fully-fledged layout manager in and of itself) arranging an entire dashboard of commands becomes trivial.</p>
</div>
<div class="listingblock">
<div class="title"><em>~/.bash_risingteam</em></div>
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">function rtk() ( set -euxo pipefail
  tmux kill-session -t risingteam
)</code></pre>
</div>
</div>
<div class="paragraph">
<p>And here&#8217;s the darker side, <code>rtk</code> ("rising team kill"). This command cleanly shuts down the <a href="https://tmuxguide.readthedocs.io/">tmux</a> session started by the one above, so that a subsequent <code>rts</code> may start fresh.</p>
</div>
</div>
</div>
<h1 id="automate-everything" class="sect0">Automate Everything</h1>
<div class="listingblock">
<div class="title"><em>~/.bash_risingteam</em></div>
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">function rtreset() ( set -euxo pipefail
  rtk &amp;&gt;/dev/null &amp;&amp; true
  cd "$HOME/risingteam"
  ./scripts/rt data reset || ./scripts/rt data init
  echo "Enter a password for local risingteam admin user:"
  ./scripts/rt manage rt_createsuperuser --email evan@risingteam.com
  for name in "session_admin" "demo_mode"; do
    rtdb "INSERT INTO waffle_flag (name, superusers, staff, authenticated, testing, rollout, note, languages, created, modified) VALUES ('${name}', TRUE, FALSE, FALSE, FALSE, FALSE, '', '', NOW(), NOW())"
  done
  sleep 10 &amp;&amp; open "http://local.rtkit.test:3006/auth/login?next=/get-started/sub/monthly/1" &amp;
  rts
)</code></pre>
</div>
</div>
<div class="paragraph">
<p>For the grand finale, a grand reset-the-world. I find that the ability to obliterate my local dev database from orbit and set up a brand-spanking new one usually tends to obliterate stress as well&#8201;&#8212;&#8201;no more worrying about clawing my way out of a badly-applied migration, only to find out some errant app code was up to no good in the meantime, etc. etc. The usual problem is that this is far from a one-button process, so I&#8217;ll frequently have a command which automates as much as possible. The above:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>kills any servers I have running via <code>rtk</code>:</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>rtk &amp;&gt;/dev/null &amp;&amp; true</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p>ensures we&#8217;re in the proper directory:</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>cd "$HOME/risingteam"</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p>database go 💥, and a fresh one is created:</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>./scripts/rt data reset || ./scripts/rt data init</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p>tells me to enter a password (in a moment):</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>echo "Enter a password for local risingteam admin user:"</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p>runs a pre-existing script which creates a new admin user, accepting said password:</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>./scripts/rt manage rt_createsuperuser --email <a href="mailto:evan@risingteam.com">evan@risingteam.com</a></code></p>
</div>
<div class="ulist">
<ul>
<li>
<p>inserts a couple of necessary admin feature flag records into the new database:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">for name in "session_admin" "demo_mode"; do
  rtdb "INSERT INTO waffle_flag (name, superusers, staff, authenticated, testing, rollout, note, languages, created, modified) VALUES ('${name}', TRUE, FALSE, FALSE, FALSE, FALSE, '', '', NOW(), NOW())"
done</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>in the background (triggered by <code>&amp;</code> at the end), waits 10 seconds and then opens a browser to the local signup page so I can finish setting up the user:</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>sleep 10 &amp;&amp; open "http://local.rtkit.test:3006/auth/login?next=/get-started/sub/monthly/1" &amp;</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p>concurrently, starts all servers with <code>rts</code> so the above is possible:</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>rts</code></p>
</div>
<hr>
<div class="paragraph">
<p>There you have it: the first few contraptions in my own handmade toolbox. I&#8217;d love to hear about yours&#8201;&#8212;&#8201;keep on building ⚒</p>
</div>]]></content><author><name>Evan Purcer</name></author><summary type="html"><![CDATA[We each have our own methods that operate behind-the-scenes while we engage in the process of software development. I like to think of this as the "craft." A woodworker hand-shapes chisels, constructs planers custom-fit to their own hands. A painter thoughtfully composes their pallet and designs a color-mixing strategy that suits their visual style.]]></summary></entry><entry><title type="html">The Most Underrated JavaScript Array Method</title><link href="blog.e2.gg/the-most-underrated-javascript-array-method" rel="alternate" type="text/html" title="The Most Underrated JavaScript Array Method" /><published>2021-11-26T00:00:00-08:00</published><updated>2021-11-26T00:00:00-08:00</updated><id>blog.e2.gg/the-most-underrated-javascript-array-method</id><content type="html" xml:base="blog.e2.gg/the-most-underrated-javascript-array-method"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes"><code>Array.prototype.includes</code></a> ? The ever-headscratch-inducing <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce"><code>.reduce</code></a> ? The extra-fancy  &nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap"><code>.flatMap</code></a> ? JavaScript Arrays have become veritable swiss-army knives in the age of ES6 / ES9 / ES2021 / <a href="https://babeljs.io/">babel</a>-thank-god-we-don&#8217;t-have-to-think-about-this, with browser support catching up faster than ever and polyfills abound when you need them. But I&#8217;d wager there&#8217;s one humble Array method that would get daily, nay <em>hourly</em> use by any dev wrangling indices and items under the sun, if only its true personality was understood.</p>
</div>
<div class="paragraph">
<p>That method is the unassuming <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a>.</p>
</div>
<div class="paragraph">
<p>No prototypes here folks&#8201;&#8212;&#8201;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> harkens straight from the Class itself. It&#8217;s cat-in-balloon-factory <a href="https://developer.mozilla.org/en-US/docs/Glossary/Static_method">static</a>.</p>
</div>
<div class="paragraph">
<p>This means you can use it <em>without</em> an existing array, on things that aren&#8217;t arrays at all. As such, it effectively grants you a superpower&#8201;&#8212;&#8201;the ability to use the entire menagerie of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> methods on <em>any object you want</em>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Yes, JavaScript being JavaScript, you can actually just call Array methods on any rando object (or function, dog, cat, another method, anything, 24/7). Since JavaScript lets us grab methods directly from any object&#8217;s <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">prototype</a> and specify what <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this"><code>this</code></a> context should be used while that method executes, if you know the right incantations it&#8217;s a literal free-for-all. I&#8217;ve always been leery of this practice&#8201;&#8212;&#8201;yes you&#8217;re explicitly setting <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this"><code>this</code></a> during method execution to whatever non-Array thing, but you have absolutely zero guarantees that the method&#8217;s internals expect and operate well with whatever object you decide to give it (and that they will continue to operate well across thousands of browser versions, in perpetuity). I think it would be fair to say calls like <code>Array.prototype.filter.call(myArrayLikeObj, (item) &#8658; { &#8230;&#8203; })</code> are hacks that should be avoided if possible&#8201;&#8212;&#8201;the approach I&#8217;d like to describe in this post is an alternative that sticks firmly within the realm of standard language tools.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Why might you want to use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> methods on non- <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> objects? It&#8217;s not always (or often) a good idea; <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter"><code>Array.filter</code></a> on a plain ol' object make code go boom. But it&#8217;s occasionally essential&#8201;&#8212;&#8201;one example happens to be extremely common when negotiating with browser APIs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const paragraphs = document.querySelectorAll("p");
const paragraphsAboutCats = paragraphs.filter((p) =&gt; p.innerHTML.includes("cat"));

OUTPUT &gt;&gt;&gt; Uncaught TypeError: paragraphs.filter is not a function</code></pre>
</div>
</div>
<div class="paragraph">
<p><em>Damn the torpedoes,</em> you might say to yourself; <em>give me those blasted cats!</em> And the browser would ignore you, belligerently erroring despite the fact you <em>know</em> you have a list of items in hand. Unfortunately, you don&#8217;t have an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a>, a sad fact that JavaScript makes very unclear&#8201;&#8212;&#8201;you have what&#8217;s known as a <a href="https://developer.mozilla.org/en-US/docs/Web/API/NodeList"><code>NodeList</code></a>, that just so happens to <em>not</em> support any of the standard methods you know and love. Enter: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const paragraphs = document.querySelectorAll("p");
const paragraphsAboutCats = Array.from(paragraphs)
  .filter((p) =&gt; p.innerHTML.includes("cat"));

OUTPUT &gt;&gt;&gt; [&lt;p&gt;The &lt;code&gt;concat()&lt;/code&gt; method is used to merge...  🎉</code></pre>
</div>
</div>
<div class="paragraph">
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> cleverly transforms the rogue <a href="https://developer.mozilla.org/en-US/docs/Web/API/NodeList"><code>NodeList</code></a> into a familiar <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a>. Balance is restored, and you can move on to more interesting problems such as a feline-informed naming scheme for your conference rooms.</p>
</div>
<div class="paragraph">
<p>Before you do though, if you happen to be up on the latest ES6 trends you might have a bone to pick. Isn&#8217;t there built-in syntax to accomplish the exact same thing? That is, transform any <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#iterators">iterable</a> object into a bonafide JavaScript <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a>?</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const paragraphs = document.querySelectorAll("p");
const paragraphsAboutCats = [...paragraphs].filter((p) =&gt; p.innerHTML.includes("cat"));

OUTPUT &gt;&gt;&gt; [&lt;p&gt;The &lt;code&gt;concat()&lt;/code&gt; method is used to merge...  🎉</code></pre>
</div>
</div>
<div class="paragraph">
<p>Indeed there is, and it&#8217;s a cool seven characters more concise. But while <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spread syntax</a> may get you an in with the hottest frontend developer clique at the next standup, I&#8217;d like to illuminate a few qualities of
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> that might just convince you to raise it as one of your own.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="array-from-is-descriptive">Array.from is descriptive</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>[&#8230;&#8203;paragraphs]</code> syntax is clear as day, said no one ever. It&#8217;s what we call an "idiom" in the biz, something that "looks weird at first, but you&#8217;ll get used to it." Don&#8217;t get me wrong, idioms and idiomatic code are great; but a requirement for obtuse syntax isn&#8217;t what makes them so&#8201;&#8212;&#8201;it&#8217;s their reinforcement of consistent, recognisable patterns across codebases and teams.</p>
</div>
<div class="paragraph">
<p>It&#8217;s a tricky balance&#8201;&#8212;&#8201;some idioms, while mysterious to newcomers, allow code to become more <em>expressive</em> when used well. It&#8217;s a judgement call you&#8217;ll constantly have to make; I&#8217;d personally put <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_object_literals">object spread</a> in this category over <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign"><code>Object.assign</code></a>; similarily I&#8217;d prefer <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_array_literals">array spread</a> over <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">slicing and dicing</a>. But in the case of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a>, it&#8217;s a one-for-one switcheroo to use the more "descriptive" version, and array spread doesn&#8217;t save you anything apart from a couple keypresses. Let <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> become the new idiom for copying arrays and converting iterable objects.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="array-from-is-searchable">Array.from is searchable</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Try Googling <code>[&#8230;&#8203;paragraphs]</code> as a budding developer fresh onto the inhospitable landscape of cross-browser industrial-grade JavaScripting, and you&#8217;ll hear the collective laughter of 1000s of search engineers at once, then silence.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/images/thanks-google.png" alt="Thanks Google&#8230;&#8203;">
</div>
</div>
<div class="paragraph">
<p><a href="https://www.google.com/search?q=%5B&#8230;&#8203;array%5D+javascript"><em>Thanks Google&#8230;&#8203;</em></a></p>
</div>
<div class="paragraph">
<p>Let&#8217;s try <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a>&#8201;&#8212;&#8201;longer yes, but the exact same functionality, <em>and</em> it&#8217;s searchable:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/images/actually-thanks-google.png" alt="Actually thanks Google&#8230;&#8203;">
</div>
</div>
<div class="paragraph">
<p><a href="https://www.google.com/search?q=Array.from"><em>Actually thanks Google&#8230;&#8203;</em></a></p>
</div>
<div class="paragraph">
<p>Your interns will thank you.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="array-from-can-map-more-efficiently-than-array-map-in-some-cases">Array.from can map more efficiently than Array.map! (in some cases)</h2>
<div class="sectionbody">
<div class="paragraph">
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> has a trick up its sleeve. It supports an optional second parameter&#8201;&#8212;&#8201;a so-called "map function"&#8201;&#8212;&#8201;which allows converting/copying an array <em>and</em> transforming its items in a single operation, <strong>without making any intermediate copies of the array in memory to do so.</strong> Consider this very-contrived cat-transforming JavaScript:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">function capCats(catElements) {
  return Array.from(catElements).map((p) =&gt; {
    return p.innerHTML.replaceAll("cat", "CAT");
  });
}

console.log(capCats(paragraphsAboutCats));

OUTPUT &gt;&gt;&gt; [&lt;p&gt;The &lt;code&gt;conCAT()&lt;/code&gt; method is used to merge...</code></pre>
</div>
</div>
<div class="paragraph">
<p>As we now know, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> can be used effectively on the <code>catElements</code> object even though it is <em>not</em> an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a>; it is a <a href="https://developer.mozilla.org/en-US/docs/Web/API/NodeList"><code>NodeList</code></a>. We make this conversion so that we can invoke the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"><code>Array.map</code></a> method on <code>catElements</code>, a handy tool for cat-transformation (or anything else). This method does not exist on <a href="https://developer.mozilla.org/en-US/docs/Web/API/NodeList"><code>NodeList</code></a>.</p>
</div>
<div class="paragraph">
<p>However, there is a wasteful redundancy in this series of steps. <code>Array.from(catElements)</code> creates an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> copy of the <code>catElements</code> list, but <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"><code>Array.map</code></a> <em>also</em> creates a copy of the array it takes as input. There&#8217;s an intermediate copy created in memory here that we don&#8217;t need&#8201;&#8212;&#8201;the real-world performance impacts will usually be negligible, but array data structures always have potential to become large, garbage collection behavior is ever-unpredictable. If a terser form of an idiom exists that <em>also</em> acts as an optimization, shouldn&#8217;t we pounce on it?</p>
</div>
<div class="paragraph">
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> cheekily provides just such an optimization. Our feline-finagler can be easily re-written to utilize it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">function capCats(catElements) {
  return Array.from(catElements, (p) =&gt; {
    return p.innerHTML.replaceAll("cat", "CAT");
  });
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> converts, copies, and maps, all in one. What&#8217;s not to love?</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="one-caveat">One Caveat</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Ok, there is one tiny, insignificant, miniscule, nagging aspect not to love&#8201;&#8212;&#8201;the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> "map function" doesn&#8217;t have the <em>exact</em> same signature as <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"><code>Array.map</code></a>'s transformer function. Mozilla&#8217;s <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#description">ever-excellent</a> documentation on the subject describes the relationship well:</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>More clearly, <code>Array.from(obj, mapFn, thisArg)</code> has the same result as <code>Array.from(obj).map(mapFn, thisArg)</code>, except that it does not create an intermediate array, and <code>mapFn</code> only receives two arguments <code>(element, index)</code>.</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>This is in contrast to <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"><code>Array.map</code></a>'s handler, which receives <em>three</em> arguments&#8201;&#8212;&#8201;<code>(element, index, array)</code>&#8201;&#8212;&#8201;the third is a reference to the full array being mapped over.</p>
</div>
<div class="paragraph">
<p>In practice, this enigmatic third arg is rarely used&#8201;&#8212;&#8201;you generally have a reference to the full array already when you map it. As always, pick the tools for the job that result in the clearest code; in cases where you need to reference the full array during map operations, <code>Array.from(arr).map(&#8230;&#8203;</code> sequences may end up enhancing clarity in ways that feel worthwhile. The rest of the time, don&#8217;t let this small difference dampen your enthusiasm for <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a>&#8201;&#8212;&#8201;we all have to be different somehow.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="bonus-round">Bonus round</h2>
<div class="sectionbody">
<div class="paragraph">
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> pairs beautifully with the semi-regular chore of generating a random hex string in JavaScript. I recently needed to conjure Sentry "trace IDs" from the void according to <a href="https://develop.sentry.dev/sdk/performance/#header-sentry-trace">this spec</a>, and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> provided an opportunity to convert the following function (courtesy of the internet) into something more elegant:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">function generateRandomHexString(len) {
  const bytes = crypto.getRandomValues(new Uint8Array(Math.ceil(len / 2)));
  const array = Array.from(bytes);
  // convert bytes to strings, pad leading zeros if necessary:
  const hexPairs = array.map((b) =&gt; ("00" + b.tostring(16)).slice(-2));
  return hexPairs.join("").slice(0, len);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><a href="https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues"><code>crypto.getRandomValues</code></a> returns a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array"><code>Uint16Array</code></a> here, which <em>must</em> be converted into a standard <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> before we <code>.map(b &#8658; b.toString(16).padStart(2, '0'))</code> over it to convert bytes to string chars&#8201;&#8212;&#8201;without the conversion, the result will be in decimal, not hex!</p>
</div>
<div class="paragraph">
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> allows us to perform this conversion and mapping in a single step, <em>without any intermediate array copies made</em> (making the mem footprint here N*3&#8201;&#8212;&#8201;the original <code>Uint16Array</code> array, the standard <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> copy which we <code>map</code> over, and the returned string):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">function generateRandomHexString(len) {
  const bytes = crypto.getRandomValues(new Uint8Array(Math.ceil(len / 2)));
  // convert bytes to strings, pad leading zeros if necessary:
  return Array.from(bytes, (b) =&gt; ("00" + b.tostring(16)).slice(-2))
    .splice(0, len) // for odd len values, need to trim the last char
    .join("");      // splice to modify array in-place and avoid copying
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Pre-mature optimization should be avoided, but on the other hand we should celebrate tools that allow us to easily write more efficient code by default!</p>
</div>
<div class="paragraph">
<p>Sometimes we might want to provide a fallback for older browsers, where <a href="https://developer.mozilla.org/en-US/docs/Web/API/Crypto"><code>crypto</code></a> is not yet available. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> comes to the rescue once again, helping us trivially write a version based on <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random"><code>Math.random</code></a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">function generateRandomHexString(len) {
  return Array.from({ length: len }, () =&gt;
    Math.floor(Math.random() * 16).toString(16)
  ).join("");
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Usage here is a bit of a hack, but allows us to construct the entire char array <em>without any extraneous array copies whatsoever</em>. By telling <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> to operate on <em>some</em> object with <code>length: len</code>, we can convince it to execute its mapping function <code>len</code> times, giving us exactly the number of chars we need. The usually-seen approach would be <code>new Array(len).fill().map(() &#8658; &#8230;&#8203;)</code>, but this constructs an array and immediately copies it needlessly via <code>map</code> (and it&#8217;s just a lot of parentheses). I&#8217;ll take mild <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> hacks any day.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
You might be wondering what the practical difference is between these two approaches&#8201;&#8212;&#8201;if they both produce the same result why do we need the esoteric <code>crypto.getRandomValues</code> at all? The short answer is: <code>Math.random</code> uses an inferior Random Number Generator (RNG) which can only be considered "psuedo-random", and would <em>never</em> be considered "cryptographically secure," but it&#8217;s also somewhat faster (albeit less than expected, only ~3o% &#8201;&#8212;&#8201; see <a href="https://jsbench.me/unkxtaccg9">this benchmark</a> for up-to-date results running on your browser of choice). Read into these quoted terms at your own discretion, and <a href="https://security.stackexchange.com/questions/181580/why-is-math-random-not-designed-to-be-cryptographically-secure">look here</a> for a far more in-depth analysis. At the end of the day <code>Math.random</code> may be entirely sufficient for your use case &#8201;&#8212;&#8201; use the right tool for the job at hand.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>All together, we could construct a robust, vintage-browser-capable version of <code>generateRandomHexString</code> like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">function generateRandomHexString(len) {
  if (typeof crypto === "object" &amp;&amp; typeof crypto.getRandomValues === "function") {
    var bytes = crypto.getRandomValues(new Uint8Array(Math.ceil(len / 2)));
    // convert bytes to strings, pad leading zeros if necessary:
    return Array.from(bytes, function (b) {
      return ("00" + b.toString(16)).slice(-2);
    })
      .splice(0, len) // for odd len values, need to trim the last char
      .join("");      // splice to modify array in-place and avoid copying
  } else {
    // if crypto.getRandomValues not supported, fall back to Math.random:
    return Array.from({ length: len }, function () {
      return Math.floor(Math.random() * 16).toString(16);
    }).join("");
  }
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="in-closing">In closing</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To those who give <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"><code>Array.from</code></a> the respect and mileage it deserves, I salute you.</p>
</div>
</div>
</div>]]></content><author><name>Evan Purcer</name></author><summary type="html"><![CDATA[Array.prototype.includes ? The ever-headscratch-inducing .reduce ? The extra-fancy &nbsp;.flatMap ? JavaScript Arrays have become veritable swiss-army knives in the age of ES6 / ES9 / ES2021 / babel-thank-god-we-don&#8217;t-have-to-think-about-this, with browser support catching up faster than ever and polyfills abound when you need them. But I&#8217;d wager there&#8217;s one humble Array method that would get daily, nay hourly use by any dev wrangling indices and items under the sun, if only its true personality was understood.]]></summary></entry><entry><title type="html">A Toolkit for Design Docs</title><link href="blog.e2.gg/Technical-Doc-Toolkit" rel="alternate" type="text/html" title="A Toolkit for Design Docs" /><published>2021-04-09T00:00:00-07:00</published><updated>2021-04-09T00:00:00-07:00</updated><id>blog.e2.gg/Technical-Doc-Toolkit</id><content type="html" xml:base="blog.e2.gg/Technical-Doc-Toolkit"><![CDATA[<h1 id="a-toolkit-for-design-docs">A Toolkit for Design Docs</h1>
<p>As I have (somewhat unexpectedly) been drawn into the world of management, one of my favourite parts of the job has been mentoring and uplifting then engineers in my organization. One of the most critical parts of that process is the fitting of incrementally more ambitious and open-ended projects to devs at each step of their learning curve, and the most important part of <em>that</em>, in terms of ensuring their success, is act of writing effective design documents for their projects.</p>

<p>This isn’t a post about why design docs are fundamentally critical to the design of good software (Joel Spolsky <a href="https://www.joelonsoftware.com/2000/10/02/painless-functional-specifications-part-1-why-bother/">articulated that more effectively than I ever will</a>, as have, honestly, <a href="https://www.industrialempathy.com/posts/design-docs-at-google/">many</a>, <a href="">many</a> others) but it is worth noting that single most common root cause of failure that I’ve seen hamstring projects, particularly those run by more junior engineers, has been inadequately thorough design documents. This is the singular moment during which more senior engineers can scrutinize each element of the design, particularly the nasty and easy to miss failure cases, in the context of the whole (other than, of course, after the project launches and things start breaking). However, the exercise of communicating technical intent, complete and unambiguous, is a new and foreign challenge of its own - and even just getting started can be a daunting task to someone writing their first design doc.</p>

<p>So instead this is a post about what you need to get started writing your first (or your hundredth) design doc, in as brief and functional terms as is possible. With the following, I hope to provide all the structure and tooling you need to create something comprehensive for review from your peers, as well as offering a few tips and tricks to keep in mind as you fill out the format along the way.</p>

<h1 id="structure">Structure</h1>
<p>There’s nothing more intimidating, as a writer, than a blank sheet of paper - where do I even <em>start</em>? To that end, for any informative documents I’m required to produce, I start with all the sections and headers I can identify, and turn the problem from “filling out the page” into (as much as is possible) “filling in the blanks.” Although the following may not quite be universal - you shouldn’t shy away from altering it to fit your domain - I find that generally starting with this format gives me enough structure to start breaking down the document into smaller problems to digest.</p>

<ol>
  <li><strong>Overview</strong>
    <ol>
      <li><strong>Stakeholders/key personnel</strong> - Start off with who are you (author), who owns the thing you’re building (teams), and who cares about it (key stakeholders). Although this may be unnecessary in some smaller docs, for a broader audience it really helps the folks asking questions if they know who they’re talking to.</li>
      <li><strong>Background</strong> - This is where you start the narrative. It’s always important to think about how the content of your document flows from section to section, each conveying unique information that supports the conclusions that follow, and this is where you can lay your groundwork for your readers’ comprehension of that narrative. Keep it short, this isn’t the time to justify all the specifics of your solution, but set the stage with the impetus for the feature, and any requisite technological context.</li>
      <li><strong>Essential terminology</strong> - Although there’s a good chance you can skip this section, take a moment and consider - are there any terms that are specific to this domain that your readers are unlikely to know, or are you introducing novel terminology for the purposes of your solution? I’ve seen countless technical discussions spiral into frustration because speaking unambiguously in english is actually <em>really hard</em>, and anything you can do to preempt potential confusion will save you effort down the line.</li>
      <li><strong>Objectives</strong>
        <ol>
          <li><strong>Goals</strong> - What are you going to accomplish?</li>
          <li><strong>Non-goals</strong> - What are you <em>not</em> trying to accomplish? Don’t put world peace. Many projects have intuitable extensions, or adjacent problem domains that you may be pushed towards rolling into scope. Push back - be clear regarding your boundaries (in documentation as in life).</li>
        </ol>
      </li>
    </ol>
  </li>
  <li><strong>Technical Summary</strong>
    <ol>
      <li><strong>General Overview</strong> - Explain the logic and flow of your solution in two to three paragraphs, or if you’re feeling ambitious, five or six bullet points.</li>
      <li><strong>System Diagrams</strong> - At least a broad system overview, with diagrams for key subsystems as necessary, with complimentary notes providing context as necessary.</li>
      <li><strong>Key Components</strong> - Using a new AWS offering? Have a really complicated class heirarchy that’s central to the solution? Offering a new API to internal clients? Enumerate them here.</li>
    </ol>
  </li>
  <li><strong>Technical Flows</strong> - This is a chance to explain how what you’re building will be used. Whether it’s a library, an API, or elsewise, understanding it through its flows rather than it’s atomic points of interaction is a much more informative lens for critiquing the design. Sequence diagrams are immensely useful here, and I’d strongly recommend getting familiar with them for anyone who writes client-facing code (more on them later).</li>
  <li><strong>Contracts/API</strong> - Okay, so now that we understand the flows, what exactly are our points of contact? The prior segment should have had most of these listed by name, and now that the reader understands how they’ll be used you can step through and give more detail on specific arguments, return values, and encapsulated business logic.</li>
  <li><strong>Persistence</strong> -  Are you storing data? Great, now let’s get into the details. How is that data modelled? How is it indexed? Is it scalable, and is it flexible enough to support future use cases? Bad modelling at the persistence level often causes problems down the road - particularly for the <em>second</em> version of a feature as you expand beyond the tightly scoped initial problem domain, so making sure the constraints of your design are well understood at the outset can be enormously valuable.</li>
  <li><strong>Observability</strong>
    <ol>
      <li><strong>Metrics</strong> - What are you counting?</li>
      <li><strong>Monitors</strong> - What are you analyzing?</li>
      <li><strong>Alerts</strong> - What do you want to respond to?</li>
    </ol>
  </li>
  <li><strong>Risks and Risk Mitigation</strong> - Where could this project go off the rails? What business outcomes or technology constraints might result in failure cases? What might extend the timeline beyond your current estimates for delivery?</li>
  <li><strong>Deployment/Rollout Strategy</strong> - “Turning it on” is another common point of failure for new features. Particularly if your project is a new/alternative flow or resource, ensuring that that any ramp up is smooth and well monitored is essential. How to manage deployments is the subject of another post, but at a minimum cover timelines, rollback plans, backwards compatibility, monitors to track during deployment, and metrics to be used as success criteria.</li>
  <li><strong>Appendix</strong> - At this point you’ve covered your bases! Long form references, or content that isn’t strictly necessary to the pitch but may be useful to a curious reader can be plugged into an appendix, making it clear that this isn’t part of the body of the proposal. You can drop basically anything in here, but a few likely entries follow:
    <ol>
      <li><strong>Alternatives</strong> - Are there other strategies that are still worth considering, or that you want to justify in their exclusion?</li>
      <li><strong>Required Sign-offs</strong>  - In some cases explicit sign off from a set of technical partners (for inter-service contributions, for example) may be useful to have on paper. Drop it in here!</li>
      <li><strong>Follow-on projects</strong> - Where are you taking this project post-MVP?</li>
      <li><strong>Specific scope exclusions</strong> - Any potential expansions on the non-Goals as listed above.</li>
      <li><strong>Dependencies</strong> - Projects being executed in parallel, requirements of non technical partners, really anything that may block the project from proceeding.</li>
    </ol>
  </li>
</ol>

<h1 id="tools">Tools</h1>
<p>Of course, not everything you’ll be sticking in that doc will raw text - it’s helpful to have diagrams and tables to present specific structured information, and so I’ve highlighted a few of the most lightweight and useful tools I’ve come to appreciate in my time producing design docs.</p>

<h2 id="authorship">Authorship</h2>
<p>Where do you actually write the doc? Honestly, “wherever you’re most comfortable” is a good place to start, and the first few hours should mostly be spent dumping as many ideas as possible out of your head and into their respective sections in preparation for organization and editing. That said, once you’ve got a semi-mature draft I strongly recommend finding a buddy, copying the content into a collaborative editor like <a href="https://docs.new">google docs</a>, and soliciting feedback as early as possible. You don’t have to have every potential question answered and every spelling eror fixed before you start getting criticism, and it’ll save you having to make larger changes when your document is more complete. Is this obvious? Sure. Have most people put off reaching out to peers in favour of adding a <em>little</em> more polish first, to their net detriment? Absolutely.</p>

<h2 id="system-diagrams">System diagrams</h2>
<p>A high level system overview is near essential for any system describing more than one client and one server. Although you can get by with just Google Draw (or, for that matter, MS Paint), there are better solutions out there. <a href="https://www.diagrams.net/">Diagrams.net</a> is free, easy to use (many of the tools in this space are far more complicated than necessary for the general case), and produces diagrams that aren’t an eyesore. If you don’t want to think about what to use here (and you shouldn’t, generally, that’s not the problem you’re trying to solve), just use this. Technically this site addresses <em>almost</em> every use case listed here, but due to my preference for text-based diagramming tools (over wysiwyg), I’ll include more specialized tools in the following sections.</p>

<h2 id="sequence-diagrams">Sequence diagrams</h2>
<p>These are the bees knees, and criminally underused. Many technical specifications are most usefully understood through the the flow of data and the sequence of their use, but it can be hard to express these things in raw text without being so verbose as to obfuscate the key information. Sequence diagrams offer a flexible and fun way to render these flows, and in many cases can replace hundreds of words of text with a few easily understood images. I’ve been using <a href="https://www.websequencediagrams.com/">websequencediagrams.com</a> for years, and would strongly recommend them for their simplicity and clarity.</p>

<h2 id="entity-relationship-diagrams">Entity Relationship Diagrams</h2>
<p>Got a bunch of models, and those models are related to each other? Just like they hammered home in CS101, entity relationship diagrams are your friend. They’re simple and easy to read, so although they can be skipped over in more simply modelled domains, they’re an extremely efficient utility to have in your toolkit when necessary. <a href="https://playground.diagram.codes/">Diagram.codes</a> has a bevy of diagramming options, is well designed, and it’s ER syntax is particularly clear and simple.</p>

<h2 id="api-definitions">API definitions</h2>
<p>For long term documentation I think that APIs should almost <em>always</em> have their docs written inline with their method signatures and docs should be generated from there. However, before the API exists in code, tooling for expressing the contract you’ll be putting in place is a lot more sparse. Most popular options, like Swagger, are a little heavyweight for the brief and high-level definitions that might exist in a design doc, and I haven’t found any solutions that I’ve really loved. As such, I basically just copy and paste a rich-text version of this snippet, and now you can make your own too!</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>+--------------------+-----------------------------------------------------------------+
| Endpoint Name/Path                                                                   |
+--------------------+-----------------------------------------------------------------+
| Description        | A little about the endpoint, how it operates, and why it exists |
| Arguments:         | | Parameter | Type |            Description            |        |
|                    | | --------- | ---- | --------------------------------- |        |
|                    | |    id     |  int | the uuid of the referenced object |        |
| Response:          | Serialized response object                                      |
+--------------------+-----------------------------------------------------------------+
</code></pre></div></div>

<h1 id="techniques">Techniques</h1>
<p>So now you have a structure, a general sense of content, and a few handy tools for mocking up the diagrams that you may want to include - you’re pretty much good to go! Before you rush off though, I’d like to offer a few more points to consider as you draft your first (or fiftieth) design doc.</p>
<ul>
  <li>Good headers help set expectations for readers and break up your document into easily parsable components. Good formatting seems like a nicety that many developers see as unnecessary frivolity, but self explanatory headers with good visual distinction between h1/h2/h3/etc. make a huge difference for reader comprehension.</li>
  <li>Don’t just cover the happy path. Failure modes are an essential component of a design doc, and warrant equal emphasis along with the success cases.</li>
  <li>The design doc should <em>not</em> be a product doc. Linking to the product doc near the top is a great idea, but retreading product/business outcomes, unless the project is <em>strictly</em> technical (and even then you could pull those out into another doc), is often counterproductive because it invites debate on a tangential subject, rather than focusing attention on the technical design.</li>
  <li>Emphasize complex elements, and unique/novel (within your context) elements, leave explanations of common infrastructure out or note them only briefly.</li>
  <li>This is a long doc structure. It can feel unduly burdensome for smaller projects, and even for larger projects it’s easy for this to feel like busywork once the author feels they’ve fully internalized the solution. Again, I don’t want to litigate that these docs are valuable (they are), but if you <em>do</em> feel like this is too much - do less. Something is better than nothing. Skipping some sections in the name of velocity or flexibility or just in the name of saving your sanity after a long week, can be totally fine so long as the doc still covers the core design elements of your solution. Edit the format to fit your needs and your patience, but remember the more thorough the doc, the more detailed feedback you’ll get from your peers, and the more value it will return to the project.</li>
</ul>

<p>Finally, one last note before you go - this guide is intended to inform a formal proposal of a solution, which may be several docs deep in the design process already. You might write out a complete list of approaches to be debated, early on after identifying a problem space; you might throw together a one-pager outlining your preferred solution when you’re first seeking approval from your peers or boss to explore the direction; those are good an important, but should not be as exhaustive as the document outlined above. A design doc should assume an opinionated position regarding the correct solution, and justify that opinion through its thorough treatment of the problem space. If you’re not ready to tackle the design doc yet, that’s okay! Seek advice from peers or mentors, do a lightweight comparison of alternative solutions, and make clear to your stakeholders that you need a little more time - this is a big commitment! But when you <em>are</em> ready, I hope this guide helps make your experience of writing your design doc just a little bit easier.</p>]]></content><author><name>Evan Brynne</name></author><summary type="html"><![CDATA[A Toolkit for Design Docs As I have (somewhat unexpectedly) been drawn into the world of management, one of my favourite parts of the job has been mentoring and uplifting then engineers in my organization. One of the most critical parts of that process is the fitting of incrementally more ambitious and open-ended projects to devs at each step of their learning curve, and the most important part of that, in terms of ensuring their success, is act of writing effective design documents for their projects.]]></summary></entry><entry><title type="html">JavaScript Objects and Arrays are Broken</title><link href="blog.e2.gg/javascript-objects-and-arrays-are-broken" rel="alternate" type="text/html" title="JavaScript Objects and Arrays are Broken" /><published>2021-04-09T00:00:00-07:00</published><updated>2021-04-09T00:00:00-07:00</updated><id>blog.e2.gg/javascript-objects-and-arrays-are-broken</id><content type="html" xml:base="blog.e2.gg/javascript-objects-and-arrays-are-broken"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>JavaScript and TypeScript share a secret&#8201;&#8212;&#8201;their native <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><code>Object</code></a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> data structures, used the world over to represent key/value data, don&#8217;t work exactly as you&#8217;d expect. To understand why, and what sorts of subtle, maddening bugs you risk inflicting on your future self when using them dangerously, behold this simple example (even better&#8201;&#8212;&#8201;try running it yourself in the devtools of this browser tab):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const foo = { bar: "baz" };
OUTPUT &gt;&gt;&gt; undefined

if (foo["buzz"]) {
  console.log("This shoudn't print; `foo` has no value under `buzz`.");
}
// no output, so far so good...

const userProvidedKey = "constructor";
OUTPUT &gt;&gt;&gt; undefined

if (foo[userProvidedKey]) {
  console.log("There's more to `foo` than meets the eye...");
}
OUTPUT &gt;&gt;&gt; "There's more to `foo` than meets the eye..."
// output? why does `foo` have something other than `baz`?

if (foo["toString"]) {
  console.log("Objects, prototypes, constructors, oh my!");
}
OUTPUT &gt;&gt;&gt; "Objects, prototypes, constructors, oh my!"
// oh no, it seems to happen for some indeterminate set of keys...</code></pre>
</div>
</div>
<div class="paragraph">
<p>Why did our <code>if</code> statements think that <code>foo</code> contained these extra keys, when it was defined as simply <code>{ bar: "baz" }</code>? The answer lies in JavaScript&#8217;s "prototypical" inheritance system (not to say that JavaScript inheritance is in any way normal).</p>
</div>
<div class="paragraph">
<p>You may have heard: everything in JavaScript is an object. This sounds beautifully simple! It means everything you&#8217;re working with shares fundamental similarities&#8201;&#8212;&#8201;for instance, everything has a <code>constructor</code> method that&#8217;s called when it&#8217;s initialized; everything has a <code>toString</code> method that allows it to be easily converted to some string representation; and notably, everything has a <code>prototype</code>, where all methods such as these are stored. Really these prototypes are <em>chains</em>, shaping hierarchies that give form to "inheritance", more or less. This is where JavaScript objects get their <code>toString</code> method along with everything else&#8201;&#8212;&#8201;it&#8217;s defined near the very top of their prototype chain, in a grab-bag of methods shared by just about everything under the sun.</p>
</div>
<div class="paragraph">
<p>What&#8217;s important here is that everything has a "toString" method. That method is accessible in two different ways:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">foo.toString
OUTPUT &gt;&gt;&gt; ƒ toString() { [native code] }

foo["toString"]
OUTPUT &gt;&gt;&gt; ƒ toString() { [native code] }

foo.toString()
OUTPUT &gt;&gt;&gt; "[object Object]"

foo["toString"]()
OUTPUT &gt;&gt;&gt; "[object Object]"</code></pre>
</div>
</div>
<div class="paragraph">
<p>The former seems very usual; the latter, not so much. JavaScript was apocryphally written in 10 days, and on such a short timescale, axioms such as:
- <em>everything is an object</em> and
- <em>every attribute of an object may be accessible via dot-notation or square-bracket-notation</em>
start to sound very appealing&#8201;&#8212;&#8201;there&#8217;s an elegant or extreme form of simplicity there, depending on your predelictions. Either way, the design came with a bitter side-effect, with regard to sanely using JavaScript objects as key/value maps.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const fooArr = [1, 2, 3];
const userProvidedKey = "constructor";
const hasIndex = fooArr[userProvidedKey];
console.log(hasIndex);
OUTPUT &gt;&gt;&gt; true

// yes, arrays have the same quirkiness</code></pre>
</div>
</div>
<div class="paragraph">
<p>When might this become a problem? <em>I&#8217;d never use</em> <code>toString</code> <em>or</em> <code>constructor</code> <em>as an object key when writing a real program,</em> you might say to yourself.</p>
</div>
<div class="paragraph">
<p>It&#8217;s true, <em>you</em> might not. But your users have other ideas. In short, if you <em>ever</em> use user-provided data as keys on JavaScript (or TypeScript) objects or arrays, you&#8217;re subjecting yourself to risk of future bugs of this sort. This isn&#8217;t <em>that</em> common of a practice, but it&#8217;s often a hard one to identify in the midst of a complex application&#8201;&#8212;&#8201;it&#8217;s not always clear where the data that led to a given variable has come from. It&#8217;s an issue that takes developer discipline to avoid, and as teams get larger and developers get busy, discipline becomes lofty ambition more than general practice.</p>
</div>
<div class="paragraph">
<p>So what can we do? There are a few interesting options, each with trade offs and quirks. Let&#8217;s briefly compare them.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-map-approach">The Map Approach</h2>
<div class="sectionbody">
<div class="paragraph">
<p>One school of thought tells us that when trying to safely store and access key/value data, we should just use the tool designed for the job. This would be JavaScript&#8217;s built-in <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"><code>Map</code></a> object, available in all major browsers since ES6 (aka ES2015).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const fooMap = new Map(Object.entries({ bar: "baz" }));
fooMap.get("bar");
OUTPUT &gt;&gt;&gt; "baz"

fooMap.get("toString");
OUTPUT &gt;&gt;&gt; undefined    // hooray! actually the behavior we want</code></pre>
</div>
</div>
<div class="paragraph">
<p>This works perfectly&#8201;&#8212;&#8201;code that safely accesses <code>bar</code> could never unexpectedly access <code>toString</code> by mistake, thanks to Map&#8217;s get-based key access.</p>
</div>
<div class="paragraph">
<p>There are some glaring downsides though. For one, it&#8217;s awkward as a giraffe in a car wash. The <code>Object.entries</code> boilerplate is unpleasant, and the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"><code>Map</code></a> interface generally doesn&#8217;t lend itself well to declarative or immutable code patterns. How would one merge two Maps, for instance?</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const fooMap = new Map(Object.entries({ bar: "baz" }));
const barMap = new Map(Object.entries({ bizz: "buzz" }));
const mondoMap = new Map(fooMap.entries().concat(barMap.entries());</code></pre>
</div>
</div>
<div class="paragraph">
<p>Ouch. Not exactly elegant, especially sitting next to ES6&#8217;s object spread syntax:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const foo = { bar: "baz" };
const bar = { bizz: "buzz" };
const mondo = { ...foo, ...bar };</code></pre>
</div>
</div>
<div class="paragraph">
<p>"Plain Old JavaScript Objects" (POJOs, if you like weird acronyms) have especially come into favor lately as "reactive" UI frameworks (Vue, React, et. al.) have become the ligua franca of modern web development, completely eclipsing their MVC bretheren of yore. These frameworks rely on efficient tracking of state changes to determine exactly what parts of UI need to be re-rendered, exactly when.</p>
</div>
<div class="paragraph">
<p>Unfortunately, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"><code>Map</code></a> does not lend itself well to this. The fundamental issue is that changes to Maps happen <em>mutably</em>&#8201;&#8212;&#8201;you must "mutate" the data structure in order to change it, meaning you sneakily change a value deep within it. The alternative would be to construct a completely new version of your data structure, with the desired key/value set, and swap the old map out for the new one. This sounds roundabout, but bear with for a moment and consider this example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const myMap = new Map(Object.entries({ a: "b", c: "d" }));
// ... some code later ...
myMap.set("c", "z"); // "mutate" myMap
console.log(myMap.get("c"));
OUTPUT &gt;&gt;&gt; "z"

let myObj = { a: "b", c: "d" };
// ... some code later ...
myObj = { ...myObj, c: "z" }; // update myObj "immutably"
console.log(myObj.get("c"));
OUTPUT &gt;&gt;&gt; "z"</code></pre>
</div>
</div>
<div class="paragraph">
<p>This may not persuade on its own, but at least the code styles are roughly similar. You might think that the second example, with its superflouous copying of data, would be horribly inefficient compared to the first; in reality, running on modern JavaScript engines like V8, the performance differences will be negligible until data becomes massive. There are many tools built by incredibly clever people that make "immutable" data mangement efficient even in these cases&#8201;&#8212;&#8201;I&#8217;ll leave that exploration to other more-brilliant minds that have produced plenty of quality material on the subject.</p>
</div>
<div class="paragraph">
<p>When it comes to "reactive" web UI development, the bottleneck is not object copying; it&#8217;s DOM manipulation. What becomes important is identifying exactly what has changed, not reducing the number of operations required to make those changes. V8 eats objects <em>and</em> Maps for breakfast.</p>
</div>
<div class="paragraph">
<p>The problem then is that Maps provide no way of efficiently indicating that they have changed, in order to trigger a fine-grained re-render of relevant DOM. This is especially true when dealing with complex state object built of many layers. Consider this sort of check, for whether a peice of state has changed:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">if (newState.pethaus.dogs !== app.state.pethaus.dogs) {
  app.render(newState);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>!==</code> comparison operator compares object <em>references</em> in JavaScript and TypeScript, meaning that it will only result in <code>false</code> when used to compare two completely different and separate object instances. It&#8217;s an extremely fast check, operating with O(1) complexity&#8201;&#8212;&#8201;constant time as even as compared objects grow in size. In our "immutable" object update example above, this sort of efficient reference check works great. This is exactly why so many libraries in the vein of Redux have cropped up in recent years&#8201;&#8212;&#8201;libraries that actively discourage state mutation and rely on a set of immutable operations (<a href="https://redux.js.org/understanding/thinking-in-redux/glossary#reducer"><em>reducers</em></a> in Redux nomenclature). Immutable state management lends itself extremely well to the problem of keeping UIs up-to-date alongside complex state&#8201;&#8212;&#8201;and standard JavaScript objects paired with ES9&#8217;s <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spread syntax</a> lend _them_selves extremely well to the task of manipulating state in immutable fashion.</p>
</div>
<div class="paragraph">
<p>In contrast, Maps do not work well for this task. If <code>app.state.pethaus.dogs</code> were a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"><code>Map</code></a>, how would we tell if it had changed? Since <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set"><code>Map.set</code></a> mutates the Map&#8217;s internals in a way that is invisible to the outside, <code>newState.pethaus.dogs !== app.state.pethaus.dogs</code> would likely compare the same <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"><code>Map</code></a> instance to itself, uselessly. Or worse, we may have a copy of our original map that may or may not have changed, and the only way to tell would be an expensive enumeration + comparison of internal key/value pairs. If you&#8217;re dealing with nested state comprised of many layers of data, these would need to recursively crawled and compared as well&#8201;&#8212;&#8201;you can only be certain if two maps are <em>actually</em> different once every piece of data within them has been looked at (worst-case; you can of course exit early once you find differing datums, but on average you will have traversed half the map at this point, which might as well be all of it when talking about efficiency in relation to size of state data).</p>
</div>
<div class="paragraph">
<p>Overall, this is an extremely common set of problems in modern UI development of all kinds, since even outside of the web arena most frameworks seem to be evolving toward the "declarative" approach popularized by React (the value of which has become extremely clear in recent years; that&#8217;s a blog post for the masochistic historians of JS framework yore). Due to its reliance on immutable state management, declarative apps will never be able to effectively embrace such a mutation-centric data structure as <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"><code>Map</code></a>. For this reason alone, the idea of consistently using Maps for all dynamic-key data storage seems like a non-starter in most modern JavaScript and TypeScript contexts.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-object-createnull-approach">The Object.create(null) Approach</h2>
<div class="sectionbody">
<div class="paragraph">
<p>It&#8217;s been suggested from the highest echelons of StackOverflow that <code>Object.create(null)</code> might be a robust solution to our problem. Let&#8217;s give it a try:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const foo = Object.create(null);
foo.bar = "baz";
const userProvidedKey = "constructor";
if (foo[userProvidedKey]) {
  console.log("There's more to `foo` than meets the eye...");
}
OUTPUT &gt;&gt;&gt; undefined</code></pre>
</div>
</div>
<div class="paragraph">
<p>Lovely. <code>Object.create(null)</code> effectively creates a "prototypeless" object, meaning that none of the methods (<code>toString</code>, <code>constructor</code>) that come along with the standard JavaScript object prototype are present on our new object. Even <code>prototype</code> itself is missing, solving all three of our original example cases in which our object incorrectly reported a key/value pair being present. Blind trust in strange programmers online should tell us that any other problematic cases should be resolved as well.</p>
</div>
<div class="paragraph">
<p>Unfortunately, this to me seems a worse approach than <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"><code>Map</code></a>, will all the same downsides and even less clarity. You may have noticed that <code>foo.bar = "baz";</code> is the simplest form of <em>mutation</em> you can possibly make; this in itself disqualifies <code>Object.create(null)</code> for use as state data in modern UI applications. Worse, errant developers may forget to use <code>Object.create(null)</code> in dark corners of your codebase and there will be absolutely no way to tell within other code contexts where objects are accessed; in contrast to <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"><code>Map</code></a> where <code>thing1.get(dynamicKey); thing2["constKey"];</code> clearly demarcates <code>thing1</code> as a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"><code>Map</code></a> and <code>thing2</code> as a simple object. You will have no such luxury with <code>Object.create(null)</code>&#8201;&#8212;&#8201;even TypeScript won&#8217;t be able to help as it cannot distinguish between "prototypeless" objects and normal (broken) ones.</p>
</div>
<div class="paragraph">
<p>This is all a recipe for codebases that develop extremely subtle bugs over time, as developers are asked to adhere to code conventions whose intentions become murkier with each passing commit; with each addition of a new team member and departure of a more experienced one. As a general rule, safety should <em>never</em> be enforced through convention&#8201;&#8212;&#8201;there must be a better way.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-safekey-approach">The Safekey Approach</h2>
<div class="sectionbody">
<div class="paragraph">
<p>What we need is static analysis. We need a <em>mechanical</em> rather than social method of ensuring that no unsafe object access code makes it into our codebase. As it turns out, this is quite possible using a custom rule in a JavaScript (and TypeScript) code-quality analyzer known as <a href="https://github.com/eslint/eslint">eslint</a>. There is a tradeoff&#8201;&#8212;&#8201;some brevity of code is lost when accessing objects with dynamic keys. But apart from this minor sacrifice of convenience, we can have our cake and eat it too: we get to use <em>standard</em> JavaScript objects with all the ES6 spread syntax we want along with them, and we get to <em>know</em> concretely that there will never be instances of unsafe access covertly appearing in our codebase.</p>
</div>
<div class="paragraph">
<p>Instead, in dynamic-key-access cases we&#8217;ll use a "known-safe" form of getter that incorporates JavaScript&#8217;s <code>hasOwnProperty</code> to ensure no false-positive keys are retrieved. The end result would look something like this, in practice:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-javascript" data-lang="javascript">const foo = { bar: "baz" };
OUTPUT &gt;&gt;&gt; undefined

foo["bar"]; // this is OK per our eslint rule; key is constant
OUTPUT &gt;&gt;&gt; "baz"

const userProvidedKey = "constructor";
foo[userProvidedKey]; // this is NOT OK per our eslint rule; key is "dynamic"
OUTPUT &gt;&gt;&gt; ƒ Object() { [native code] }

// so instead, we'll use this equivalent-but-safe form:

import { get } from "safekey";
get(foo, "bar");
OUTPUT &gt;&gt;&gt; "baz"
get(foo, userProvidedKey);
OUTPUT &gt;&gt;&gt; undefined  // hooray, this is all we wanted in the first place</code></pre>
</div>
</div>
<div class="paragraph">
<p>The folks at <strong>e<sup>2</sup></strong> have codified this approach into a tiny library called <a href="https://www.npmjs.com/package/safekey">safekey</a>; if you&#8217;re interested in these issues with JavaScript and exploring mitigation techniques, give it a look. I&#8217;ll leave the details to the source&#8201;&#8212;&#8201;nothing speaks more clearly than a good README over a cup of ☕</p>
</div>
</div>
</div>]]></content><author><name>Evan Purcer</name></author><summary type="html"><![CDATA[JavaScript and TypeScript share a secret&#8201;&#8212;&#8201;their native Object and Array data structures, used the world over to represent key/value data, don&#8217;t work exactly as you&#8217;d expect. To understand why, and what sorts of subtle, maddening bugs you risk inflicting on your future self when using them dangerously, behold this simple example (even better&#8201;&#8212;&#8201;try running it yourself in the devtools of this browser tab):]]></summary></entry><entry><title type="html">Getting Started as a Distributed Worker</title><link href="blog.e2.gg/Getting-Started-as-a-Distributed-Worker" rel="alternate" type="text/html" title="Getting Started as a Distributed Worker" /><published>2020-05-15T17:34:27-07:00</published><updated>2020-05-15T17:34:27-07:00</updated><id>blog.e2.gg/Getting-Started-as-a-Distributed-Worker</id><content type="html" xml:base="blog.e2.gg/Getting-Started-as-a-Distributed-Worker"><![CDATA[<p>In amongst all the tragedy and trauma of our current circumstance, I find some solace in the newfound solidarity formed and felt in our communities—individuals of many disparate circumstances coming together and lending their expertise to support and uplift each other. I have felt the growth of the online community of workers particularly acutely, as thousands of Canadians bring their daily routines onto the internet and transition to being remote workers. This is a field in which I have some expertise; I have spent the last six years working from a home office for various companies, and many of the newfound frustrations of my friends and family trying out remote work for the first time are very familiar to me. As such I’d like to offer a few thoughts, to both give better definition to the problems we face, and also to offer a few solutions wherever I have some experience.</p>

<h2 id="working-from-home-working-distributed">Working from home, working distributed</h2>

<p>Although an exhaustive analysis is outside the scope of this document, I think it’s constructive to consider our new work circumstances in two dimensions rather than lumping it all together under “remote work.” First, we are now working from home: this means dealing with distractions, new challenges to our work life balance, and other largely environmental complications to our processes. Secondly, we are working distributed, newly remote from our peers and collaborators: this comes with issues of communication and organization, and of staying on top of information that used to be at our literal physical fingertips. I think by considering our new circumstances through this lens we can move beyond listicles of tips and tricks, and instead provide a framework for more deeply understanding our challenges at hand and finding solutions tailored to our individual needs.</p>

<h1 id="working-from-home">Working From Home</h1>

<p>Although I’m a fan of and advocate for the many advantages of working from home (notably, no corporate policies against your cat sleeping on your desk), I’m more than happy to acknowledge that it also comes with its fair share of challenges and drawbacks. The loss of enforced boundaries is a common frustration for people newly transitioning to working from home, and somehow it can be simultaneously challenging to avoid the distractions and temptations of the home while also frustrating to find ways to disengage from work and not let it bleed into the rest of your life. Similarly, those new to home offices will find themselves suddenly deprived of the many enriching aspects of office life (as strange as that may sound) that exist at the margins of work and that provide essential social and physical variety to our lives.</p>

<h2 id="boundaries-of-work">Boundaries of Work</h2>

<p>Boundaries are going to come in a few different forms but the first, and most obvious, category to address is physical boundaries. Not that you have to build up blockades to keep out your family, but a clear definition of where you work and where you don’t will give you great mileage for both defining to others when you’re in “work mode” and not to be distracted, and also for training your brain to reflexively understand the same and help you find that “flow” that’s so much easier in a dedicated collocated office. Again, maybe you don’t have a home office, or maybe not even a desk, but that doesn’t mean you can’t carve out a dedicated space for thinking and working. Maybe between 9am and 5pm the kitchen table is strictly off limits to non-workers, or maybe for the duration of staying at home you only sit in your comfiest chair when you’re working.</p>

<p>And that nicely brings us to barriers around time—if the table stops being an office at 5pm, then you have to leave that office and go back to real life. It’s so easy to just keep going when you don’t have to physically leave work behind, but by all appearances this is going to be much more of a marathon than a sprint, and making sure that you’re not accidentally burning yourself out is going to be critical to your long term health. The inverse also applies —you should be very cautious about allowing yourself to take on other tasks during your work hours, like tidying up around the house or taking time for video games (not that you shouldn’t at all, just that you should be conservative and deliberate in your choices). If you’re already struggling to remain focused, giving yourself more chances to feel more ‘at home’ rather than ‘at work’ will further cement your mentality of not being singularly focused the way you would be in an office.</p>

<p>Finally, social boundaries play a critical role as well. Those who aren’t working from home—but are home with you—are likely not going to immediately appreciate how important and how hard it is to keep a clear(ish) work-life divide. That doesn’t mean you can’t plan and enjoy moments with the people around you, but if the people around you feel they have unfettered access to your person, it’s on you to have the willpower to say no to them each and every time, and pretty often it’ll be all too easy to say yes. Being clear and up front about the requirements of your job and the times when you’ll be occupied, prevents regular interrupts and distractions and makes the times that you do surprise them with an afternoon break all the more special.</p>

<h2 id="lost-margins">Lost Margins</h2>

<p>The other, subtler change you have to account for when you start working from home is the loss of the margins around your work that existed when you were in an office. There’s a significant portion of your day between the moment you leave for work to the time when you get home that isn’t occupied with what would traditionally be considered ‘work,’ and while much of that time is spent on things that are frustrating and unnecessary (I’m looking at you, commute), there are significant segments that are remarkably critical to our health and happiness. The first thing that you may notice is that you are significantly less active than you were before. Although office activities aren’t exactly a rigorous workout, the bustle of getting to your place of work, shuffling between meetings and events, and running to the bathroom that is for some reason on the opposite side of the building is a lot more active than rolling out of bed and grabbing your laptop (in my experience, the difference between about 3500 and 500 steps a day). If you’re not that active, like me, then you’ve just lost a meaningful percentage of your daily exercise (about 30% if we’re aiming for 10k steps and going by my numbers), and finding a way to replace that is important for staving off sluggishness and fatigue. If you struggle sticking to exercise regimes, I find replacing the lost activity with other ‘movement with purpose’ is easier to maintain; when I’m having a hard time with motivation I’ll allocate an hour in the afternoons for tidying or minor projects around the house. It keeps me moving when I’m not up for going for a run, and has the added bonus of making my home slightly less of a disaster.</p>

<p>Another significant loss in transitioning to working from home is the loss of social contact. You may not chat a lot with your colleagues, you may not even like most of them, but your day was likely still punctuated with casual social interactions that have just disappeared entirely. I’m sure a psychologist could get into a lot more detail about how social deprivation affects us and why humans just aren’t wired for it, but those little moments when you said hello as you rolled into the office, or chatted after a meeting, or paused to catch up in a hallway, those were important. It can be hard to understand at first why something feels off, but in time you’ll likely find just how much you appreciate what little casual social contact you have left. Fostering these connections, and making deliberate time for interactions that previously would have been incidental (I personally favour leaning into casual catch-ups during the start of calls, as we wait for everyone to get on and ready), is a valuable investment in your mental health and, as I’ll cover in the next section, an equally valuable investment in your productivity.</p>

<h1 id="working-distributed">Working Distributed</h1>

<p>Working in a distributed manner is likely something that most folks have at least some passing familiarity with, even if they haven’t had to be particularly thoughtful about it before. Any time you’re working with someone who isn’t in the seat right next to you, you’re dealing with some degree of distribution, although for most people this is generally with others with whom they are more professionally distanced, rather than close collaborators. The uniqueness of the current situation comes from the rapid displacement of previously collocated collaborators—people with whom you are expected to be tightly integrated are suddenly inaccessible in ways you likely haven’t had to cope with before. Bridging that gap—making your team as accessible as it is integrated—is fully possible (and the crux of successful distributed organizations), but the transition is extremely jarring when we have an established set of norms that rely on seeing each other in person on a daily basis.
Reestablishing Presence</p>

<p>If there’s one thing to focus on when trying to reconnect a team that’s been recently distributed, it’s re-establishing a sense of presence. An enormous component of the accessibility that exists between members of a collocated team is their immediate knowledge of their coworkers location and status. A quick glance can instantly establish whether a team mate is at work, and furthermore whether they’re readily interruptible, based on whether they’re wearing headphones, posture, and many other small cues that are obvious in person. That immediate understanding of the presence of one’s colleagues makes choosing when and how to engage with them about as low friction as possible, as opposed to when they’re on the other side of the internet and it may be hard to establish whether a coworker is even in “the office” that day or not. There are a myriad of ways to communicate presence remotely—status messages in your favourite chat app, announcing your arrival/departure in a public channel, and automated activity trackers that exist in many modern tools (like Slack or Teams)—be considerate of what works for you and your team and make sure that it is used widely and consistently.</p>

<h2 id="tools-and-technology">Tools and Technology</h2>

<p>There’s a whole separate blog post to be written on the best tooling for distributed work, so once again for the sake of brevity I’ll stick to the core concepts and personal highlights as best I can. When it comes to sharing information you’re generally going to have tooling that fits into three categories: synchronous communication (video/phone calls), asynchronous communication (chat/email), and information repositories (Jira/Google Docs); and broadly these map to three different modes of exchange: freeform exploration/debate, structured discussion, and the establishment of a referenceable library of information. The boundaries and definitions of each category are not firm, the study of communication and its mediums is deep, broad, and outside of the scope of this post, but understanding your toolset through that lens may help you better select which tool is most appropriate (just because that meeting could have been an email doesn’t mean it should have been). Similarly, this perspective can be used to maximize the ease of access to any given information source. To clarify with some examples, consider the barriers in play when an individual is looking to either video conference with a colleague, or extract documented knowledge from a google doc. To reduce friction hindering them from starting a conference call you may need to focus on ensuring that they know who to contact, that they are comfortable reaching out to the domain expert, and they know when the individual with the required knowledge is available. On the opposite end of the spectrum, to reduce friction when sourcing information from an information repository like a google doc, you should focus on good naming, searchability, and on ensuring that in your information library there exists only a single source of truth for each piece of information (or at least that duplicates don’t contradict each other).</p>

<p>Although I’ve excluded matters of hardware entirely from this discussion so far (in short, a good mic, HD camera, and fast and hardwired internet valuable additions if available), I would like to make one specific recommendation. Given that you can’t always rely upon your coworkers to have high quality hardware of their own, I find a set of good headphones to be invaluable for making out the more muddled speakers on a call. The flip side of this of course is that headphones have the disadvantage of muffling your own voice, which many people find disconcerting and distracting while speaking. It turns out that you can have the best of both worlds—get a nice mic with aux out, and wire your headphones through that. This way the audio of your voice that the mic is picking up will be looped back to your ears sufficiently quickly that it’s almost indistinguishable from hearing yourself speak with no headphones on at all, and lets you hear people clearly without impediments to your own speech.</p>

<h2 id="keeping-teams-social">Keeping teams social</h2>

<p>Perhaps the least obvious aspect of interconnectedness and accessibility of a team is the social component—the ways we reduce the friction in our teams’ communication by being friendly with each other. Reaching out to a friend, even if they’re less accessible in other ways, is almost always preferable to connecting with someone with whom your relationship has soured (or didn’t exist in the first place). Not that you should necessarily be trying to force a team to become best buddies, but it is crucial to recognize the value derived from the socialization amongst your members—specifically the ways in which it eases the processes of outreach and communication. We tend to implicitly acknowledge this with collocated groups in the form of team events, where we ostensibly build camaraderie. Certainly those are valuable, and their digital analog—the Zoom cocktail hour—can be useful as well, but there’s an enormous amount of invisible socialization that goes on in the office that we should also attempt to replicate for our distributed workers. Moments like walking to meetings together, chatting over coffee, and exchanging thoughts at a shared desk, tragically, have no obvious analogue. Instead we must engineer space for alternative activities. As I mentioned before I’m particularly partial to the start-of-meeting social which, despite initially feeling like a waste of time (at least to some) pays significant social dividends in time. That supplemented with a generous allocation of semi-social 1-1 meetings keeps me feeling connected with my organization socially, as well as professionally. And if you are the individual in charge of a team, I strongly recommend ramping up loosely structured meetings like standups and planning sessions where you can leave ample room for social margins to keep your team talking.</p>

<p>In a team that is tightly integrated, one of the primary goals of the teams’ organizers should be making the act of drawing upon the knowledge of a collaborator as low-friction as possible. By considering our tools, practices, and processes through that lens of accessibility, it is possible to make considerable improvements to our collective experience as distributed workers.</p>

<h2 id="a-final-thought">A Final Thought</h2>

<p>As I mentioned before, there are many invaluable posts written by <a href="https://trello.com/en/remote-work-guide">incredibly thoughtful people</a> espousing theories of remote work, or providing <a href="https://auth0.com/blog/21-tips-for-remote-working/">lists</a> of <a href="https://zapier.com/learn/remote-work/">helpful advice</a> for managing your new situation. The challenge then is not how to find advice, but to find advice that works for you—successful remote work is a deeply personal matter and there are few one-size-fits-all solutions. Instead, I hope that this post can provide some guidance to help you sift through your thoughts on being a remote worker and what works best for you when it comes to staying focused at home, and connected at work.</p>

<p>Stay safe.</p>

<p>Evan</p>]]></content><author><name>Evan Brynne</name></author><summary type="html"><![CDATA[In amongst all the tragedy and trauma of our current circumstance, I find some solace in the newfound solidarity formed and felt in our communities—individuals of many disparate circumstances coming together and lending their expertise to support and uplift each other. I have felt the growth of the online community of workers particularly acutely, as thousands of Canadians bring their daily routines onto the internet and transition to being remote workers. This is a field in which I have some expertise; I have spent the last six years working from a home office for various companies, and many of the newfound frustrations of my friends and family trying out remote work for the first time are very familiar to me. As such I’d like to offer a few thoughts, to both give better definition to the problems we face, and also to offer a few solutions wherever I have some experience.]]></summary></entry></feed>