<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Sinistra]]></title><description><![CDATA[Thoughts, stories and ideas.]]></description><link>https://www.andrewsouthpaw.com/</link><image><url>https://www.andrewsouthpaw.com/favicon.png</url><title>Sinistra</title><link>https://www.andrewsouthpaw.com/</link></image><generator>Ghost 3.2</generator><lastBuildDate>Sun, 05 Apr 2026 14:35:22 GMT</lastBuildDate><atom:link href="https://www.andrewsouthpaw.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Syncing your personal and work calendars in Google Calendar.]]></title><description><![CDATA[<p>I live off my Google Calendar, and both my personal and work calendars can get pretty complicated. I found it difficult to keep the two in sync, namely blocking out time in the workday when I have something personal come up (e.g. a doctor's appointment).</p><p>I wanted a way</p>]]></description><link>https://www.andrewsouthpaw.com/syncing-your-personal-calendar-with-your-work-calendar/</link><guid isPermaLink="false">6165075918e49303f199c015</guid><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Tue, 12 Oct 2021 03:58:38 GMT</pubDate><content:encoded><![CDATA[<p>I live off my Google Calendar, and both my personal and work calendars can get pretty complicated. I found it difficult to keep the two in sync, namely blocking out time in the workday when I have something personal come up (e.g. a doctor's appointment).</p><p>I wanted a way to synchronize my personal calendar to my work calendar, but not reveal any of the details. Fortunately, I found a Google Apps script that started as an inspiration point. I've added to it and included more thorough instructions to make it more friendly to people unfamiliar with code.</p><p>Enjoy!</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://gist.github.com/AndrewSouthpaw/5ef5798d46a4ee159e05ef5a477b542d"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Google Apps script to copy personal events and block those times in your work calendar.</div><div class="kg-bookmark-description">Google Apps script to copy personal events and block those times in your work calendar. - calendarCopy.js</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/favicons/favicon.svg"><span class="kg-bookmark-author">262588213843476</span><span class="kg-bookmark-publisher">Gist</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://github.githubassets.com/images/modules/gists/gist-og-image.png"></div></a></figure>]]></content:encoded></item><item><title><![CDATA[How to upgrade Ruby.]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I've done this so many times, and I keep forgetting what exactly needs to be done. So I decided to write it down. Enjoy!</p>
<p>You have a few files to update:</p>
<ul>
<li><code>.ruby-version</code> -- tells various systems (e.g. rvm) which ruby version to use automatically</li>
<li><code>Gemfile</code> -- update the <code>ruby</code></li></ul>]]></description><link>https://www.andrewsouthpaw.com/how-to-upgrade-ruby/</link><guid isPermaLink="false">604295a318e49303f199c009</guid><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Fri, 05 Mar 2021 20:34:59 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I've done this so many times, and I keep forgetting what exactly needs to be done. So I decided to write it down. Enjoy!</p>
<p>You have a few files to update:</p>
<ul>
<li><code>.ruby-version</code> -- tells various systems (e.g. rvm) which ruby version to use automatically</li>
<li><code>Gemfile</code> -- update the <code>ruby</code> line toward the top of the file</li>
</ul>
<p>Once that's done, you'll need to reinstall stuff. Start by installing the new ruby version in rvm:</p>
<pre><code class="language-bash">$ rvm install &quot;ruby-2.6.6&quot;
</code></pre>
<p>Then you'll need to install the bundler for the new ruby version. Grab the bundler version from the <code>Gemfile.lock</code>, search for <code>BUNDLED WITH</code>. At the time of writing, that was 2.1.4. Then you install it:</p>
<pre><code class="language-bash">$ gem install bundler:2.1.4
</code></pre>
<p>Once that's done, run bundler to install all your gems for the newly installed ruby version:</p>
<pre><code class="language-bash">$ ruby -v
# should be the one you just installed, e.g. 2.6.6
# if not, reload your shell

$ bundle
</code></pre>
<p>Lastly, you'll want to quit and re-open RubyMine to let it work its magic with indexing the new ruby SDK and its gems. Your settings should now point to the new SDK:</p>
<p><img src="https://i.imgur.com/j7dAn8u.jpg" alt></p>
<p>And with that, you're done!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Testing an attachment CSV with RSpec and controllers.]]></title><description><![CDATA[<p>Ever send down a CSV from a controller like this:</p><pre><code class="language-ruby">  def index
    @users = User.all

    respond_to do |format|
      format.csv { send_data @users.to_csv, filename: "users-#{Date.today}.csv" }
    end
  end</code></pre><p>And then wonder how you can test the contents as well as the filename, and the fact</p>]]></description><link>https://www.andrewsouthpaw.com/testing-an-attachment-with-rspec-and-controllers/</link><guid isPermaLink="false">5f937b0918e49303f199bfd4</guid><category><![CDATA[rails]]></category><category><![CDATA[rspec]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Sat, 24 Oct 2020 00:59:18 GMT</pubDate><content:encoded><![CDATA[<p>Ever send down a CSV from a controller like this:</p><pre><code class="language-ruby">  def index
    @users = User.all

    respond_to do |format|
      format.csv { send_data @users.to_csv, filename: "users-#{Date.today}.csv" }
    end
  end</code></pre><p>And then wonder how you can test the contents as well as the filename, and the fact that it's supposed to be a download?</p><p>To check the filename, look at <code>response.headers['Content-Disposition']</code>.</p><pre><code class="language-ruby">expect(response.headers['Content-Disposition'])
  .to eq 'attachment; filename=users-2020-10-23.csv'</code></pre><p>To check the contents, look at <code>response.body</code>:</p><pre><code class="language-ruby">expect(response.body).to eq &lt;&lt;~CSV
  First Name,Last Name
  Andrew,Smith
CSV</code></pre>]]></content:encoded></item><item><title><![CDATA[The Value of Validations]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A quick story in the importance of database-level validations...</p>
<p>At Transparent Classroom, teachers are allowed to react to photos uploaded by parents with either a Heart or a Thumbs Up.</p>
<p><img src="https://i.imgur.com/mmTXQzj.gif" alt></p>
<p>Much like Facebook, you can only have reaction for a post. If you click Heart and then Thumbs Up, it</p>]]></description><link>https://www.andrewsouthpaw.com/the-value-of-validations/</link><guid isPermaLink="false">5eb43c9018e49303f199bfc1</guid><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Thu, 07 May 2020 16:54:43 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A quick story in the importance of database-level validations...</p>
<p>At Transparent Classroom, teachers are allowed to react to photos uploaded by parents with either a Heart or a Thumbs Up.</p>
<p><img src="https://i.imgur.com/mmTXQzj.gif" alt></p>
<p>Much like Facebook, you can only have reaction for a post. If you click Heart and then Thumbs Up, it will change your reaction rather than create a new one.</p>
<p>A simple solution to this on the server side could look like:</p>
<pre><code class="language-ruby">def create
  if (reaction = @post.reactions.find_by user: current_user)
    reaction.update! code: params[:reaction]
  else
    @post.reactions.create! user: current_user, code: params[:reaction]
  end
  # ...
end
</code></pre>
<p>A pretty common pattern, but there's a sneaky race condition in this code. Can you find it?</p>
<p>Our users were able to find it. Turns out that a combination of clicking different reactions in rapid succession, combined with the database occasionally being slightly slower, means that the system can break.</p>
<p>If a <code>sleep 3</code> was added before <code>@post.reactions.create!</code> it's easy to trigger. On the first request, the DB is checked for the presence of a reaction, finds none, and then starts the (artificially slow) process of creating a reaction. Meanwhile, a second request comes in, similarly doesn't (yet) find a reaction in the DB, and also starts to create a different reaction for the same post.</p>
<p>🤦‍♂️</p>
<p>Luckily, we had put a Rails model validation on our <code>Reaction</code>:</p>
<pre><code class="language-ruby">class Reaction
  validates :user_id, presence: true, uniqueness: { scope: :post_id }
  # ...
end
</code></pre>
<p>What could've led to bad data in the system instead simply triggered a 500 that we could detect and recover from.</p>
<p>Remember kids: latency is the root of many system errors. Even a simple system like ours (no distributed systems, simple lookup, a couple lines of code, etc.) can have edge cases that are easy to miss but likely to encounter.</p>
<p>Latency is exceptionally hard to account for correctly, and it takes a lot of extra time and careful design. We generally don't have the luxury of going slowly and meticulously designing every new feature or system. We move fast, so a decent middle ground is to add validations to protect against bad data and then to fix bugs due to latency when they're triggered in the real world.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Fix Invalid Hook Call Warning in React Tests]]></title><description><![CDATA[<p>So you've decided to hop on board the React Hooks train. Welcome to a fun, wild ride. They can add a great deal of declarative power to React. In my opinion, hooks were the missing puzzle piece in the API developed by React.</p><p>You get your first custom hook working,</p>]]></description><link>https://www.andrewsouthpaw.com/fix-invalid/</link><guid isPermaLink="false">5e8608c952ee6d03e016e500</guid><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Thu, 02 Apr 2020 15:58:36 GMT</pubDate><content:encoded><![CDATA[<p>So you've decided to hop on board the React Hooks train. Welcome to a fun, wild ride. They can add a great deal of declarative power to React. In my opinion, hooks were the missing puzzle piece in the API developed by React.</p><p>You get your first custom hook working, everything looks good in prod. Then, like the responsible developer you are, you write a simple test for it and run it.</p><figure class="kg-card kg-image-card"><img src="https://www.andrewsouthpaw.com/content/images/2020/04/image-1.png" class="kg-image"></figure><p>Damn. </p><p>"Invariant Violation: Hooks can only be called inside the body of a function component." But... you ARE!</p><p>A likely culprit is that you have multiple copies of React in your system. Rather than hunting through <code>yarn.lock</code> files, you can most reliably confirm this with some simple debugging logs:</p><pre><code class="language-javascript">// Add this in node_modules/react-dom/index.js
window.React1 = require('react');

// Add this in your component file
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2);</code></pre><p>Most people focus on forcing the same <code>react</code> package using Yarn resolutions. However, if you're only getting this error in your tests, the most likely culprit is a different version of <code>react-test-renderer</code>. You can fix it by adding these lines to your <code>package.json</code> file if you're using Yarn:</p><pre><code class="language-json">"resolutions": {
    "react-test-renderer": "your.reaction.version"
  }</code></pre><p>Hope that helps!</p>]]></content:encoded></item><item><title><![CDATA[Basic Babel + Webpack setup in 2020.]]></title><description><![CDATA[<p>Babel and Webpack keep evolving. It's time for yet another article about how to set them up for a web project in 2020.</p><p>You can check out a complete project <a href="https://github.com/AndrewSouthpaw/webpack-babel-starter-project">here</a>.</p><!--kg-card-begin: markdown--><h3 id="setuptheproject">Set up the project</h3>
<p>Create a new project and initialize git and npm.</p>
<pre><code class="language-bash">$ mkdir myProject
$ cd myProject
$ git init</code></pre>]]></description><link>https://www.andrewsouthpaw.com/basic-babel-webpack-setup-in-2020/</link><guid isPermaLink="false">5e61cda552ee6d03e016e4e4</guid><category><![CDATA[javascript]]></category><category><![CDATA[web bundling]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Fri, 06 Mar 2020 04:17:53 GMT</pubDate><media:content url="https://www.andrewsouthpaw.com/content/images/2020/03/lego-708088_1280.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.andrewsouthpaw.com/content/images/2020/03/lego-708088_1280.jpg" alt="Basic Babel + Webpack setup in 2020."><p>Babel and Webpack keep evolving. It's time for yet another article about how to set them up for a web project in 2020.</p><p>You can check out a complete project <a href="https://github.com/AndrewSouthpaw/webpack-babel-starter-project">here</a>.</p><!--kg-card-begin: markdown--><h3 id="setuptheproject">Set up the project</h3>
<p>Create a new project and initialize git and npm.</p>
<pre><code class="language-bash">$ mkdir myProject
$ cd myProject
$ git init
$ npm init
</code></pre>
<p>Create a <code>public</code> folder and stick in a skeleton <code>index.html</code> HTML file that will load a JS file that we expect to eventually produce using Webpack.</p>
<pre><code class="language-html">&lt;!-- public/index.html --&gt;

&lt;!-- sourced from https://raw.githubusercontent.com/reactjs/reactjs.org/master/static/html/single-file-example.html --&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;body&gt;
&lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
&lt;noscript&gt;
  You need to enable JavaScript to run this app.
&lt;/noscript&gt;
&lt;script src=&quot;../dist/bundle.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;

&lt;/html&gt;
</code></pre>
<p>(There's more you probably want with your <code>&lt;header&gt;</code> and such, we're ignoring that for now.)</p>
<h3 id="setupbabel">Set up Babel</h3>
<p>Install all the packages:</p>
<pre><code class="language-bash">$ yarn add @babel/core @babel/cli @babel/preset-env
</code></pre>
<p>Create a <code>babel.config.js</code> file:</p>
<pre><code class="language-js">// babel.config.js

module.exports = {
  'presets': ['@babel/env']
}
</code></pre>
<p>Create a <code>src/index.js</code> file and put in some basic code.</p>
<pre><code class="language-js">// src/index.js

const add = (a = 1, b = 2) =&gt; {
  return a + b
}
</code></pre>
<p>You can run Babel from the command line to verify it's working.</p>
<pre><code class="language-bash">$ ./node_modules/.bin/babel src/index.js
</code></pre>
<p>You should get something like this printed to your console (notice how it's transpiling ES2015 code -- the default parameters -- into compatible JS code for older browsers):</p>
<pre><code>&quot;use strict&quot;;

var add = function add() {
  var a = arguments.length &gt; 0 &amp;&amp; arguments[0] !== undefined ? arguments[0] : 1;
  var b = arguments.length &gt; 1 &amp;&amp; arguments[1] !== undefined ? arguments[1] : 2;
  return a + b;
};
</code></pre>
<h3 id="setupwebpack">Set up webpack</h3>
<p>Install all the packages:</p>
<pre><code class="language-bash">$ yarn add webpack webpack-cli webpack-dev-server style-loader css-loader babel-loader 
</code></pre>
<p>Add a <code>webpack.config.js</code> at the root:</p>
<pre><code class="language-js">// webpack.config.js

const path = require('path')
const webpack = require('webpack')

module.exports = {
  entry: './src/index.js',
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /(node_modules|bower_components)/,
        loader: 'babel-loader'
      },
      {
        test: /\.s?css$/,
        use: [&quot;style-loader&quot;, &quot;css-loader&quot;]
      }
    ]
  },
  resolve: { extensions: [&quot;*&quot;, &quot;.js&quot;, &quot;.jsx&quot;] },
  output: {
    path: path.resolve(__dirname, 'dist/'),
    publicPath: '/dist/',
    filename: 'bundle.js',
  },
  devServer: {
    contentBase: path.join(__dirname, &quot;public/&quot;),
    port: 3000,
    publicPath: &quot;http://localhost:3000/dist/&quot;,
  },
}
</code></pre>
<p>Add a build script to your <code>package.json</code> to run your webpack dev server:</p>
<pre><code>{
  ...
  &quot;scripts&quot;: {
    ...
    &quot;start&quot;: &quot;webpack-dev-server&quot;
  },
}
</code></pre>
<p>Now run the script.</p>
<pre><code class="language-bash">$ yarn start
</code></pre>
<p>And visit your site at <a href="http://localhost:3000">http://localhost:3000</a>. Viola, you have a working JS project.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Why I Can't Stand Java.]]></title><description><![CDATA[<p>I've been tooling around on Codewars lately, solving challenges as part of morning routine to awaken my brain and sharpen my problem-solving skills. I decided to try my hand at some Java again, and boy, was I in for a rude surprise.</p><p>Primarily I solve problems in Ruby or JavaScript,</p>]]></description><link>https://www.andrewsouthpaw.com/why-i-cant-stand-java/</link><guid isPermaLink="false">5d1a219a61a08f04a993a854</guid><category><![CDATA[languages]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Mon, 01 Jul 2019 15:32:53 GMT</pubDate><content:encoded><![CDATA[<p>I've been tooling around on Codewars lately, solving challenges as part of morning routine to awaken my brain and sharpen my problem-solving skills. I decided to try my hand at some Java again, and boy, was I in for a rude surprise.</p><p>Primarily I solve problems in Ruby or JavaScript, my two primary languages at the moment. For funsies and a little bit of a challenge, I decided to take on a couple easy katas in a different language. Apparently, because I'm a glutton for punishment, I chose to solve it in Java.</p><p>The challenge was straightforward: take a string of words, and print the words in reverse; so <code>Hello I like Ruby</code> becomes <code>Ruby like I Hello</code>.</p><p>Easy enough, I thought. In Ruby it's the most terse:</p><!--kg-card-begin: markdown--><pre><code class="language-ruby">str.split(' ').reverse.join(' ')
</code></pre>
<!--kg-card-end: markdown--><p>JavaScript is not far behind. Unfortunately, its <code>Array#reverse</code> method is destructive, reversing the elements in place, but whatever JS you made some poor choices back in the day, we all learned better since then.</p><!--kg-card-begin: markdown--><pre><code class="language-javascript">str.split(' ').reverse().join(' ')
</code></pre>
<!--kg-card-end: markdown--><p>Then, I took on Java. Boy, was I in for a surprise. I thought it would be very similar, pretty straightforward. </p><ol><li>Turn your string into an array of strings.</li></ol><p>Is it <code>str.split(" ")</code>? Nope. Missing a semicolon. Okay fine, how about <code>return str.split(" ");</code>? Sure, that gives us <code>String[]</code> but it turns out that's a comically under-featured abstraction. Want to do something like a reversal? Good luck doing that with <code>Anything[]</code> in a declarative way. You want a <code>List</code>, which you get with <code>Arrays.asList(thing)</code>, and also requires an import. Great! I have a solution!</p><!--kg-card-begin: markdown--><pre><code class="language-java">import java.util.*;

public class ReverseWords {
    public static String reverseWords(String str) {
        return Arrays.asList(str.split(&quot; &quot;)).reverse().join(&quot; &quot;);
    }
}
</code></pre>
<!--kg-card-end: markdown--><p>Nope. Hold on cowboy. You want a <code>reverse</code> method on <code>List</code>? What kind of craziness is that? You need the <code>Collections</code> framework, which gives you <code>Collections.reverse(list)</code>.</p><p>Okay, fine, whatever, here we go:</p><!--kg-card-begin: markdown--><pre><code class="language-java">import java.util.*;

public class ReverseWords {
    public static String reverseWords(String str) {
        Collections.reverse(Arrays.asList(str.split(&quot; &quot;))).join(&quot; &quot;);
    }
}
</code></pre>
<!--kg-card-end: markdown--><p>Still nope?! It turns out <code>Collections.reverse</code> <em>doesn't return anything </em>which is not intuitive and only does the reversal in place. </p><p>And guess what? <code>List</code> doesn't have a <code>join</code> method either. Want to join a list back into a string? Why, that would be on the <code>String</code> class, of course. Why? Because Java. Doesn't. Make. Sense.</p><!--kg-card-begin: markdown--><pre><code class="language-java">import java.util.*;

public class ReverseWords {
    public static String reverseWords(String str) {
        List words = Arrays.asList(str.split(&quot; &quot;));
        Collections.reverse(words);
        return String.join(&quot; &quot;, words);
    }
}
</code></pre>
<!--kg-card-end: markdown--><p>And there you have a working solution. This solution also happens to be highest ranked for cleverness and best practices in Codewars. This is the best that can be done in Java? Yep, and what's more, it can get a lot worse:</p><!--kg-card-begin: markdown--><pre><code class="language-java">public class ReverseWords{
   public static String reverseWords(String str){
       String[] str2 = str.split(&quot; &quot;);
       String fin = &quot;&quot;;
       for(int i=str2.length-1;i&gt;=0;i--){
           fin += str2[i];
           if(i&gt;0)fin+=&quot; &quot;;
       }
       return fin;
   }
}
</code></pre>
<!--kg-card-end: markdown--><p>There is <em>no way</em> you could, at a glance while squinting, understand what this code is doing (without reading the method name). I like to ask myself: does my code pass the "squint test"? (It's often used in reference to <a href="https://datasavvy.me/2017/12/22/design-concepts-for-better-power-bi-reports-part-4-the-squint-test/">parsing graphs</a>, but I think it applies to software as well.) I focus on writing code that can be skimmed so that later, when I've lost all context about the code I wrote, I don't get annoyed with past Andrew.</p><p>I remember being similarly frustrated by the limitations of Java when I was working on the backend of Kinesis Analytics at AWS. Doing a basic operation such as mapping across an array ( <code>arr.map { |x| doSomething(x) }</code> in Ruby or <code>arr.map(x =&gt; doSomething(x))</code> in JS) in Java requires a baffling amount of verbosity:</p><pre><code>arr.stream().map(e -&gt; doSomething(e)).collect(Collectors.toList());</code></pre><p>Moments like these make me appreciate how languages like Ruby were so revolutionary, in focusing on using human-readable syntax and favoring declarative over imperative coding. The Java solution reveals <em>so</em> many more implementation details and requires far more constructs ( <code>String</code>, <code>String[]</code>, <code>List&lt;String&gt;</code>, <code>Collections</code>). </p><p>It's not about brevity or fewest keystrokes (though I do enjoy a clever solution in katas), it's about expressiveness. I value the ability to express in abstract, high-level terms about something I want to accomplish.<em> </em>That's the point of declarative programming: focus on what kinds of transformations you want to perform on your data, rather than <em>how</em> to perform those transformations.</p>]]></content:encoded></item><item><title><![CDATA[Advanced Redux TDD: Reducers]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>We do TDD for most development at <a href="https://www.transparentclassroom.com">Transparent Classroom</a>, including our frontend business logic written in Redux. Doing TDD for Redux revealed certain frustrating aspects of structuring and testing Redux. I set out to make it better. This post offers a slightly different structure for your reducers to make them</p>]]></description><link>https://www.andrewsouthpaw.com/advanced-redux-tdd-reducers/</link><guid isPermaLink="false">5bab2f2461a08f04a993a841</guid><category><![CDATA[frontend]]></category><category><![CDATA[redux]]></category><category><![CDATA[testing]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Tue, 25 Sep 2018 07:02:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>We do TDD for most development at <a href="https://www.transparentclassroom.com">Transparent Classroom</a>, including our frontend business logic written in Redux. Doing TDD for Redux revealed certain frustrating aspects of structuring and testing Redux. I set out to make it better. This post offers a slightly different structure for your reducers to make them more testable and easier to statically type (for Flow or TypeScript). Let's dive in.</p>
<p>(Note: we also use Flow for type checking, which adds additional motivation for what we did. Where appropriate, I'll be adding Flow typing for discussion purposes, otherwise I'll strip it.)</p>
<h1 id="thestatusquo">The Status Quo</h1>
<p><a href="https://redux.js.org/recipes/writing-tests#reducers">In the offical docs</a>, reducers are structured using a <code>switch</code> statement, and then the branches of the reducer are tested using actions:</p>
<pre><code class="language-javascript">it('should handle ADD_TODO', () =&gt; {
  expect(reducer(initialState, addTodo('Run the tests'))) .toEqual([
    {
      text: 'Run the tests',
      completed: false,
      id: 0
    }
  ])
})
</code></pre>
<p>There were a couple issues that didn't sit right with me:</p>
<ol>
<li><strong>Navigation was a pain.</strong> We couldn't navigate directly to that part of the reducer from the spec by going into a function definition. At best, we'd have to look for usages of the constant, then find it that way.</li>
<li><strong>Tests didn't read naturally</strong>, with all the extra setup for the reducer, action object, etc. We wanted to write functions, because functions are easy to test.</li>
<li>We're also <strong>testing the action creators, which are a separate concern</strong>; not a big deal, but also not my favorite.</li>
<li><strong>Type checking with Flow was a miserable experience</strong> based on what was recommended by the <a href="https://flow.org/en/docs/react/redux/">official Flow docs</a>. We were essentially creating the same type definition in multiple places, getting obtuse errors, and finding little benefit. (That's saying a lot for being one of the maintainers of <a href="https://github.com/flowtype/flow-typed/">flow-typed</a>.)</li>
</ol>
<h1 id="findingabetterwayhandlerstake1">Finding a Better Way: Handlers -- Take 1</h1>
<p>An alternative to using a switch statement is to have a &quot;handlers object,&quot; <a href="https://redux.js.org/recipes/reducing-boilerplate#generating-reducers">mapping action types to handlers</a>, like so:</p>
<pre><code class="language-javascript">export const todos = createReducer([], {
  [ActionTypes.ADD_TODO]: (state, action) =&gt; {
    const text = action.text.trim()
    return [...state, text]
  }
})
</code></pre>
<p>(Amusingly, I thought of this idea on my own after ruminating on how to improve on the switch statement, then discovered it was already discussed in the Redux docs. Turns out coming up with original ideas is hard.)</p>
<p>It was a nice start, but not enough. It didn't allow for easy navigation between implementation and test, and the dynamic key object syntax felt a bit weird and limiting.</p>
<p>This approach can be taken one step further to something that is truly useful, however. The functions on that &quot;handlers object&quot; can be pulled out and exported. At last, we have a solution where we're testing functions rather than a system. I call these exported functions <em>handlers</em>:</p>
<pre><code class="language-javascript">// reducer.js
export const addTodo = ({ todo }, state) =&gt; /* ... */

// reducer_spec.js
describe('#addTodo', () =&gt; {
  it('should add a todo to the state', () =&gt; {
    expect(addTodo({ todo: 'Hello' }, [])).toEqual(['Hello'])
  })
})
</code></pre>
<p>The need for an action object to be passed in was still dissatisfying and not natural to write. Consider a handler that takes a bunch of pieces of data that are necessary, i.e. an action object with many keys:</p>
<pre><code class="language-javascript">it('should do a thing', () =&gt; {
  const action = {
    thing1: 'foo',
    thing2: 'bar',
    thing3: 'baz',
    thing4: 'qux',
  }
  const state = myHandler(action, defaultState)
  /* ... */
})

it('should do another thing', () =&gt; {
  const action = {
      thing1: 'argh',
      thing2: 'whyMustI',
      thing3: 'keepWritingOut',
      thing4: 'theseDarnKeys',
    }
})
</code></pre>
<h1 id="findingabetterwayhandlerstake2">Finding a Better Way: Handlers -- Take 2</h1>
<p>I wanted something that reads more naturally, like an ordinary function that has multiple parameters:</p>
<pre><code class="language-javascript">myHandler('foo', 'bar', 'baz', 'qux', state)
</code></pre>
<p>In its current form, the handlers were just an extraction of the internals of how Redux and reducers work, and I wasn't interested in being beholden to those details. I wanted to extract the arguments from the action object and just give them to the handler. Turns out, you can do just that.</p>
<pre><code class="language-javascript">// Let's say you have an action object...
const actionObject = { type: 'ADD_TODO', title: 'Write a cool blog post about reducers', description: 'It better be good...' }

// ...you can safely extract the values and pass them in as parameters to a handler 
const { type, ...payload } = actionObject
const newState = myHandler(...Object.values(payload), state)
</code></pre>
<p><strong>A brief disclaimer about <code>Object.values</code> and object iteration order, before you flip a table...</strong></p>
<p>I thought using <code>Object.values</code> in this way would be dangerous: we always hear about how <a href="https://stackoverflow.com/a/5525820/2672869">the iteration order of an object's keys is not guaranteed</a>. I tried a couple alternatives, including having the action creators generate <code>Map</code>s rather than objects (where the order is guaranteed). Using <code>Map</code>s were unpleasant to debug and it bothered me to step further away from how Redux is normally structured (i.e. using plain objects).</p>
<p>ES6, however, <a href="http://2ality.com/2015/10/property-traversal-order-es6.html">introduced a spec</a> for the iteration order of object keys. For objects with string (non-<code>Symbol</code>) keys that can't be parsed as integers, the iteration order is simply the insertion order.</p>
<pre><code class="language-javascript">Object.values({ foo: 1, bar: 2 })
// [1, 2]
</code></pre>
<p>Adding keys that are symbols (<code>{ [Symbol('first')]: true }</code>) or ones that can be parsed as integers (<code>{ '10': true }</code>) behave differently and make the picture more complex, but that doesn't matter for our purposes, because we want the string keys on the object to generally reflect parameter names, which cannot be integers or Symbols. Put another way, we have no need for <code>Symbol</code>s or strings that can be parsed as integers to be used as keys on our action objects.</p>
<p>Assuming consistent iteration order for object keys is totally safe given the above restrictions, which I think are reasonable. We've been doing it in our production code for almost a year without issue. Even older browsers seem fine, because <code>Object#values</code> is polyfilled by our Babel setup, so we can safely rely on the newer standard for how it behaves. (No promises though.)</p>
<p><strong>Now then, disclaimer aside...</strong></p>
<p>With this new pattern to extract the values off the action object and apply them to a handler function, we could easily translate handler functions into a reducer that fits with Redux. Remember, <em>a reducer is a function that takes a state and an action object and returns a state</em>:</p>
<pre><code class="language-javascript">export const addTodo = (title, description, state) =&gt; { /* ... */ }
export const removeTodo = (id, state) =&gt; { /* ... */ }

const handlers = {
  [ADD_TODO]: addTodo,
  [REMOVE_TODO]: removeTodo,
}

const reducer = (state = defaultState, { type, ...args }) =&gt; {
  const handler = handlers[type]
  if (!handler) return state
  return handler(...Object.values(args), state)
}
export default reducer
</code></pre>
<p>With all this in place, we could test our reducers as a series of functions, easily navigate from its usage in the test to the implementation, and have a bunch of other handy IDE intellisense features (e.g. easily seeing code structure, auto-imports, etc.).</p>
<pre><code class="language-javascript">// actions.js
export const addTodo = (title, description) =&gt; ({ type: ADD_TODO, title, description })

// reducer.js
export const addTodo = (title, description, state) =&gt; { /* ... */ }

// reducer_spec.js
it('should do a thing', () =&gt; {
  const state = addTodo('My First Todo', 'I feel so proud!', defaultState)
  /* ... */
})
</code></pre>
<p>Ah, the sweet smell of victory.</p>
<p>A bit on the nose, but worth reminding: the parameter names of the <code>addTodo</code> handler do not have to match the key names of the action object; only the order of them matters. We use the same names for convenience. If you had something like this:</p>
<pre><code class="language-javascript">// actions.js
export const addTodo = (title, description) =&gt; ({ type: ADD_TODO, description, title }) // &lt;-- notice the order

// reducer.js
export const addTodo = (title, description, state) =&gt; { /* ... */ } // &lt;-- vs. here
</code></pre>
<p>... you've got a bug. That translation does feel brittle, and also it hasn't come up yet as a problem. We're talking about other possible solutions such as using <a href="https://github.com/erikras/ducks-modular-redux">ducks</a> to co-locate our action creators and reducers, or even auto-generate our action creates based on our reducers, for an even better developer experience.</p>
<h1 id="wiringthehandlerstothereducer">Wiring the Handlers to the Reducer</h1>
<p>The tricky part then became how to tell the reducer to actually use these handlers. You saw one above, where I created the handlers object, and just before the reducer I associated handlers to their action types. I didn't like it that much; it wasn't obvious when a handler was actually being registered with the reducer. After running through a few different approaches, I settled on the concept of &quot;registering&quot; a handler on the handlers object, then giving the object to the reducer. I'm going to omit the actual helper code for now and focus on its usage:</p>
<pre><code class="language-javascript">// reducer.js

const handlers = {}
const registerHandler = setupRegistration(handlers)

export const addTodo = (title, description, state) =&gt; { /* ... */ }
registerHandler(ADD_TODO, addTodo)

export const removeTodo = (id, state) =&gt; { /* ... */ }
registerHandler(REMOVE_TODO, removeTodo)

const initialState = { /* ... */ }
export default createReducerWithHandlers(handlers, initialState)
</code></pre>
<p>This approach made it clear which handlers were actually employed by the reducer (rather than helpers) and colocated the action type with the handler. Super handy for navigation and reasoning about whether a handler was being used directly to respond to an action type.</p>
<h1 id="waitwhyisthestateaparameterattheend">Wait, Why is the State a Parameter at the End?</h1>
<p>I structured the handlers to take the state object <em>at the end</em> rather than at the beginning (like in the actual reducer). Answering the question of &quot;why&quot; requires diving into a bit of functional programming.</p>
<p>I made this design choice to reflect a common principle of functional programming: put the intended recipient of the operation at the end of the parameter list. So, if you were to write a standalone map function:</p>
<pre><code class="language-javascript">// do this
map(someFn, xs)

// not this
map(xs, someFn)
</code></pre>
<p>This principle is useful because you can make that concept of &quot;map someFn&quot; into another abstraction:</p>
<pre><code class="language-javascript">const addOne = x =&gt; x + 1
// this is the abstraction
const incrementList = map(addOne) // this assumes `map` is curried
// which can be applied to various lists
const list1 = incrementList([1, 2, 3])
const list2 = incrementList([4, 5, 6])
</code></pre>
<p>Trying to do it the other way around is... really hard to do. So, to reiterate, in FP you often want to structure your functions such that the most commonly changing parameter comes at the end, so you can create more useful abstractions on the parameters that come before it.</p>
<p>(By the way, if <code>const incrementList = map(addOne)</code> throws you and you don't know about currying, I strongly recommend you check out one of the many excellent blog posts out there that explains this concept. The basic idea of currying is that it allows you to take a function and incrementally call it with arguments until all the parameters are provided, and then the function is called. So, for example, <code>add(1, 2) === add(1)(2)</code>.)</p>
<p>Anyway. I moved the state to the end to make piping state from one handler to the next a breeze. If you curry your handlers, the tests become wonderfully simple and expressive, piping results from one handler into another one.</p>
<p><strong>A brief aside on piping</strong></p>
<p><code>pipe</code> takes any number of functions, takes the last parameter given to it and gives it to the first fn, which then pipes the output into the second one, and so on. FPers call it &quot;left-to-right composition.&quot; If you have something like <code>pipe(f1, f2, f3, x)</code>, this translates to <code>f3(f2(f1(x)))</code>. Or, in an imprecise graphical sort of way, <code>f1(x) -&gt; f2 -&gt; f3</code>.</p>
<p>I strongly recommend using <a href="https://ramdajs.com/">Ramda</a> to give you an insanely powerful FP toolkit for Javascript. I hope to write more about Ramda some other day.</p>
<p>So, with <code>pipe</code>, we can easily build up a state through a sequence of handler uses.</p>
<pre><code class="language-javascript">const state = pipe(
  addTodo('First Todo', 'This was my first todo!'),
  addTodo('Make TDD better', 'Focus first on reducers'),
)(defaultState)
</code></pre>
<p>Compare this with the alternative, where state is the first parameter:</p>
<pre><code class="language-javascript">const state = pipe(
  x =&gt; addTodo(x, 'First Todo', 'This was my first todo!'),
  x =&gt; addTodo(x, 'Make TDD better', 'Focus first on reducers'),
)(defaultState)
</code></pre>
<p>It's not terrible, but I vastly prefer the flexibility of the former. Also, the handlers can then be used to create other abstractions, in the same way as <code>incrementList</code> was created:</p>
<pre><code class="language-javascript">const someComplicatedHandler = curry((arg1, arg2, arg3, arg4, arg5, state) =&gt; { /* ... */ })
const mostlyFigureOutHandler = someComplicatedHandler(1, 2, 3, 4)
</code></pre>
<p>With all this setup, you can at last achieve TDD nirvana and test the various parts of your reducer functionality like they were functions that are composable and modular. (Yes, you functional programmers out there can be all 🙌 here.)</p>
<pre><code class="language-javascript">it('#completeTodo should mark a todo at an index as completed', () =&gt; {
  const state = pipe(
    addTodo('A'),
    addTodo('B'),
    addTodo('C'),
    completeTodo(1),
  )(defaultState)

  expect(state.map(x =&gt; x.completed)).toEqual([false, true, false])
})
</code></pre>
<h1 id="statictypingforreducers">Static Typing for Reducers</h1>
<p>Using this approach of exporting handlers and registering them on the reducer provides the added benefit of dramatically simplifying the type checking for reducers. I'll discuss it using Flow, but I'm sure TypeScript would be similar.</p>
<p>Setting up type checking based off the Flow docs is a mouthful, requiring a lot of extra typing:</p>
<pre><code class="language-javascript">// types.js
type FooAction = { type: &quot;FOO&quot;, foo: number }
type BarAction = { type: &quot;BAR&quot;, bar: boolean }

type Action =
  | FooAction
  | BarAction

// actions.js
const fooAction: FooAction = (foo: number) =&gt; ({ type: 'FOO', foo })
const barAction: BarAction = (bar: boolean) =&gt; ({ type: 'BAR', bar})

// reducer.js
function reducer(state: State, action: Action): State {
  switch (action.type) { /* ... */ }
}
</code></pre>
<p>It works, but not perfectly. Flow sometimes behaves strangely with disjoint unions because it's not a perfect system. It's also hard to understand, requiring a deeper knowledge of Flow and typing. Finally, inside the reducer, you don't actually know your types at the various branches of your switch statement; you have to refer to a different file entirely to figure out the types of the action object for that branch.</p>
<p>Fortunately, using handlers circumvents all these issues, because the handlers are simply functions whose parameters can be easily typed. The inputs to the function are explicitly typed right with the definition, making it a breeze to read.</p>
<pre><code class="language-javascript">const addTodo = (title: string, description: string, state: TodosStateT): TodosStateT =&gt; { /* ... */ }
</code></pre>
<p>(We append type names with <code>T</code> to avoid naming conflicts, which has worked out <em>really</em> well for us.)</p>
<p>We don't bother typing our actions because it hasn't served any utility. There's a temptation to &quot;Type All The Things&quot; with Flow, but we've decided to be more strategic around what we type to maximize benefit and not waste time.</p>
<h1 id="tldr">TL;DR</h1>
<p>To recap: you can write your reducers as a collection of handlers that are registered to the reducer. Structuring them this way keeps with the patterns of Redux while improving testability, navigation, and general developer experience. Here's the code in a nutshell, including the helper functions extracted into a separate file:</p>
<pre><code class="language-javascript">// reducer_helpers.js

// this mutates the handler object! That's okay though.
export const setupRegistration = (handlers) =&gt; (actionType, handler) =&gt; {
  handlers[actionType] = handler
}

export const createReducerWithHandlers = (handlers, defaultState, state, { type, ...args }) =&gt; {
  const handler = handlers[type]

  if (!handler) return state || defaultState

  // This is safe for empty args arrays, the spread will still come out to be [state], not [null, state]
  return handler(...Object.values(args), state)
}

// reducer.js

const handlers = {}
const registerHandler = setupRegistration(handlers)

export const addTodo = (title, description, state) =&gt; { /* ... */ }
registerHandler(ADD_TODO, addTodo)

export const removeTodo = (id, state) =&gt; { /* ... */ }
registerHandler(REMOVE_TODO, removeTodo)

const initialState = { /* ... */ }
export default createReducerWithHandlers(handlers, initialState)
</code></pre>
<p>I hope you will give it a try and see if you get similar benefits. I'd love to hear your thoughts and how it works out in your projects.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Ramda, webpack, and tree-shaking.]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Are you using Ramda and Webpack? Then you probably want to read this, because chances are good you're importing more of the Ramda library than you might think...</p>
<p>We're all big on reducing bundle sizes for the web. When leveraging larger utility libraries such as <a href="https://github.com/ramda">Ramda</a>, we are encouraged to</p>]]></description><link>https://www.andrewsouthpaw.com/ramda-webpack-and-tree-shaking/</link><guid isPermaLink="false">5ba9dcfd57dc045b69146b70</guid><category><![CDATA[web bundling]]></category><category><![CDATA[frontend]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Fri, 19 Jan 2018 06:59:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Are you using Ramda and Webpack? Then you probably want to read this, because chances are good you're importing more of the Ramda library than you might think...</p>
<p>We're all big on reducing bundle sizes for the web. When leveraging larger utility libraries such as <a href="https://github.com/ramda">Ramda</a>, we are encouraged to only import the functions we need:</p>
<pre><code class="language-javascript">import R from 'ramda' // bad times
import { identity } from 'ramda' // good times
</code></pre>
<p>At Transparent Classroom, we dutifully do as such, yet recently I was struck with an unfortunate reality: <strong>the whole Ramda library was still being imported</strong>.</p>
<div style="text-align:center"><img src="https://www.andrewsouthpaw.com/content/images/2018/01/beforeAppMinified.jpg" alt style="margin:1em 0;"></div>
<p>So, I started to do some investigating, and began with a simple test file:</p>
<pre><code class="language-javascript">import { identity } from 'ramda'

identity()
</code></pre>
<p>Running webpack on that, it yielded this result, which felt like a horrible betrayal.</p>
<div style="text-align:center"><img src="https://www.andrewsouthpaw.com/content/images/2018/01/beforeSimpleMinified.jpg" alt style="margin:1em 0;"></div>
<p>The expected contract was broken: when you extract your imports, you don't get the whole darn library. Based on several discussions (<a href="https://github.com/ramda/ramda/issues/2355">here</a>, <a href="https://github.com/ramda/ramda/issues/1505">here</a>, and <a href="https://github.com/webpack/webpack/issues/2867">here</a>), most fingers point to webpack being the culprit. There was a thorough exploration of webpack and its tree shaking abilities WRT Ramda done <a href="https://github.com/scabbiaza/ramda-webpack-tree-shaking-examples">here</a>. It turns out your options are limited if you're just using webpack:</p>
<ol>
<li><strong>Manually cherry pick</strong>: do <code>import identity from 'ramda/es/identity'</code> -- ugh, no thank you.</li>
<li><strong>Use <code>ModuleConcatenationPlugin</code></strong> -- helps improve the tree shaking algorithm, though it's still a bit experimental.</li>
</ol>
<p>Fortunately, if you use <code>babel</code>, there's a handy plugin that can manually turn your general imports into cherrypicked imports:</p>
<pre><code class="language-javascript">import R, {map} from 'ramda';

map(R.add(1), [1, 2, 3]);
</code></pre>
<p>becomes</p>
<pre><code class="language-javascript">import add from 'ramda/src/add';
import map from 'ramda/src/map';

map(add(1), [1, 2, 3]);
</code></pre>
<p>With this plugin in place, justice is restored:</p>
<div style="text-align:center"><img src="https://www.andrewsouthpaw.com/content/images/2018/01/afterSimpleMinified.jpg" alt style="margin:1em 0;"></div>
<p>Doing this on our app reduced the Ramda library import by 60%, from 75.5KB to 29.8KB.</p>
<div style="text-align:center"><img src="https://www.andrewsouthpaw.com/content/images/2018/01/postAppMinified.jpg" alt style="margin:1em 0;"></div>
<p>However, I still like to include the whole Ramda library and set it on <code>window</code> in my dev environment for debugging purposes, i.e. <code>window.R = require('ramda')</code>. Turns out the plugin doesn't like that, <a href="https://github.com/megawac/babel-plugin-ramda/issues/28">discussed here</a>. The easy solution is to only enable the plugin in dev. Here's my <code>.babelrc</code> file, shortened to the relevant part:</p>
<pre><code>{
  ...
  &quot;env&quot;: { &quot;production&quot;: { &quot;plugins&quot;: [&quot;ramda&quot;] } }
}

</code></pre>
<p>Next up: dropping use of lodash. Oh the joys of working on apps that have lived through many eras of web development (that is to say, is ~5 years old).</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[AWS DevOps for Dummies: Node.js, Elastic Beanstalk, PostgreSQL, & Travis.]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I've put together my first screencast demonstrating deployment of a Node.js app with a PostgreSQL backend to AWS using Elastic Beanstalk and Travis as a continuous integration server. I had a lot of fun putting it together, and owe many thanks to <a href="https://github.com/kwhinnery">Kevin Whinnery</a> who put together the repo</p>]]></description><link>https://www.andrewsouthpaw.com/aws-devops-for-dummies-node-js-elastic-beanstalk-postgresql-travis/</link><guid isPermaLink="false">5ba9dc7b57dc045b69146b6a</guid><category><![CDATA[devops]]></category><category><![CDATA[beginner's path]]></category><category><![CDATA[aws]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Mon, 17 Jul 2017 06:57:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I've put together my first screencast demonstrating deployment of a Node.js app with a PostgreSQL backend to AWS using Elastic Beanstalk and Travis as a continuous integration server. I had a lot of fun putting it together, and owe many thanks to <a href="https://github.com/kwhinnery">Kevin Whinnery</a> who put together the repo I used for demo purposes. He taught a course on <a href="https://frontendmasters.com">Frontend Masters</a> about (among other things) running a <a href="https://frontendmasters.com/courses/production-node-aws/">Node app in production on AWS</a>. Based on what I learned there, I expanded with setting up Travis CI as well as providing some of my own tips on a more secure setup (using a slightly different configuration for security groups and the database). I hope you enjoy, feedback is most welcome!</p>
<p><a href="https://github.com/AndrewSouthpaw/todomvc-plusplus">Repo to get started</a>. Most of the instructions are in the README, with the screencast providing a clearer visual walkthrough along with explanations of core concepts in AWS.</p>
<p><a href="http://www.youtube.com/watch?v=B1_t8McaWaA" title="AWS DevOps for Dummies"><div style="text-align:center"><img src="http://img.youtube.com/vi/B1_t8McaWaA/0.jpg" alt style="margin:1em 0;"></div></a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Really, Javascript?]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I'm a huge fan of JavaScript, but sometimes I'm left flabberghasted by some of its most basic reasoning.</p>
<pre><code class="language-javascript">// This sort of makes sense... 
1 &gt; null  // true

// ...what?
-1 &gt; null  // false
</code></pre>
<p>I would get it if <em>any</em> number was larger than <code>null</code>, but apparently in the land of JavaScript</p>]]></description><link>https://www.andrewsouthpaw.com/really-javascript/</link><guid isPermaLink="false">5ba9dc3157dc045b69146b66</guid><category><![CDATA[javascript]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Sat, 24 Jun 2017 06:56:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I'm a huge fan of JavaScript, but sometimes I'm left flabberghasted by some of its most basic reasoning.</p>
<pre><code class="language-javascript">// This sort of makes sense... 
1 &gt; null  // true

// ...what?
-1 &gt; null  // false
</code></pre>
<p>I would get it if <em>any</em> number was larger than <code>null</code>, but apparently in the land of JavaScript only positive numbers are larger.</p>
<p>In case you haven't seen it, I highly recommend the <a href="https://www.destroyallsoftware.com/talks/wat">Wat</a> talk by Gary Bernhardt. Super funny, and reveals a lot of quirks of different languages.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Neat features of Flow.]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I recently took a couple hours to read through the Flow docs, which was an informative and valuable use of time. Here are a bunch of notes on useful and slightly intuitive aspects of Flow. Many of these code blocks are pulled from the docs.</p>
<h1 id="settingupflow">Setting up Flow.</h1>
<p>The Flow</p>]]></description><link>https://www.andrewsouthpaw.com/neat-features-of-flow/</link><guid isPermaLink="false">5ba9dbdd57dc045b69146b61</guid><category><![CDATA[frontend]]></category><category><![CDATA[flow]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Mon, 15 May 2017 06:55:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I recently took a couple hours to read through the Flow docs, which was an informative and valuable use of time. Here are a bunch of notes on useful and slightly intuitive aspects of Flow. Many of these code blocks are pulled from the docs.</p>
<h1 id="settingupflow">Setting up Flow.</h1>
<p>The Flow official page has decent <a href="https://flow.org/en/docs/install/">installation instructions</a>. If you're using Webpack and it's already working with Babel, all you need is to install the packages and edit your <code>.babelrc</code> file as they mention.</p>
<h4 id="settingupwithwebstormrubymine">Setting up with Webstorm / Rubymine</h4>
<p><a href="https://blog.jetbrains.com/webstorm/2016/11/using-flow-in-webstorm/">This article</a> provides a thorough explanation, but here's the basic takeaway:</p>
<ol>
<li>Go to Preferences | Languages &amp; Frameworks | JavaScript in WebStorm and set language version to Flow.</li>
<li>Specify the Flow executable to something similar to this path, replacing <code>/path/to</code> with your directory structure: <code>/path/to/TransparentClassroom/node_modules/flow-bin/vendor/flow</code></li>
</ol>
<h1 id="usingflow">Using Flow.</h1>
<p><a href="https://flow.org/en/docs/usage/">This page</a> is a good place to get the basic understanding what what's going on, and then <a href="https://flow.org/en/docs/types/">read here</a> for all the information on different types, and it's good to start at the beginning and read through, it has a good linear progression. Most of them are pretty obvious or easy to find in the documentation (e.g. arrays, objects, functions). Here are a few that are less obvious, but very useful:</p>
<h4 id="uniontype">Union type</h4>
<p>Allows you to specify more than one possible type.</p>
<pre><code class="language-javascript">function stringifyBasicValue(value: string | number | boolean) {
  return '' + value;
}
</code></pre>
<p>Can also be written with leading vertical bar:</p>
<pre><code class="language-javascript">type Foo =
  | Type1
  | Type2
</code></pre>
<h4 id="readonlyproperties">Read-only properties</h4>
<p>You can make properties of an object read-only, which can be super useful in helping enforce immutability. <a href="https://flow.org/en/docs/types/interfaces/#toc-interface-property-variance-read-only-and-write-only">More here.</a></p>
<pre><code class="language-javascript">type Foo = { +bar: string }
const a: Foo = { bar: 'hello' }
a.bar = 'new' // Error: Flow: object type. Covariant property `bar` incompatible with contravariant use in assignment of property `bar` 
</code></pre>
<h4 id="disjointunion">Disjoint union</h4>
<p>Useful for when you know that the type will have certain properties dependent on a specific property, e.g. whether a server call was successful. <a href="https://flow.org/en/docs/types/unions/#toc-disjoint-unions">Read more.</a></p>
<pre><code class="language-javascript">// @flow
type Success = { success: true, value: boolean };
type Failed  = { success: false, error: string };

type Response = Success | Failed;

function handleResponse(response: Response) {
  if (response.success) {
    var value: boolean = response.value; // Works!
  } else {
    var error: string = response.error; // Works!
  }
}
</code></pre>
<h4 id="mixedtype">Mixed type</h4>
<p>When the type is unknown.</p>
<pre><code class="language-javascript">function getTypeOf(value: mixed): string {
  return typeof value;
}
</code></pre>
<p><strong>Important!</strong> Don't confuse with <code>any</code>, which effectively disables type checking and can leak to other parts of the system.</p>
<h4 id="keys">$Keys</h4>
<p>Useful for enums with values you want to access at runtime. <a href="https://flow.org/en/docs/types/utilities/#toc-keys">More here.</a></p>
<pre><code class="language-javascript">// @flow
const countries = {
  US: &quot;United States&quot;,
  IT: &quot;Italy&quot;,
  FR: &quot;France&quot;
};

type Country = $Keys&lt;typeof countries&gt;;

const italy: Country = 'IT';
const nope: Country = 'nope'; // 'nope' is not a Country
</code></pre>
<h4 id="maybetypesvsoptionalparameters">Maybe types vs. optional parameters</h4>
<p>A <code>maybe</code> type is that type, <code>undefined</code>, or <code>null</code>. It's a <code>?</code> in front of the type, e.g. <code>?number</code></p>
<pre><code class="language-javascript">// @flow
function acceptsMaybeNumber(value: ?number) {
  // ...
}

acceptsMaybeNumber(42);        // Works!
acceptsMaybeNumber();          // Works!
acceptsMaybeNumber(undefined); // Works!
acceptsMaybeNumber(null);      // Works!
acceptsMaybeNumber(&quot;42&quot;);      // Error!
</code></pre>
<p>An optional parameter is specified with a <code>?</code> after the variable name. It means the parameter is either specified or <code>undefined</code>, but not <code>null</code>.</p>
<pre><code class="language-javascript">// @flow
function acceptsObject(value: { optionalProp?: string }) {
  // ...
}

acceptsObject({ foo: &quot;bar&quot; });     // Works!
acceptsObject({ foo: undefined }); // Works!
// $ExpectError
acceptsObject({ foo: null });      // Error!
acceptsObject({});                 // Works!
</code></pre>
<h1 id="usingflowwithredux">Using Flow with Redux.</h1>
<p>The Redux GitHub repo has a nice <a href="https://github.com/reactjs/redux/tree/master/examples/todos-flow">starter example</a> of using Flow with Redux. Noteworthy points:</p>
<ul>
<li>Defining types in a separate folder, and using them everywhere for consistency</li>
<li>Making <code>Actions</code> and other state variables read-only through the use of covariant properties</li>
<li>Using same properties that define state as properties on React components. Now it's much easier to keep React component types in sync with state. Whoo!</li>
</ul>
<h1 id="diggingdeeper">Digging deeper.</h1>
<p>There's much more to explore, and <a href="https://flow.org/en/docs/">this page</a> offers a good starting point. Happy digging.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Jest + Chai and expect.assertions.]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>At <a href="https://www.andrewsouthpaw.com/jest-chai/www.transparentclassroom.com">Transparent Classroom</a>, we use both Mocha/Chai to test our modules and Redux code and Jest to test our React components. Mocha/Chai and Jest are very similar in syntax, except for this annoying difference in that the matchers are different, e.g. <code>to.eq(1)</code> vs <code>toEqual(1)</code></p>]]></description><link>https://www.andrewsouthpaw.com/jest-chai/</link><guid isPermaLink="false">5ba9db6d57dc045b69146b5d</guid><category><![CDATA[testing]]></category><category><![CDATA[frontend]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Fri, 12 May 2017 06:53:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>At <a href="https://www.andrewsouthpaw.com/jest-chai/www.transparentclassroom.com">Transparent Classroom</a>, we use both Mocha/Chai to test our modules and Redux code and Jest to test our React components. Mocha/Chai and Jest are very similar in syntax, except for this annoying difference in that the matchers are different, e.g. <code>to.eq(1)</code> vs <code>toEqual(1)</code>. We liked the natural assertion style of Chai, which is also similar to RSpec (which we use extensively for our Rails backend), so we wanted to use Chai-style assertions in our Jest tests. This post explains how to make that possible, still take advantage of some neat new features of Jest's assertion library, and learn something about <code>Object.defineProperty</code>.</p>
<h1 id="gettingstarted">Getting Started.</h1>
<p>The setup was originally inspired by <a href="https://medium.com/@RubenOostinga/combining-chai-and-jest-matchers-d12d1ffd0303">this post</a> by Ruben Oostinga. You should read through that post for context. The key takeaway is to do two things:</p>
<h4 id="1createasetuptestframeworkscriptjs">1. Create a <code>setup-test-framework-script.js</code>.</h4>
<p>Create <code>setup-test-framework-script.js</code> and place it in your root directory.</p>
<pre><code class="language-javascript">const chai = require('chai')

// Make sure chai and jasmine &quot;.not&quot; play nice together
const originalNot = Object.getOwnPropertyDescriptor(chai.Assertion.prototype, 'not').get
Object.defineProperty(chai.Assertion.prototype, 'not', {
  get() {
    Object.assign(this, this.assignedNot)
    return originalNot.apply(this)
  },
  set(newNot) {
    this.assignedNot = newNot
    return newNot
  },
})

// Combine both jest and chai matchers on expect
const originalExpect = global.expect

global.expect = (actual) =&gt; {
  const originalMatchers = originalExpect(actual)
  const chaiMatchers = chai.expect(actual)
  const combinedMatchers = Object.assign(chaiMatchers, originalMatchers)
  return combinedMatchers
}
</code></pre>
<h4 id="2addthescripttoyourjestconfiguration">2. Add the script to your Jest configuration.</h4>
<p>Inside <code>package.json</code>, under your <code>&quot;jest&quot;</code> configuration:</p>
<pre><code class="language-javascript">  &quot;jest&quot;: {
    ...
    &quot;setupTestFrameworkScriptFile&quot;: &quot;&lt;rootDir&gt;/setup-test-framework-script.js&quot;,
  }
</code></pre>
<h1 id="huzzahweredonewellnotquite">Huzzah, We're Done! Well, Not Quite...</h1>
<p>This worked great, for a long while. We could happily write <code>expect(1).to.eq(1)</code> in our Jest tests and everyone was happy.</p>
<p>UNTIL.</p>
<p>I came across a neat feature of Jest, where you can <a href="https://facebook.github.io/jest/docs/expect.html#expectassertionsnumber">assert the number of assertions that should be made</a>. This is useful when you're testing async actions, and want to make sure your assertions are actually fired. Otherwise, if you have a test like this:</p>
<pre><code class="language-javascript">it('should work', () =&gt; {
  return somethingAsyncAndReject().then(() =&gt; {
    expect(1).to.eq(2)
  })
})
</code></pre>
<p>and <code>somethingAsync()</code> rejects its promise, this test would silently pass because the <code>.then</code> block was never reached. Sad times. Jest fixes the issue by allowing you to specify that assertions should be made:</p>
<pre><code class="language-javascript">it('should work', () =&gt; {
  expect.assertions(1)
  return somethingAsyncAndReject().then(() =&gt; {
    expect(1).to.eq(2)
  })
})
</code></pre>
<p>Then you can get output like this to the console:</p>
<pre><code>expect.assertions(1)

Expected: one assertion
Received: zero assertions
Expected :1
Actual   :0
</code></pre>
<p>At least, that's how it works <em>in theory</em>. Using the super-charged, monkey-patched <code>global.expect</code> object in our setup, we get an error:</p>
<pre><code>TypeError: expect.assertions is not a function
</code></pre>
<p>This was because in our setup, we set <code>global.expect</code> to <em>only be a function</em>. Recall this snippet:</p>
<pre><code class="language-javascript">global.expect = (actual) =&gt; {
  ...
}
</code></pre>
<p>There ain't no <code>.assertions</code> function on that! We've blindly overridden some useful functionality of <code>expect</code> that Jest provided us. Fortunately, you can give those methods back to the object:</p>
<pre><code class="language-javascript">global.expect = (actual) =&gt; {
  ...
}
Object.keys(originalExpect).forEach(key =&gt; (global.expect[key] = originalExpect[key]))
</code></pre>
<p>This allows us to set an expectation around the number of assertions that will be made, but my code was still mysteriously failing, even with this simple example:</p>
<pre><code class="language-javascript">it('should work', () =&gt; {
  expect.assertions(1)
  expect(1).to.eq(1)
})
</code></pre>
<p>I was still receiving an error saying that 1 assertion was expected, but none were made.</p>
<p>Any guesses as to why?</p>
<p>I didn't have any either, and it took me the better part of an hour to figure out.</p>
<p><code>expect#assertions</code> isn't <em>actually</em> magic, which should come as no surprise. The implementation of it is <a href="http://bit.ly/2pEffzq">quite simple</a>, it sets a state variable of the number of expected assertions. After some digging around, I figured out that the variable tracking the number of assertions made was also on that state, called <code>assertionsMade</code>. This variable would be incremented when assertions are made using Jest matchers, but obviously Chai would not do the same, hence the discrepancy. If I had written <code>expect(1).toEqual(1)</code> it would have worked fine, but then I miss out on my original goal of enjoying the natural syntax of Chai and not remembering <em>yet another syntax</em>.</p>
<p>I needed a way to tell the Chai matchers to also increment that value whenever I used it. I knew how to increment the value using this <a href="http://bit.ly/2q9k5bv">handy method</a>:</p>
<pre><code class="language-javascript">originalExpect.setState({ assertionsMade: assertionsMade + 1 })
</code></pre>
<p>Telling Chai to run this statement whenever its matchers were accessed was a trickier matter. In comes <code>Object.defineProperty</code> to the rescue! It allows us, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">among other things</a>, to do something specific whenever that a property is accessed on an object. Essentially it works like this:</p>
<pre><code class="language-javascript">const myObj = {}
Object.defineProperty(myObj, 'foo', {
  get() {
    console.log('hello!')
    return 42
  }
})
myObj.foo // logs &quot;hello!&quot;, returns 42
</code></pre>
<p>This setup allows us to effectively create middleware on an object's properties, with potential use cases like logging the number of times it was accessed. While I don't recommend using it regularly in practice, since <code>Object.defineProperty</code> is clever, it does <em>exactly</em> what we need in this case where we're hacking some functionality together.</p>
<p>With Chai, we always end up using <code>.to</code> in our assertions, so it seemed like a reasonable place to stick our little &quot;middleware.&quot; Here's the final code:</p>
<pre><code class="language-javascript">global.expect = (actual) =&gt; {
  const originalMatchers = originalExpect(actual)
  const chaiMatchers = chai.expect(actual)

  // Add middleware to Chai matchers to increment Jest assertions made
  const { assertionsMade } = originalExpect.getState()
  Object.defineProperty(chaiMatchers, 'to', {
    get() {
      originalExpect.setState({ assertionsMade: assertionsMade + 1 })
      return chai.expect(actual)
    },
  })

  const combinedMatchers = Object.assign(chaiMatchers, originalMatchers)
  return combinedMatchers
}
Object.keys(originalExpect).forEach(key =&gt; (global.expect[key] = originalExpect[key]))
</code></pre>
<p>Note that we return <code>chai.expect(actual)</code>, i.e. the original intended value. We can't return <code>chaiMatchers.to</code> because that creates an infinite loop (whee!).</p>
<p>With this in your setup file, you have everything needed to make assertions about how many assertions should be made while still using the Chai syntax in your Jest tests.</p>
<p>I hope you enjoyed this article and learned something interesting in the process! Feedback is always welcome.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Source maps for Sentry: setting the UTF-8 encoding.]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>We use <a href="http://sentry.io">Sentry</a> at <a href="http://www.transparentclassroom.com">TransparentClassroom</a> to monitor errors in our front-end application. It's an excellent tool and has proven very useful, but for the longest time we could not get source maps to work correctly. As a consequence, we'd get woefully useless errors like these:</p>
<div style="text-align:center"><img src="https://www.andrewsouthpaw.com/content/images/2017/02/Screen-Shot-2017-02-06-at-12-26-29-PM.png" alt style="margin:1em 0;"></div>
<p>This article quickly covers how</p>]]></description><link>https://www.andrewsouthpaw.com/source-maps-for-sentry-setting-the-utf-8-encoding/</link><guid isPermaLink="false">5ba9dafb57dc045b69146b59</guid><category><![CDATA[frontend]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Fri, 17 Feb 2017 06:51:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>We use <a href="http://sentry.io">Sentry</a> at <a href="http://www.transparentclassroom.com">TransparentClassroom</a> to monitor errors in our front-end application. It's an excellent tool and has proven very useful, but for the longest time we could not get source maps to work correctly. As a consequence, we'd get woefully useless errors like these:</p>
<div style="text-align:center"><img src="https://www.andrewsouthpaw.com/content/images/2017/02/Screen-Shot-2017-02-06-at-12-26-29-PM.png" alt style="margin:1em 0;"></div>
<p>This article quickly covers how we set up source maps using Webpack and got them working correctly on Sentry, using some fixes that were not obvious and not covered by the Sentry documentation. It took me the better part of a day running into dead ends and chasing my tail before it was working end to end; hopefully this post saves you similar pain.</p>
<h1 id="settingupsourcemapsusingwebpack">Setting up source maps using Webpack.</h1>
<p>Webpack is an incredible tool, and a pain to understand. Fortunately, getting source maps to work on Webpack &quot;should&quot; only require one line to magically work:</p>
<pre><code class="language-javascript">config.devtool = /* your source map compilation setting goes here */
</code></pre>
<p>I followed an <a href="http://survivejs.com/webpack/building-with-webpack/source-maps/">excellent post by SurviveJS</a> to get my source maps working. It turns out source maps can be generated through many different means, which vary in speed and quality. The post covers the different kinds <a href="http://survivejs.com/webpack/building-with-webpack/source-maps/#source-map-types-supported-by-webpack">here</a>. For our setup, we do the following:</p>
<pre><code class="language-javascript">var production = process.env.NODE_ENV === 'production';

var config = {
  ...
}

if (production) {
  config.devtool = 'source-map';
} else {
  config.devtool = 'eval-source-map';
}
</code></pre>
<h2 id="checkingthatitworks">Checking that it works.</h2>
<p>If you're like us and use <code>eval-source-map</code> for development, you will not be outputting an actual <code>.map</code> file. See the (edited) output of our webpack:</p>
<pre><code>Version: webpack 1.14.0
                                            Asset       Size  Chunks             Chunk Names
                                application.en.js    5.18 MB       0  [emitted]  application.en
                                    manifest.json    3.71 kB          [emitted]
</code></pre>
<p>But, happily, it still works magically in the browser:</p>
<div style="text-align:center"><img src="https://www.andrewsouthpaw.com/content/images/2017/02/Screen-Shot-2017-02-06-at-12-06-17-PM.png" alt style="margin:1em 0;"></div>
<p>Notice the correct stack trace when you click on the error, and how it points to the correct file and line number in <code>boom.js</code>.</p>
<p>In production, the output should look something like this:</p>
<pre><code>Version: webpack 1.14.0
                                                Asset       Size  Chunks             Chunk Names
               application.en-c763e9250b27a905d9e7.js     761 kB       2  [emitted]  application.en
           application.en-c763e9250b27a905d9e7.js.map    4.44 MB       2  [emitted]  application.en
                                        manifest.json    5.04 kB          [emitted]
</code></pre>
<h2 id="gotchas">Gotchas.</h2>
<h3 id="remembertorestartyourwebpack">Remember to restart your Webpack.</h3>
<p>Not doing what you expected? Make sure you restart webpack, before digging in further.</p>
<h3 id="dontlistentosentryssetupforsourcemaps">Don't listen to Sentry's setup for source maps.</h3>
<p>Some tutorials for setting up source maps, such as <a href="https://docs.sentry.io/clients/javascript/sourcemaps/#webpack">this one from Sentry</a>, tell you to manually configure the source map output, like so:</p>
<pre><code class="language-javascript">module.exports = {
    // ... other config above ...
    output: {
      path: path.join(__dirname, 'dist'),
      filename: &quot;[name].js&quot;,
      source mapFilename: &quot;[name].js.map&quot;,
    }
};
</code></pre>
<p>My suggestion: <em>do not do this</em>, it will only end in tears.</p>
<h3 id="watchoutforuglifyjsoptimization">Watch out for UglifyJS optimization.</h3>
<p>You may be optimizing your UglifyJS plugin for production, in which case you'll need to specify that you still want source maps. We do it at the end in a specific segment of code that adds configuration specific to production, but you can place it wherever you actually set up the plugin:</p>
<pre><code class="language-javascript">if (production) {
  config.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compressor: { warnings: false },
      source map: true // &lt;-- this is what you need
    }),
  );
}
</code></pre>
<h1 id="settingupsentrytouseyoursourcemaps">Setting up Sentry to use your source maps.</h1>
<p>TransparentClassroom is served through a Rails server running on a Heroku deployment. Based on the <a href="https://docs.sentry.io/clients/javascript/sourcemaps/#making-source-maps-available-to-sentry">source map setup documentation for Sentry</a>, our source maps should've started working magically, but sadly they weren't. Sentry would report a cryptic error when we looked at the details on a user-generated error (note we use a Cloudfront distribution, but hitting <code>www.transparentclassroom.com</code> had the same effect):</p>
<pre><code>Source file was not 'utf8' encoding: https://d2ps218qravhxv.cloudfront.net/webpack/application.en-c763e9250b27a905d9e7.js.map
</code></pre>
<p>It turns out that Sentry does not automatically assume source maps are UTF-8 encoded (even though Webpack does <a href="https://github.com/webpack/webpack/pull/1797">this for us</a>). This is because, at least with our Rails server, the <code>.map</code> files had a <code>Content-Type</code> that did not specify UTF-8 encoding:</p>
<pre><code>$ curl -I https://d2ps218qravhxv.cloudfront.net/webpack/application.en-c5ebd83387db86032a23.js.map
HTTP/1.1 200 OK
...snip...
Content-Type: text/plain  # &lt;-- :-(
</code></pre>
<p>While some setups have artifacts served from S3 via Cloudfront, we choose to have Cloudfront capture artifacts on a cache miss; so the first time it will hit our server, after which point it will be cached in CF. This meant we needed to change the <code>Content-Type</code> for our <code>.map</code> files, which turned out to be relatively easy with Rails:</p>
<pre><code># config/initializers/mime_types.rb

Rack::Mime::MIME_TYPES[&quot;.map&quot;] = &quot;text/plain; charset=utf-8&quot;
</code></pre>
<p>Now when we hit the server, we get the correct Content-Type:</p>
<pre><code>$ curl -I https://d2ps218qravhxv.cloudfront.net/webpack/application.en-c5ebd83387db86032a23.js.map
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8  # :-)
</code></pre>
<p>Making this change FINALLY got souremaps working for us in Sentry:</p>
<div style="text-align:center"><img src="https://www.andrewsouthpaw.com/content/images/2017/02/Screen-Shot-2017-02-06-at-12-22-56-PM.png" alt style="margin:1em 0;"></div>
<h1 id="wrappingup">Wrapping up.</h1>
<p>Configuring source maps to work correctly in Sentry has been so valuable to us in our debugging process, as it's decidedly unpleasant to dig into minified, webpacked code and attempt to figure out it's corresponding location in your codebase. Hopefully this article has served you well! Let me know your thoughts or if you have any other insights to share!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Node: exploring asynchronous vs. multi-threaded approaches.]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I recently ran a small exercise to demonstrate the power, limitations, and workarounds of Node. In the process, I gained a deeper understanding of asynchronous operations, multi-threading, and forking. Many thanks to my mentor, Anoakie, for his valuable help in walking along with me for this exploration.</p>
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
<ul>
<li><a href="#whatnodedoesreallywell">What Node does really well</a></li>
<li><a href="#whatnodedoesnotsowell">What Node does not so well</a></li>
<li><a href="#whatnodedoesprettywell">What Node does pretty well</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<h1 id="whatnodedoesreallywell">What Node does really well</h1>
<p>Node was built from the ground up with asynchronicity in mind, leveraging the event loop of JavaScript. It can handle a lot of requests quickly by not waiting around for the request when there are certain kinds of work being done for the request, such as database requests.</p>
<p>Imagine you have a database operation that takes 10 seconds to complete, represented by a <code>setTimeout</code>:</p>
<pre><code class="language-javascript">router.route('/api/delayed')
  .get(function(req, res) {
    setTimeout(function() {
      res.end('foo');
    }, 10000);
  });

router.route('/api/immediate')
  .get(function(req, res) {
    res.end('bar');
  });
</code></pre>
<p>For a back end framework that does not support asynchronous execution, this situation is an anti-pattern: the server will hang as it waits for the database operation to complete and then fulfill the request. In Node, it fires off the operation and then returns to be ready to field the next incoming request. Once the operation finishes, it will be handled in an upcoming cycle of the event loop and the request gets fulfilled.</p>
<p>(In case the <code>&amp;</code> in the bash command throws you, it's essentially a way to tell bash to do two things in parallel.)</p>
<pre><code class="language-bash"># In a synchronous</code></pre>]]></description><link>https://www.andrewsouthpaw.com/node-exploring-asynchronous-vs-multi-threaded-approaches/</link><guid isPermaLink="false">5ba9d9d757dc045b69146b53</guid><category><![CDATA[backend]]></category><category><![CDATA[scaling]]></category><dc:creator><![CDATA[Andrew Smith]]></dc:creator><pubDate>Tue, 10 Mar 2015 06:46:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I recently ran a small exercise to demonstrate the power, limitations, and workarounds of Node. In the process, I gained a deeper understanding of asynchronous operations, multi-threading, and forking. Many thanks to my mentor, Anoakie, for his valuable help in walking along with me for this exploration.</p>
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
<ul>
<li><a href="#whatnodedoesreallywell">What Node does really well</a></li>
<li><a href="#whatnodedoesnotsowell">What Node does not so well</a></li>
<li><a href="#whatnodedoesprettywell">What Node does pretty well</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<h1 id="whatnodedoesreallywell">What Node does really well</h1>
<p>Node was built from the ground up with asynchronicity in mind, leveraging the event loop of JavaScript. It can handle a lot of requests quickly by not waiting around for the request when there are certain kinds of work being done for the request, such as database requests.</p>
<p>Imagine you have a database operation that takes 10 seconds to complete, represented by a <code>setTimeout</code>:</p>
<pre><code class="language-javascript">router.route('/api/delayed')
  .get(function(req, res) {
    setTimeout(function() {
      res.end('foo');
    }, 10000);
  });

router.route('/api/immediate')
  .get(function(req, res) {
    res.end('bar');
  });
</code></pre>
<p>For a back end framework that does not support asynchronous execution, this situation is an anti-pattern: the server will hang as it waits for the database operation to complete and then fulfill the request. In Node, it fires off the operation and then returns to be ready to field the next incoming request. Once the operation finishes, it will be handled in an upcoming cycle of the event loop and the request gets fulfilled.</p>
<p>(In case the <code>&amp;</code> in the bash command throws you, it's essentially a way to tell bash to do two things in parallel.)</p>
<pre><code class="language-bash"># In a synchronous world...
curl http://localhost:3000/api/delayed &amp; curl http://localhost:3000/api/immediate
# this returns 'foo' after 10s and 'bar' right after

# In an asynchronous world...
curl http://localhost:3000/api/delayed &amp; curl http://localhost:3000/api/immediate
# this returns 'bar' right away, and 'foo' 10s later
</code></pre>
<p>As long as we only write non-blocking code, our Node server will perform better than other backend languages, right? Right?...</p>
<h1 id="whatnodedoesnotsowell">What Node does not so well</h1>
<p>JavaScript is a single-threaded scripting language. Compared with other languages where you can spin off multiple threads to do concurrent processing, JavaScript performs work in a single thread.</p>
<p>Node, written in JavaScript, exhibits (suffers?) the same behavior. Some people like single-threaded because it keeps life simple, but it no longer leverages the power of ubiquitous multi-core processors.</p>
<p>Say you have a simple operation inside the Node server which operates on data. It could be simulated with a basic for loop:</p>
<pre><code class="language-javascript">router.route('/api/delayed')
  .get(function(req, res) {
    for (var i = 0; i &lt; 1000000000; i++) {}
    res.end('foo');
  });

router.route('/api/immediate')
  .get(function(req, res) {
    res.end('bar');
  });
</code></pre>
<p>In this example, asynchronocity will not save you. Run this in a server and it'll take ~2s to process. Imagine your receiving hundreds of concurrent requests for that same operation and you have a major problem on your hands.</p>
<pre><code class="language-bash">curl http://localhost:3000/api/delayed &amp; curl http://localhost:3000/api/immediate
# Returns 'foo' after 2s and 'bar' immediately after
</code></pre>
<p>Back end languages like PHP try to address the problem by creating multiple threads in which work can be done. While multi-threading opens up a different can of worms, at least it wouldn't hang in this situation. As a bonus, PHP tries to handle much of the multi-threading for you. (This is based off a very limited understanding of PHP, so corrections here are welcome.)</p>
<pre><code class="language-bash"># Assuming the server is equivalently written in PHP...
curl http://localhost:3000/api/delayed &amp; curl http://localhost:3000/api/immediate
# Returns 'bar' immediately and 'foo' 2s after.
</code></pre>
<p>Huh. That's a bummer. Node doesn't handle a commonplace situation nearly as well as PHP. It's beginning to look like a Node production server will need a separate &quot;crunch&quot; cluster to run numbers. Perhaps that separation of concerns (request handling vs. number crunching) is a good idea anyway, but right now it seems like an unfortunate limitation. What can be done about it?</p>
<h1 id="whatnodedoesprettywell">What Node does pretty well</h1>
<p>Node provides an easy way to <strong>fork</strong> multiple instances of Node, creating a cluster. There's <a href="http://cjihrig.com/blog/scaling-node-js-applications/">an excellent tutorial on the topic</a>. Here's the key bit of code, slightly modified for simplicity:</p>
<pre><code class="language-javascript">var cluster = require(&quot;cluster&quot;);
var numForks = 4;

if (cluster.isMaster) {
  for (var i = 0; i &lt; numForks; i++) {
    cluster.fork();
  }

  cluster.on(&quot;exit&quot;, function(worker, code, signal) {
    cluster.fork();
  });
} else {
  // Server creation code here
}
</code></pre>
<p>With this surprisingly small amount of code, you can create multiple forks. A fork is completely isolated, unlike threads; its in-memory store is not shared. Using this setup, the number-crunching code that originally caused the Node server to hang is now gracefully managed by sending subsequent requests off to forks that are available for doing work.</p>
<pre><code class="language-bash">curl http://localhost:3000/api/delayed &amp; curl http://localhost:3000/api/immediate
# Returns 'bar' immediately and 'foo' 2s after.
</code></pre>
<p>With the <a href="http://learnboost.github.io/cluster/">cluster</a> npm module, Node is back in the game and able to handle intensive data operations, much like PHP.</p>
<p>It's worth reiterating that these two approaches (forking vs. threading) are fundamentally different. <s>With forking, you cannot use multiple cores to speed up the processing of a particular operation. But, it can be used to handle multiple request concurrently when they are blocking operations. With threading, multiple cores can, in theory, be used to speed up the operations on a single request.</s> [EDIT] Forking creates its own process with access to its own memory. Threading, by contrast, preserves access to the same memory (which is both a feature and a source of consternation). However, forking can still be used to speed up the work of a single request. Forked processes can communicate with each other through the <code>child_process.fork()</code> <a href="http://nodejs.org/api/child_process.html#child_process.fork">API</a>. It's a similar model to web workers -- create an isolated environment to do some work, do the work, and return the results. Additionally, the <code>cluster</code> module allows for socket sharing across forks. [/EDIT -- thanks to John Jarvis for the tip.]</p>
<h1 id="conclusion">Conclusion</h1>
<p>It's hard to beat Node at asynchronous operations; while other languages like Ruby and Python support it, Node was structured expressly to optimize asynchronocity.</p>
<p>Meanwhile, the <code>cluster</code> module helps Node handle multiple requests with blocking operations concurrently through forks.</p>
<p>As is the case in much of software engineering, choosing one language/framework/technology/data structure or another is about a balance of tradeoffs. Node does some things really well, others not so much. Hopefully this post gave some insight into the balance of forces in Node.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>