<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Harold Treen</title>
    <description>Just another nerd.
</description>
    <link>https://haroldtreen.com/</link>
    <atom:link href="https://haroldtreen.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 05 Aug 2023 17:03:05 -0400</pubDate>
    <lastBuildDate>Sat, 05 Aug 2023 17:03:05 -0400</lastBuildDate>
    <generator>Jekyll v3.8.5</generator>
    
      <item>
        <title>Contributing to prettier-atom 💅</title>
        <description>&lt;p&gt;&lt;em&gt;“Contributing to {project}” is a series of blog posts where I highlight a helpful project I’m using and an open source contribution I made to it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Today I’m going to talk about &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier&lt;/code&gt;, the &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; package and how I reduced it’s activation time by 75%.&lt;/p&gt;

&lt;h2 id=&quot;what-is-prettier&quot;&gt;What is &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier&lt;/code&gt;?&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;prettier&lt;/code&gt; is an opinionated code formatter.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Should I break this chain of function calls into multiple lines?
Should I add a space before each bracket?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Deciding on a code format raises many mundane questions like these. In reality, the answers don’t really matter. The most important thing is to decide on a format and stick to it.&lt;/p&gt;

&lt;p&gt;Consistency.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;prettier&lt;/code&gt; is exactly that - a tool for consistently formatting your code to an opinionated style.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;prettier
npx prettier poorly-formatted.js
&lt;span class=&quot;c&quot;&gt;# -&amp;gt; Outputs nicely formatted file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;what-is-prettier-atom&quot;&gt;What is &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt;?&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; is a package for the &lt;a href=&quot;https://atom.io/&quot;&gt;atom editor&lt;/a&gt; that allows you to format open files.&lt;/p&gt;

&lt;p&gt;I really like having &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier&lt;/code&gt; in my editor because it allows me to format my files as I go. Rather than writing a bunch of code and formatting it before commit, I can see exactly what prettier is going to give me.&lt;/p&gt;

&lt;p&gt;This also helps me be more efficient as I code. Rather than spending time writing out spaces and brackets, I can just type code freely and prettier will handle the formatting on save.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; also integrates with &lt;a href=&quot;https://eslint.org/&quot;&gt;eslint&lt;/a&gt;. That means in addition to applying a consistent format, it can also fix linting issues (it does so by running the prettier output through &lt;code class=&quot;highlighter-rouge&quot;&gt;eslint --fix&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This helps reduce the number of linting issues I encounter when I go to commit.&lt;/p&gt;

&lt;p&gt;Amaze! 🎉&lt;/p&gt;

&lt;h2 id=&quot;finding-issues-with-prettier-atom&quot;&gt;Finding issues with &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;As much as I love the Atom editor, it can be quite slow at times. One of the things that slows atom down is “package activation”.&lt;/p&gt;

&lt;p&gt;Whenever atom boots, it runs an &lt;code class=&quot;highlighter-rouge&quot;&gt;activate&lt;/code&gt; function in each package. Activation allows packages to queue any initialization and get ready for use. It also blocks the editor from loading, so slow activation in a package can bring atom to a crawl.&lt;/p&gt;

&lt;p&gt;I had been noticing some lag with atom’s boot, so I opened up Timecop to see what might be causing the issue:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Atom -&amp;gt; Packages -&amp;gt; Timecop -&amp;gt; Show
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sure enough there were some packages taking a long time to activate - &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; being the worst offenders.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/timecop-prettier-before.png&quot; alt=&quot;Prettier w/ slow activation in Timecop&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This seemed like an issue. Most packages activate in &amp;lt; 50 ms. What would be causing &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; to take so much time?&lt;/p&gt;

&lt;h2 id=&quot;opening-an-issue&quot;&gt;Opening an issue&lt;/h2&gt;

&lt;p&gt;I’m pretty unfamiliar with atom packages - so I wanted to open an issue and get more info before trying to contribute.&lt;/p&gt;

&lt;p&gt;Here’s the repo for &lt;a href=&quot;https://github.com/prettier/prettier-atom/&quot;&gt;prettier-atom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The repo has an &lt;code class=&quot;highlighter-rouge&quot;&gt;ISSUE_TEMPLATE.md&lt;/code&gt;. This means when you go to open an issue, the description is pre-populated with a template. The one for &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; asks the submitter to double check the issue doesn’t already exist and include output from a &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; debug command.&lt;/p&gt;

&lt;p&gt;I followed those instructions and &lt;a href=&quot;https://github.com/prettier/prettier-atom/issues/330&quot;&gt;opened my issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The maintainer replied a few days later saying he’d done a bunch of things to reduce activation time, but was out of ideas. Receiving a reply that was receptive to help gave me the necessary encouragement to dig deeper.&lt;/p&gt;

&lt;h2 id=&quot;collecting-debug-information&quot;&gt;Collecting debug information&lt;/h2&gt;

&lt;p&gt;I did a simple google search for “Debugging Atom Packages” which led me to &lt;a href=&quot;https://flight-manual.atom.io/hacking-atom/sections/debugging/&quot;&gt;this handy page on debugging atom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Atom is basically a web application, so it has all the same debug tooling as Chrome. The article also mentioned a &lt;code class=&quot;highlighter-rouge&quot;&gt;--profile-startup&lt;/code&gt; flag that could be used to collect performance information for the initialization stage.&lt;/p&gt;

&lt;p&gt;I ran the following command in order to start atom and collect a profile of the startup phase.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;atom &lt;span class=&quot;nt&quot;&gt;--profile-startup&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;analyzing-profile-information&quot;&gt;Analyzing profile information&lt;/h2&gt;

&lt;p&gt;This is what the profile looked like in the Chrome javascript profiler.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/prettier-profile-full.png&quot; alt=&quot;Prettier javascript profile&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The chart shows all the function calls that happen during initialization. The length of the bar indicates how long the function ran for. The layers represent functions called from within other functions.&lt;/p&gt;

&lt;p&gt;In other words, it’s a &lt;a href=&quot;http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html&quot;&gt;flame graph&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By hovering over these bars, I was able to find the one corresponding to the &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom.activate&lt;/code&gt; function and dig into what was causing the slow activation time.&lt;/p&gt;

&lt;p&gt;Looking at the chart, a few things stood out.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Loading code adds up. Every &lt;code class=&quot;highlighter-rouge&quot;&gt;require&lt;/code&gt; triggers a file to be read, parsed and compiled.&lt;/li&gt;
  &lt;li&gt;One file was requiring something called &lt;code class=&quot;highlighter-rouge&quot;&gt;toConsumableArray&lt;/code&gt; which was taking 64ms to load.&lt;/li&gt;
  &lt;li&gt;Another file was requiring &lt;code class=&quot;highlighter-rouge&quot;&gt;lodash/fp&lt;/code&gt; which was taking 111ms to load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/consumable-array-load-time.png&quot; alt=&quot;consumable array load time&quot; /&gt;
&lt;img src=&quot;/assets/posts/lodash-load-time.png&quot; alt=&quot;lodash load time&quot; /&gt;&lt;/p&gt;

&lt;p&gt;These were both occurring from a &lt;code class=&quot;highlighter-rouge&quot;&gt;require&lt;/code&gt;. That means it wasn’t time spent computing useful stuff, it was time spent simply loading the libraries. Yuck!&lt;/p&gt;

&lt;p&gt;If we could avoid loading these packages, we would save ~170ms from the activation time! ⚡️&lt;/p&gt;

&lt;h2 id=&quot;optimization-1-removing-toconsumablearray&quot;&gt;Optimization 1: Removing toConsumableArray&lt;/h2&gt;

&lt;p&gt;I noticed that the &lt;code class=&quot;highlighter-rouge&quot;&gt;toConsumableArray&lt;/code&gt; import was coming from &lt;code class=&quot;highlighter-rouge&quot;&gt;babel-runtime&lt;/code&gt;. Babel runtime is a collection of polyfills to allow ES6 syntax in ES5 code. I looked at the file triggering the require, and sure enough there was some fancy syntax going on.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getAllScopes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getJavascriptScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getTypescriptScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getCssScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getJsonScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getGraphQlScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getMarkdownScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;...&lt;/code&gt; operator allows the arrays to be cleanly combined, but it’s also not supported in ES5. So babel sees that syntax and adds &lt;code class=&quot;highlighter-rouge&quot;&gt;toConsumableArray&lt;/code&gt; to polyfill the functionality.&lt;/p&gt;

&lt;p&gt;It’s nice syntax, but not nice enough to warrant 64ms of activation time. Converting the expression to an ES5 compatible version stopped &lt;code class=&quot;highlighter-rouge&quot;&gt;babel-runtime&lt;/code&gt; from being included.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getAllScopes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;getJavascriptScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;getTypescriptScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;getCssScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;getJsonScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;getGraphQlScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;getMarkdownScopes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sure enough, the require disappeared and the activation time reduced substantially.&lt;/p&gt;

&lt;h2 id=&quot;optimization-2-lazy-loading-lodash&quot;&gt;Optimization 2: Lazy loading lodash&lt;/h2&gt;

&lt;p&gt;A common pattern in nodejs code is to include all your requires at the top of the file.&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lodash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;reverseAndCompact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;reversed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;compact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Activating!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is nice for keeping track of what’s required, but slows down the initial load of the file. Anything that requires the above file will need to wait for &lt;code class=&quot;highlighter-rouge&quot;&gt;lodash&lt;/code&gt; to be fully parsed before it can even see the &lt;code class=&quot;highlighter-rouge&quot;&gt;reverseAndCompact&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;This is especially annoying if we just want to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;activate&lt;/code&gt; function. It doesn’t depend on &lt;code class=&quot;highlighter-rouge&quot;&gt;lodash&lt;/code&gt;, but still needs to wait for &lt;code class=&quot;highlighter-rouge&quot;&gt;lodash&lt;/code&gt; when it’s imported.&lt;/p&gt;

&lt;p&gt;Boo!&lt;/p&gt;

&lt;p&gt;This is more or less what was going on. One of the helper files was requiring &lt;code class=&quot;highlighter-rouge&quot;&gt;lodash/fp&lt;/code&gt; at the top of the file, despite only 1 function actually using it (and a function that was not needed for activation).&lt;/p&gt;

&lt;p&gt;The solution? Lazy loading!&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lazyLodash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lodash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;reverseAndCompact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;reversed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lazyLodash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;compact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Activating&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By placing our require within a function, we stop it from being loaded when the file is required. Now when I go to import the &lt;code class=&quot;highlighter-rouge&quot;&gt;activate&lt;/code&gt; function, there’s no waiting for lodash to be required.&lt;/p&gt;

&lt;p&gt;Those two changes saved the expected 111ms and more. Yay! 🎉&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/timecop-prettier-after.png&quot; alt=&quot;Prettier atom startup after&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;submitting-a-pr&quot;&gt;Submitting a PR&lt;/h2&gt;

&lt;p&gt;Once I had validated my fixes for the issue, I was ready to open a PR.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; repo contained a &lt;code class=&quot;highlighter-rouge&quot;&gt;CONTRIBUTING.md&lt;/code&gt; file with instructions for opening a PR.&lt;/p&gt;

&lt;p&gt;Some highlights from it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The project uses something called &lt;code class=&quot;highlighter-rouge&quot;&gt;nps&lt;/code&gt; or “node package scripts”. This means all the development scripts are run with &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn start &amp;lt;script-name&amp;gt;&lt;/code&gt;. The scripts were also defined in the &lt;code class=&quot;highlighter-rouge&quot;&gt;package-scripts.yml&lt;/code&gt; to reduce the size of &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The project has an &lt;code class=&quot;highlighter-rouge&quot;&gt;addContributor&lt;/code&gt; script. That script allows you to update the README with a link to your Github and notes about what you contributed. Such a cool way of acknowledging contributors!&lt;/li&gt;
  &lt;li&gt;To commit you use &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn start commit&lt;/code&gt;. This starts a little cli to create your commit. The command ensures that all commits conform to a consistent style and make things like generating a &lt;code class=&quot;highlighter-rouge&quot;&gt;CHANGELOG&lt;/code&gt; easier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I followed the instructions, &lt;a href=&quot;https://github.com/prettier/prettier-atom/pull/335&quot;&gt;opened a PR&lt;/a&gt; and had my changes merged within a few days!&lt;/p&gt;

&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;/h2&gt;

&lt;p&gt;Contributing to &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; was a great experience. Many projects I’ve contributed to in the past are pretty ad-hoc and don’t have a clear process for contributing. The maintainers of &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; are very experienced open source maintainers and seeing their process taught me a lot about managing my own open source projects.&lt;/p&gt;

&lt;p&gt;Some other learnings…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Profile your code:&lt;/strong&gt; It’s amazing the optimizations you can find if you just dig a little. You can’t understand the performance of your code by simply reading it. You need to run it and analyze it. I would never have guessed imports accounted for 75% of startup time.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Improving performance is a great contribution:&lt;/strong&gt; Most people aren’t profiling their code, which makes it a great area to look for bugs. It’s also extremely satisfying to have a measurable impact on the project.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Babel has a cost:&lt;/strong&gt; Writing code with the latest ES6 features is all the craze, but there’s not much discussion about the cost of doing so. Simple things like using the &lt;code class=&quot;highlighter-rouge&quot;&gt;...&lt;/code&gt; operator might require extra dependencies. How much are you willing to slow down your code to use the new fancy syntax?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Open source is a great way to learn about project management:&lt;/strong&gt; Seeing the amount of tooling and documentation that existed for &lt;code class=&quot;highlighter-rouge&quot;&gt;prettier-atom&lt;/code&gt; was really inspiring. Having a command to update your contributors list? For generating a release? For creating consistent commits? These are things I’d never really seen. It’s a great lesson in making projects beginner friendly and easy to setup. These things are easy to gloss over, but provide a lot of value in the long run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m going to continue looking for ways to speed up my atom activation 😊.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to @cqfd and @vaibhavsagar for helping me make this post prettier 💅.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 15 Jan 2018 00:00:00 -0500</pubDate>
        <link>https://haroldtreen.com/tech/open-source/contributing-to/2018/01/15/contributing-to-prettier-atom/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/open-source/contributing-to/2018/01/15/contributing-to-prettier-atom/</guid>
        
        
        <category>tech</category>
        
        <category>open-source</category>
        
        <category>contributing-to</category>
        
      </item>
    
      <item>
        <title>Contributing to redux-saga-tester ⚛️</title>
        <description>&lt;p&gt;Hello internet! It’s been a while.&lt;/p&gt;

&lt;p&gt;I’ve been getting back into open source recently by contributing to some libraries I use.&lt;br /&gt;
When it comes to open source there seems to be a lot of questions:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How do I find a project to contribute to?&lt;br /&gt;
How do I find an issue to work on?&lt;br /&gt;
How do I open a PR without looking like a n00b? I don’t want to look like a n00b! 😭&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I thought it would be fun to turn my OS contributions into blog posts!
Hopefully it can inform people about cool libraries and the process of becoming project contributor.&lt;/p&gt;

&lt;p&gt;So without further ado, I present…&lt;/p&gt;

&lt;h2 align=&quot;center&quot;&gt;The &lt;i&gt;&quot;Contributing to {project}&quot;&lt;/i&gt; Series! 🎉&lt;/h2&gt;

&lt;p&gt;In today’s edition:&lt;/p&gt;

&lt;h2 id=&quot;contributing-to-redux-saga-tester&quot;&gt;Contributing to &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt; is a library to simplify testing redux sagas.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;…???&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alright… that might not mean anything to anyone. Let’s take a step back…&lt;/p&gt;

&lt;p&gt;(Or &lt;a href=&quot;#what-is-redux-saga-tester&quot;&gt;skip ahead&lt;/a&gt; if I’m preaching to the choir!)&lt;/p&gt;

&lt;h3 id=&quot;what-is-redux&quot;&gt;What is Redux?&lt;/h3&gt;

&lt;p&gt;Redux is a state management library for javascript. It allows you to take all the state in your application and centralize it to one spot. It also enforces consistent conventions for reading and updating that state.&lt;/p&gt;

&lt;p&gt;The heart of redux is called the &lt;code class=&quot;highlighter-rouge&quot;&gt;store&lt;/code&gt;. All reading and writing to the state is done through the store.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createStore&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;redux&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;reducer&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;./reducer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reducer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In redux, state mutations are done by dispatching an &lt;code class=&quot;highlighter-rouge&quot;&gt;action&lt;/code&gt; to the store. An action is a plain javascript object describing a change:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ADD_TODO&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Use Redux&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Actions are taken by redux and handed off to a &lt;code class=&quot;highlighter-rouge&quot;&gt;reducer&lt;/code&gt; (that thing we passed &lt;code class=&quot;highlighter-rouge&quot;&gt;createStore&lt;/code&gt; above).
A reducer is a pure function that takes the current state, an action and returns new state.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;initialState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todoReducer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;initialState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ADD_TODO&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
			&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;newTodo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newTodo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
		&lt;span class=&quot;nl&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;newState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todoReducer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// -&amp;gt; { todos: [{ id: 10, description: &quot;Use Redux&quot;}] }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Your application can then &lt;code class=&quot;highlighter-rouge&quot;&gt;subscribe&lt;/code&gt; to the store and render the new state.&lt;/p&gt;

&lt;div class=&quot;language-jsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TodoList&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
				&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
					&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;reduxStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;subscribe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;reduxStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TodoList&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;todos=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;,&lt;/span&gt;
		&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s all you really need to know!&lt;/p&gt;

&lt;p&gt;Here’s a link to the &lt;a href=&quot;https://redux.js.org/&quot;&gt;docs&lt;/a&gt; in case you want to dig deeper.&lt;/p&gt;

&lt;h3 id=&quot;what-is-redux-saga&quot;&gt;What is &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga&lt;/code&gt;?&lt;/h3&gt;

&lt;p&gt;Cool! So &lt;code class=&quot;highlighter-rouge&quot;&gt;redux&lt;/code&gt; is this thing that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Accepts &lt;code class=&quot;highlighter-rouge&quot;&gt;actions&lt;/code&gt; (plain javascript objects)&lt;/li&gt;
  &lt;li&gt;Passes them to a &lt;code class=&quot;highlighter-rouge&quot;&gt;reducer&lt;/code&gt; (plain javascript function)&lt;/li&gt;
  &lt;li&gt;And returns the new state (plain javascript object)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This model works great for synchronous state changes…&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I have a todo! Add it to my state plz!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But it doesn’t really work great for asynchronous state changes…&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Make a network request for my todos! Show an error if the request fails!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Enter &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-sagas&lt;/code&gt;, a redux middleware.&lt;/p&gt;

&lt;p&gt;Reducers listen for actions with a certain &lt;code class=&quot;highlighter-rouge&quot;&gt;type&lt;/code&gt; and perform synchronous updates to the state.&lt;br /&gt;
Sagas are generator functions that listen for actions with a certain &lt;code class=&quot;highlighter-rouge&quot;&gt;type&lt;/code&gt; and perform asynchronous updates to the state.&lt;/p&gt;

&lt;p&gt;You might have a &lt;code class=&quot;highlighter-rouge&quot;&gt;fetchTodosSaga&lt;/code&gt; that listens for a &lt;code class=&quot;highlighter-rouge&quot;&gt;FETCH_TODOS&lt;/code&gt; action and handles the necessary network requests.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetchTodos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fetchTodos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;FETCH_TODOS_SUCCEEDED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;FETCH_TODOS_FAILED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetchTodosSaga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;takeLatest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;FETCH_TODOS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetchTodos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(&lt;code class=&quot;highlighter-rouge&quot;&gt;takeLatest&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; are just functions to listen for actions and dispatch other actions)&lt;/p&gt;

&lt;p&gt;This is nice because we can trigger complex behavior with actions along with update the state.&lt;/p&gt;

&lt;p&gt;…Once again, you can find much more info in the &lt;a href=&quot;https://redux-saga.js.org/&quot;&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;what-is-redux-saga-tester&quot;&gt;What is redux-saga-tester?&lt;/h3&gt;

&lt;p&gt;Great! So redux and redux-sagas allow us to centralize all our state storage and management.&lt;/p&gt;

&lt;p&gt;But now that we have all this logic in sagas… how do we test it?&lt;/p&gt;

&lt;p&gt;According to the &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga&lt;/code&gt; &lt;a href=&quot;https://redux-saga.js.org/docs/advanced/Testing.html&quot;&gt;docs&lt;/a&gt;, by calling the saga and inspecting the yielded values.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;fetches the todos&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;generator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetchTodos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;generator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fetchTodos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;generator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;FETCH_TODOS_SUCCEEDED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But this is not ideal…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What if we add an intermediate yields between the first API call and the dispatched action?&lt;/li&gt;
  &lt;li&gt;What if the order values are yielded changes?&lt;/li&gt;
  &lt;li&gt;What if we have a lot of steps in our saga?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These types of tests end up being long and fragile (any change to the saga offsets everything and breaks the test).&lt;/p&gt;

&lt;p&gt;In reality, we don’t really care all the nitty gritty details of what our &lt;code class=&quot;highlighter-rouge&quot;&gt;fetchTodos&lt;/code&gt; saga is doing.&lt;/p&gt;

&lt;p&gt;Does it log stuff? Does it dispatch other actions? What are the order of those?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;¯\_(ツ)_/¯&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What we care is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It runs when we dispatch &lt;code class=&quot;highlighter-rouge&quot;&gt;FETCH_TODOS&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;A network call is made for todos (or our API library is called).&lt;/li&gt;
  &lt;li&gt;The returned todos end up in the store.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So something like this:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;fetches the todos&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;sinon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;fetchTodos&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolves&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fetchTodosSaga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;FETCH_TODOS&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
	&lt;span class=&quot;kr&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sagaTest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;waitFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;FETCH_TODOS_SUCCEEDED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fetchTodos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;called&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toBeTrue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This setup is much nicer.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We’re using the saga the same way it will run in our application.&lt;/li&gt;
  &lt;li&gt;The test describes behavior instead of implementation details.&lt;/li&gt;
  &lt;li&gt;Our test is less likely to break due to minor changes to the saga.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second setup is what’s enabled by &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt;. It allows you to run your sagas to completion and observe the resulting actions and state changes.&lt;/p&gt;

&lt;h3 id=&quot;finding-issues-in-redux-saga-tester&quot;&gt;Finding issues in &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt; is a library I discovered after becoming frustrated with the recommended testing strategy.&lt;/p&gt;

&lt;p&gt;Originally when I read the docs for &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga&lt;/code&gt; and “How To Test”, it simply read:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;WIP
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/redux-saga/redux-saga/blob/2013a1f2fd2abafb5bc30a0c37b92b6d4c695882/docs/advanced/Testing.md&quot;&gt;Not super helpful…&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How can they recommend these patterns without also understanding the testing implications?!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I began googling around and eventually found a &lt;a href=&quot;https://github.com/redux-saga/redux-saga/issues/518&quot;&gt;github comment&lt;/a&gt; by the creator of &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt; describing their workaround. Switching to &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt; instantly made my tests simpler and more robust.&lt;/p&gt;

&lt;p&gt;But while writing tests with &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt; there was a strange error I would run into.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Timeout - Async callback was not invoked within timeout specified.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wahhh? 😰&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It turned out to be caused by the &lt;code class=&quot;highlighter-rouge&quot;&gt;waitFor&lt;/code&gt; method.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;waitFor might never resolve&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fetchTodosSaga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kr&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;waitFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;THIS_ACTION_WILL_NEVER_DISPATCH&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Boom 💥&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;waitFor&lt;/code&gt; allows the saga to run and resolves when a certain type of action is seen.&lt;/p&gt;

&lt;p&gt;Unfortunately, &lt;code class=&quot;highlighter-rouge&quot;&gt;waitFor&lt;/code&gt; would not resolve if the action never occurred. The saga might run to completion, but the &lt;code class=&quot;highlighter-rouge&quot;&gt;waitFor&lt;/code&gt; would never get resolved.&lt;/p&gt;

&lt;p&gt;This was annoying for a few reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The error was a timeout, so the test suite would hang for 5 seconds failing.&lt;/li&gt;
  &lt;li&gt;The error was extremely unhelpful (&lt;code class=&quot;highlighter-rouge&quot;&gt;timeout&lt;/code&gt; provides no indication what went wrong).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I &lt;a href=&quot;https://github.com/wix/redux-saga-tester/issues/32&quot;&gt;opened an issue&lt;/a&gt; on the repo which received a few responses from others also experiencing the issue. Normally I’d wait for the maintainer to comment before moving forward with a fix, but enough people seemed effected that I decided to work on it.&lt;/p&gt;

&lt;h3 id=&quot;fixing-the-issue-and-opening-a-pr&quot;&gt;Fixing the issue and opening a PR&lt;/h3&gt;

&lt;p&gt;For the longest time I let the issue sit.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I don’t want to dig through the internals to figure out how it works. It’s probably complicated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eventually I realized that the first step to fixing the issue wasn’t “learn how everything works”. It was simply “write a test that demonstrates the issue”.&lt;/p&gt;

&lt;p&gt;Luckily the library had a nice test suite. I was able to capture the issue with a simple test.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Rejects if saga completes without emitting awaited action&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({});&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NON_EMITTED_ACTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;NON_EMITTED_ACTION&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;emptySaga&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;emptySaga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wait&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sagaTester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;waitFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NON_EMITTED_ACTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;be&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rejectedWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NON_EMITTED_ACTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once there was something exposing the issue, working on a fix was much easier. I could read through the code, add console statements and inspect what was being run with my test. That was all the momentum I needed in order to implement a fix.&lt;/p&gt;

&lt;p&gt;Turns out that running a saga creates a promise to alert when it’s complete. Nothing was listening for that completion, so I added a callback to verify the awaited actions.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_verifyAwaitedActionsCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actionLookups&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actionType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actionLookups&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actionType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
				&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;actionType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; was waited for but never called&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_verifyAwaitedActionsCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Whenever &lt;code class=&quot;highlighter-rouge&quot;&gt;waitFor&lt;/code&gt; is called, it saves the promise in the &lt;code class=&quot;highlighter-rouge&quot;&gt;actionLookups&lt;/code&gt; object. This object also stores the number of times that action was dispatched. My function looked for actions with no dispatches and rejected their unresolved promises.&lt;/p&gt;

&lt;p&gt;This got my test passing! Yay! 🙌&lt;/p&gt;

&lt;p&gt;I pushed the change to my fork and &lt;a href=&quot;https://github.com/wix/redux-saga-tester/pull/43&quot;&gt;opened a PR&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt; doesn’t have a &lt;code class=&quot;highlighter-rouge&quot;&gt;CONTRIBUTING.md&lt;/code&gt; or a &lt;code class=&quot;highlighter-rouge&quot;&gt;PULL_REQUEST_TEMPLATE.md&lt;/code&gt;, so I just ensured my commit history was minimal, the commit messages were clear and my pull request was well explained.&lt;/p&gt;

&lt;p&gt;A few days later the maintainer merged the change after some additional testing 🎉.&lt;/p&gt;

&lt;h3 id=&quot;updating-the-readme&quot;&gt;Updating the README&lt;/h3&gt;

&lt;p&gt;While working through this issue, I was surprised to discover some additional functionality that wasn’t documented. The README contained some usage examples, but gave no overview of the API.&lt;/p&gt;

&lt;p&gt;Having to read the code to learn about everything was not ideal, so I added a more formal API to the README. Once it seemed to match the source files, I &lt;a href=&quot;https://github.com/wix/redux-saga-tester/pull/44&quot;&gt;opened a PR for that&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It was merged with no additional comments 😊.&lt;/p&gt;

&lt;p&gt;You can view that API &lt;a href=&quot;https://github.com/wix/redux-saga-tester#api&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;takeaways&quot;&gt;Takeaways&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Test behavior, not implementation:&lt;/strong&gt; Seeing the tests for redux-saga made it extremely clear why testing implementation is a bad idea. Tests become extremely flakey! If your tests are too coupled to your implementation, it may be a sign to test at a higher level. &lt;code class=&quot;highlighter-rouge&quot;&gt;redux-saga-tester&lt;/code&gt; allows for testing at a higher level where you don’t need to think about implementation details.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Open Issues:&lt;/strong&gt; It takes very little effort and is the first step to discovering whether others want a fix and if the maintainer is responsive.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Start with a test:&lt;/strong&gt; Digging through source files can be very intimidating if you don’t know the project. Writing a test is a great way to expose the issue and provide a path to implementing a fix.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Improve the project:&lt;/strong&gt; As a new contributor you have insights into the project that the maintainers don’t have. Is this project easy to understand? Easy to contribute to? Is there any documentation missing? Once you’ve got your feet in the water, you’ll likely be able to spot other things that can be improved… improve them!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So there you go! A fun open source contribution I made over a weekend.&lt;/p&gt;

&lt;p&gt;Now go forth and contribute to a library that you’re using!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to @cqfd, @jimjshields and @vaibhavsagar for thoughts and feedback!&lt;/em&gt; 😊&lt;/p&gt;
</description>
        <pubDate>Sat, 13 Jan 2018 00:00:00 -0500</pubDate>
        <link>https://haroldtreen.com/tech/open-source/contributing-to/2018/01/13/contributing-to-redux-saga-tester/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/open-source/contributing-to/2018/01/13/contributing-to-redux-saga-tester/</guid>
        
        
        <category>tech</category>
        
        <category>open-source</category>
        
        <category>contributing-to</category>
        
      </item>
    
      <item>
        <title>Debugging A Passive Aggressive Server 🤖</title>
        <description>&lt;p&gt;Since last year, I’ve been working on a project called &lt;a href=&quot;/projects/#epubpress&quot;&gt;EpubPress&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(It’s a 
&lt;a href=&quot;https://chrome.google.com/webstore/detail/epubpress-read-the-web-of/pnhdnpnnffpijjbnhnipkehhibchdeok?hl=en&quot;&gt;Chrome extension&lt;/a&gt;,
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/epub-read-the-web-offline/&quot;&gt;Firefox extension&lt;/a&gt;,
&lt;a href=&quot;https://www.npmjs.com/package/epub-press-js&quot;&gt;npm module&lt;/a&gt; and 
&lt;a href=&quot;https://epub.press&quot;&gt;web service&lt;/a&gt; 
for creating ebooks from a collection of web articles.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;EpubPress and I generally get along great.&lt;/p&gt;

&lt;p&gt;It serves my requests. It restores from errors. It does what’s expected.&lt;/p&gt;

&lt;p&gt;But all that being said, I’d noticed a persistent issue with EpubPress - &lt;strong&gt;sometimes it would just stop talking to me&lt;/strong&gt; 😭.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;EpubPress! Give me the homepage!&lt;br /&gt;
*crickets* … *timeout*&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;EpubPress! Let me connect to you via SSH!&lt;br /&gt;
*crickets* … *timeout*&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;EpubPress! Respond to my pings!&lt;br /&gt;
*crickets* … *timeout*&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What was going on? It had just created a beautiful book for me an hour ago! Why the cold shoulder?&lt;/p&gt;

&lt;p&gt;Whenever this happened, I would go through the same steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Is the server overloaded?&lt;/strong&gt; Nope. CPU usage was stable.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Did the app need a restart?&lt;/strong&gt; Nope. App is running fine.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Had Nginx failed?&lt;/strong&gt; Nope. Nginx was working normal.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Did the logs for the instance have clues?&lt;/strong&gt; Nope. Nothing out of the usual.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By this point I’d be freaking out. My server was losing ‘nines’ of uptime by the minute!&lt;/p&gt;

&lt;p&gt;My last resort was to restart the machine - that put everything back to normal. Phew! 😌&lt;/p&gt;

&lt;p&gt;…But only for so long.&lt;/p&gt;

&lt;p&gt;By the next day, the issue would be happening again 😫.&lt;/p&gt;

&lt;h2 id=&quot;enough-is-enough&quot;&gt;Enough is enough&lt;/h2&gt;

&lt;p&gt;Communication is important to me - so I was bothered that my cherished server wasn’t using its words.&lt;/p&gt;

&lt;p&gt;After multiple occurrences of this issue, I decided to get to the bottom of it.&lt;/p&gt;

&lt;h3 id=&quot;talking-to-friends&quot;&gt;Talking to friends&lt;/h3&gt;

&lt;p&gt;When someone is giving you the silent treatment - sometimes you can find out why via a friend.&lt;/p&gt;

&lt;p&gt;In this metaphor, my friend was &lt;a href=&quot;http://downforeveryoneorjustme.com/epub.press&quot;&gt;DownForEveryoneOrJustMe&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Harold:&lt;/strong&gt; Hey DownForEveryoneOrJustMe, EpubPress is ignoring me. Is it talking to you?&lt;br /&gt;
&lt;strong&gt;DownForEveryoneOrJustMe:&lt;/strong&gt; EpubPress is talking to me. Problem is only for you!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Huh? That can’t be true…&lt;br /&gt;
I tried talking to EpubPress via another server.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Harold:&lt;/strong&gt; Hey HaroldTreen.com, is EpubPress talking to you these days?&lt;br /&gt;
&lt;strong&gt;HaroldTreen.com:&lt;/strong&gt; It sure is! EpubPress is responding to all my texts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What?! Betrayal! 🔥😡🔥&lt;/p&gt;

&lt;p&gt;I now knew that…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;EpubPress was not responding to anything I sent it.&lt;/li&gt;
  &lt;li&gt;It wasn’t because EpubPress was busy. I checked and it was sitting idle at home.&lt;/li&gt;
  &lt;li&gt;It wasn’t because EpubPress was unwell. All the internal components were operational.&lt;/li&gt;
  &lt;li&gt;It wasn’t because EpubPress was anti-social. It was talking to everyone else.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was stumped.&lt;/p&gt;

&lt;h3 id=&quot;reaching-out-to-others&quot;&gt;Reaching out to others&lt;/h3&gt;

&lt;p&gt;At this point, I decided I needed more guidance. What else could cause my server to ignore me at random?&lt;/p&gt;

&lt;p&gt;Luckily &lt;a href=&quot;/tech/recurse/2017/01/27/recurse-center-return-statement/&quot;&gt;I had attended a batch at the Recurse Center&lt;/a&gt; and had &lt;a href=&quot;https://www.recurse.com/blog/112-how-rc-uses-zulip&quot;&gt;a community of knowledgeable programmers&lt;/a&gt; who might be able to help.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/timeout-debugging-zulip.jpg&quot; alt=&quot;Zulip message&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;My pleas for help on Zulip.&lt;/p&gt;

&lt;p&gt;From there, I heard from @pirate and @imccoy who helped me do some better debugging™.&lt;/p&gt;

&lt;h2 id=&quot;better-debugging-&quot;&gt;Better debugging ™&lt;/h2&gt;

&lt;p&gt;My initial debugging strategies were pretty rudimentary.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Restart &lt;code class=&quot;highlighter-rouge&quot;&gt;nginx&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Restart &lt;code class=&quot;highlighter-rouge&quot;&gt;pm2&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Make a request using Chrome.&lt;/li&gt;
  &lt;li&gt;Make a request using &lt;code class=&quot;highlighter-rouge&quot;&gt;curl&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;grep&lt;/code&gt; some log files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Talking to others introduced to me to an awesome set of tools that helped get to the root of the issue.&lt;/p&gt;

&lt;h3 id=&quot;netstat&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;netstat&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;netstat&lt;/code&gt; (network statistics) is a command line tool for displaying information on network traffic. I used it to see all the ports my server was listening to.&lt;/p&gt;

&lt;p&gt;Using the &lt;code class=&quot;highlighter-rouge&quot;&gt;netstat -ap&lt;/code&gt;, I was also able to see what processes were listening to each port. There was a normal number of connections and my app was listening to the right ports…&lt;/p&gt;

&lt;p&gt;In the output you can see &lt;code class=&quot;highlighter-rouge&quot;&gt;nginx&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;pm2&lt;/code&gt; connected and listening away:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name
unix  3      [ ]         STREAM     CONNECTED     XXXXXX   31485/nginx -g daem 
unix  3      [ ]         STREAM     CONNECTED     XXXXXX   31485/nginx -g daem
unix  2      [ ACC ]     STREAM     LISTENING     XXXXX    1486/.pm2)
unix  2      [ ACC ]     STREAM     LISTENING     XXXXX    1486/.pm2)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Maybe my packets aren’t making it to the server?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;mtr&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;mtr&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;mtr&lt;/code&gt; (my traceroute) is a program that combines traceroute and ping. It continually pings the provided host and shows a live view of the path taken to deliver the ping.&lt;/p&gt;

&lt;p&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;mtr &amp;lt;host&amp;gt;&lt;/code&gt;, I was able to see how packets were travelling to EpubPress. I noticed packets were getting blocked somewhere down the line (all the &lt;code class=&quot;highlighter-rouge&quot;&gt;???&lt;/code&gt;s).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/timeout-debugging-mtr.jpg&quot; alt=&quot;MTR output&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;mtr epub.press&lt;/code&gt; output. At hop 13, packets are swallowed into the void.&lt;/p&gt;

&lt;p&gt;It’s interesting to note that some intermediate servers were also returning &lt;code class=&quot;highlighter-rouge&quot;&gt;???&lt;/code&gt;s. This could be because they are configured to forward traffic but ignore pings. That’s fine, but my server is not one to ignore a friendly ping.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Could it be a server in the middle ignoring me?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;tcpdump&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;tcpdump&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;tcpdump&lt;/code&gt; is a program that lets you inspect all the packets being sent and received by a machine. It was like peeking into EpubPress’s brain and seeing every word received and how it was responding.&lt;/p&gt;

&lt;p&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;tcpdump host &amp;lt;my-ip&amp;gt;&lt;/code&gt; I discovered that my packets were arriving, but no packets were being returned. Not even a modest &lt;code class=&quot;highlighter-rouge&quot;&gt;SYN-ACK&lt;/code&gt;s was being returned 😥.&lt;/p&gt;

&lt;p&gt;This is what &lt;code class=&quot;highlighter-rouge&quot;&gt;tcpdump&lt;/code&gt; produced on the server while my laptop was sending pings:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;06:08:21.069515 IP pool-XXX-XX-XXX-XX.nycmny.fios.verizon.net &amp;gt; epubpress-backend.c.epubpress-XXXX.internal: ICMP echo request, id 10677, seq 33022, length 44
06:08:21.167963 IP pool-XXX-XX-XXX-XX.nycmny.fios.verizon.net &amp;gt; epubpress-backend.c.epubpress-XXXX.internal: ICMP echo request, id 10677, seq 33023, length 44
...etc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is what working output looks like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;06:13:49.763522 IP pool-XXX-XX-XXX-XX.nycmny.fios.verizon.net &amp;gt; epubpress-backend.c.epubpress-XXXX.internal: ICMP echo request, id 10770, seq 33161, length 44
06:13:49.763556 IP epubpress-backend.c.epubpress-XXXX.internal &amp;gt; pool-XXX-XX-XXX-XX.nycmny.fios.verizon.net: ICMP echo reply, id 10770, seq 33161, length 44
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ping&lt;/code&gt; uses a protocol called &lt;code class=&quot;highlighter-rouge&quot;&gt;ICMP&lt;/code&gt; (Internet Control Message Protocol). No matter how many &lt;code class=&quot;highlighter-rouge&quot;&gt;ICMP echo&lt;/code&gt; requests I sent, EpubPress would not reply.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Could it be a firewall issue?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;netcat&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;netcat&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;netcat&lt;/code&gt; is a program for reading/writing directly to a network connection. I think of it like &lt;code class=&quot;highlighter-rouge&quot;&gt;cat&lt;/code&gt;, but for printing whatever a given port receives.&lt;/p&gt;

&lt;p&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;nc &amp;lt;host&amp;gt; &amp;lt;port&amp;gt;&lt;/code&gt; on both machines, I was able to test if a program separate from my application could communicate back to my laptop. As expected, this did not work - but I tried it anyway because it was fun using all these new tools.&lt;/p&gt;

&lt;p&gt;On working computers, I was able to type in the terminal and see the characters appear on the other end! Wow!&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Teehee, I’m chatting with myself!&lt;br /&gt;
*5 minutes later*&lt;br /&gt;
Alright, enough tomfoolery! What is our firewall doing…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;iptables&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;iptables&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;iptables&lt;/code&gt; is a tool for modifying tables of firewall rules. It can be used to define how individual packets should be treated.&lt;/p&gt;

&lt;p&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;iptables -L&lt;/code&gt; I was able to list all the rules in the tables. Sure enough, there it was:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;chain sshguard (1 references)
target     prot opt source               destination
DROP       all  --  &amp;lt;my-ip&amp;gt;              anywhere
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;sshguard&lt;/code&gt; chain had a rule for blocking all my requests! 😱&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Who is this sshguard character?!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;sshguard&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;sshguard&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;sshguard&lt;/code&gt; is a tool for protecting against brute force attacks. It aggregates and inspects system logs to detect suspicious activity. It then blocks the suspicious traffic.&lt;/p&gt;

&lt;p&gt;In other words, EpubPress had this friend &lt;code class=&quot;highlighter-rouge&quot;&gt;sshguard&lt;/code&gt; who I didn’t know existed. &lt;code class=&quot;highlighter-rouge&quot;&gt;sshguard&lt;/code&gt; had noticed me constantly talking to EpubPress and become worried whether this was a good use of EpubPress’s time.&lt;/p&gt;

&lt;p&gt;So &lt;code class=&quot;highlighter-rouge&quot;&gt;sshguard&lt;/code&gt; decided to brainwash EpubPress into ignoring me so it could focus on creating books.&lt;/p&gt;

&lt;h2 id=&quot;issue-solved-&quot;&gt;Issue Solved 🎉&lt;/h2&gt;

&lt;p&gt;I had a talk with &lt;code class=&quot;highlighter-rouge&quot;&gt;sshguard&lt;/code&gt;, settled our differences and had it add me to its whitelist.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sshguard -w &amp;lt;my-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now whenever I to talk to EpubPress, &lt;code class=&quot;highlighter-rouge&quot;&gt;sshguard&lt;/code&gt; doesn’t try to interfere.&lt;/p&gt;

&lt;h2 id=&quot;the-moral-of-the-story&quot;&gt;The moral of the story?&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Smart tools exist for protecting against brute force attacks!&lt;/li&gt;
  &lt;li&gt;Sometimes strange problems arise and it makes no sense what’s going on - but if you dig deep enough you’ll likely find a fascinating explanation!&lt;/li&gt;
  &lt;li&gt;Reach out to others when you’re facing an issue - they might have a wider array of tools to help debug the problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;EpubPress and I resolved our differences and we are looking forward to making more beautiful ebooks together.&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;strong&gt;The End&lt;/strong&gt;&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;👨❤️🤖&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to @jvns and @vaibhavsagar for helping me debug this blog post 💕.&lt;/em&gt;&lt;/p&gt;

</description>
        <pubDate>Sun, 11 Jun 2017 00:00:00 -0400</pubDate>
        <link>https://haroldtreen.com/tech/epub-press/debugging/server/2017/06/11/debugging-passive-aggressive-server/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/epub-press/debugging/server/2017/06/11/debugging-passive-aggressive-server/</guid>
        
        
        <category>tech</category>
        
        <category>epub-press</category>
        
        <category>debugging</category>
        
        <category>server</category>
        
      </item>
    
      <item>
        <title>Two Months Of Tech Interviews 💼</title>
        <description>&lt;p&gt;The time finally came.&lt;/p&gt;

&lt;p&gt;Full. Time. Job. Search.&lt;/p&gt;

&lt;p&gt;Over the last 5 years, I’ve accumulated over 2.5 years of paid software engineering experience. I’ve also accumulated a fair amount of self-directed experience.&lt;/p&gt;

&lt;p&gt;But, I’ve never accepted a full-time job…&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sorry, I have more school to finish.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sorry, I want to work in a different city.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sorry, I want to travel and focus on my own projects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sorry, I want to attend the Recurse Center.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;…until now.&lt;/p&gt;

&lt;p&gt;On Monday, I accepted a full-time offer with &lt;a href=&quot;https://www.squarespace.com/&quot;&gt;Squarespace&lt;/a&gt; 🎉.&lt;/p&gt;

&lt;p&gt;Job hunting was far from the seamless process I imagined it would be. Here’s a review of my 2 months interviewing in tech.&lt;/p&gt;

&lt;h3 id=&quot;interview-prep&quot;&gt;Interview prep&lt;/h3&gt;

&lt;p&gt;The first step of my journey was interview prep.&lt;/p&gt;

&lt;p&gt;In December I was finishing a batch at the Recurse Center. During the final weeks I switched gears towards interview prep.&lt;/p&gt;

&lt;p&gt;I highly recommend taking a week or two to prep. Most of the time between mid-December to early-January was just switching my brain to interview mode.&lt;/p&gt;

&lt;p&gt;During this time, I made the mistake of scheduling a phone interview before I was fully ready. I failed pretty spectacularly and ruined a really great opportunity… not good 😢.&lt;/p&gt;

&lt;h3 id=&quot;resume-cleanup&quot;&gt;Resume cleanup&lt;/h3&gt;

&lt;p&gt;I updated &lt;a href=&quot;/resume&quot;&gt;my resume&lt;/a&gt; before starting applications and a few times throughout the process. Some things I tried to do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;One page&lt;/strong&gt;: Companies get tons of resumes and they have limited time to read each one.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Use bullets&lt;/strong&gt;: They are easier to skim and help separate discreet accomplishments.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Show, don’t tell&lt;/strong&gt;: Let experiences speak for themselves. Building something with a 10/10 rating is better than saying “my project was popular”.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Less is more&lt;/strong&gt;: At the start I thought more things meant more impressive. Later on I realized that each item has diminishing returns. Too much just creates clutter.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; I tried to be consistent with how I mention technologies and structure items.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With each update I shared my resume with a bunch of people for feedback. Here’s a .gif of all the iterations it went through.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/resumes-2017.gif&quot; alt=&quot;Resumes 2017&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;Resume evolution (6 versions)&lt;/p&gt;

&lt;p&gt;It changed quite a bit over the course of the 2 months. Looking back, I feel a tad gross having sent out the original version 😅.&lt;/p&gt;

&lt;h3 id=&quot;sending-applications&quot;&gt;Sending applications&lt;/h3&gt;

&lt;p&gt;Over the course of my 2 month search, I applied to 43 companies.&lt;/p&gt;

&lt;p&gt;Here are the stats&lt;sup&gt;*&lt;/sup&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Type of application&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;# Interested&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;% Interested&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Online&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4 / 22&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;18.2 %&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Referral&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;12 / 21&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;57.1 %&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;16 / 43&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;37.2 %&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;* &lt;em&gt;Interested means I was contacted for some type of interview.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Something to note: &lt;strong&gt;Referrals were 3x more likely to get a response.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I found referrals via:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Working with the jobs team at the &lt;a href=&quot;https://www.recurse.com/hire&quot;&gt;Recurse Center&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Contacting past coworkers.&lt;/li&gt;
  &lt;li&gt;Broadcasting my job hunt on Facebook.&lt;/li&gt;
  &lt;li&gt;Joining online tech communities (eg. a slack group for technologists in Toronto).&lt;/li&gt;
  &lt;li&gt;Talking to independent recruiters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would highly recommend reaching out to your networks. Referrals are so much more reliable.&lt;/p&gt;

&lt;p&gt;Of the places that weren’t interested, it generally fell into the category of &lt;em&gt;“looking for senior engineers”&lt;/em&gt; or &lt;em&gt;“looking for US based engineers”&lt;/em&gt; (I’m Canadian 🇨🇦).&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Side note:&lt;/em&gt;&lt;/strong&gt;&lt;br /&gt;
&lt;em&gt;Extra thanks to the Recurse Center. They were incredibly helpful during my job hunt.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Before working with them, I assumed recruiting was just a means to an end.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“We don’t run the Recurse Center so we can recruit, we recruit so we can run the Recurse Center.”&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.recurse.com/manual#sec-recruiting&quot;&gt;RC User Manual&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;After working with them, I’m super grateful they recruit. It was another amazing perk of attending.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;interviews&quot;&gt;Interviews&lt;/h3&gt;

&lt;p&gt;Of the 43 companies I applied to, 16 went forward with some type of interview.&lt;/p&gt;

&lt;p&gt;The process generally followed:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Coding test (sometimes)&lt;/li&gt;
  &lt;li&gt;Phone interview&lt;/li&gt;
  &lt;li&gt;Technical phone interview #1&lt;/li&gt;
  &lt;li&gt;Technical phone interview #2 (sometimes)&lt;/li&gt;
  &lt;li&gt;Onsite interviews&lt;/li&gt;
  &lt;li&gt;Hiring decision&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When I accepted my job offer, I was in the middle of a few other processes. I ended up having to withdraw my applications (not enough time to finish 😥). When I was applying, I tried to avoid this as much as possible by spacing out my interviews.&lt;/p&gt;

&lt;p&gt;Here’s how I progressed through my interviews:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/interview-pipeline.png&quot; alt=&quot;Progress through various interview processes&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;interview-challenges&quot;&gt;Interview challenges&lt;/h3&gt;

&lt;p&gt;Interviewing was a bunch of ups and downs.&lt;/p&gt;

&lt;p&gt;Some days I’d be applying all over and feeling super excited about my chances.&lt;br /&gt;
Other days I’d be freaking out because weeks had gone by without any responses.&lt;/p&gt;

&lt;p&gt;Some days I’d be scheduling interviews non-stop.&lt;br /&gt;
Other days I was looking back on rejections and feeling defeated by all the failures.&lt;/p&gt;

&lt;p&gt;Some days I felt bad about my interviews but then got forwarded along.&lt;br /&gt;
Other days I felt great about my interviews and then got rejected.&lt;/p&gt;

&lt;p&gt;It’s also a well known fact that interviewing is not an exact science.&lt;/p&gt;

&lt;p&gt;After my first couple of rejections, I started getting really frustrated with technical interviews.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;These coding problems are so arbitrary! If I ever needed to know this, I could easily Google it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I’m not allowed to run the code? How is this testing my actual abilities?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Yikes! I’ve been doing nothing but algorithm prep for a month and this is a CSS question…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wished people would just ask me about my past projects and how I work with other people.&lt;/p&gt;

&lt;p&gt;Then I had some really laid back interviews that did just that - those left me concerned.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;That was all conversational… what if they just hire random people who can talk but can’t code?!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;He didn’t write any notes. What’s he going off of other than just gut instinct?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is too easy…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By the end I had a new appreciation for how hard it is to interview.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You can keep things really conversational, but how does that show if someone can actually code?&lt;/li&gt;
  &lt;li&gt;You can assign a project, but how can you know if the person will have time to do a good job?&lt;/li&gt;
  &lt;li&gt;You can dive into quick algorithm problems, but how much does that actually tell you about the person?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the while you have a growing stack of applicants just waiting for an interview. 😩&lt;/p&gt;

&lt;p&gt;I wonder if any companies let candidates choose their interview style. Give a few different options and let the candidate pick the path that works best for them. I’d like to see how that type of system would work out.&lt;/p&gt;

&lt;h3 id=&quot;interview-highlights&quot;&gt;Interview highlights&lt;/h3&gt;

&lt;p&gt;Luckily, not all my interviews left me banging my head against a wall. Some were really fun!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Simple Website:&lt;/strong&gt; One company asked me to build a simple website in 4 hours. I enjoyed being able to focus on a project without having an interviewer breathing down my neck. The followup was working with some team members to add features to the site. Since it was my code, the choice of what to work on was completely open ended. The focus was on working as a team instead of finishing a list of tasks.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Life Story:&lt;/strong&gt; Two companies had me tell my life story. Where I grew up, how I got into programming and all the steps that led me to my job hunt. I love asking people to tell me their &lt;em&gt;Origin Story&lt;/em&gt;, and have spent a decent amount of time thinking about my own. It makes me happy when people have a self-awareness about their past and are willing to share. I liked that the company valued those things as well.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Independent Coding Problems:&lt;/strong&gt; At one onsite, I was given a sheet of questions and an hour to program solutions. Once again, I enjoyed being able to focus all my attention on the problems. It also gave a break from talking, talking, talking. That was nice.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Pass The Tests:&lt;/strong&gt; One interview asked me to implement a function to pass a suite of tests. I loved that! As someone who does a lot of TDD, I find it really helpful to have a set of test cases I can work through. It helps me concentrate when I can tackle the problem bit by bit.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Pairing:&lt;/strong&gt; I did a few interviews where I was allowed to use the internet and ask questions. They were described as pairing interviews, but didn’t feel like it. They usually involved an interviewer sitting across from me looking at their own laptop… not much different than sitting across from me as I write on a whiteboard. I had one really awesome pairing interview though. We both sat at the same workstation and faced the problem together. As a result, it was much easier to point at things and collaborate. That small change made a big difference.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Team Lunch:&lt;/strong&gt; Most companies with full-day onsites will schedule in some sort of lunch interview. It’s supposed to be a chance to relax and ask questions to an engineer. At one company, the lunch was with my entire prospective team. Having everyone meant I could just shut up and see how people interacted regularly. I also got to feel what it was like to spend time with my potential future colleagues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Besides the interviews themselves, I also had some really good recruiters. People who were super attentive and eager to move things along at whatever pace I felt comfortable.&lt;/p&gt;

&lt;p&gt;Interviewing was tedious, so every supportive recruiter and well thought out interview was much appreciated ❤️.&lt;/p&gt;

&lt;h3 id=&quot;offers&quot;&gt;Offers&lt;/h3&gt;

&lt;p&gt;Learning I had offers was really stressful.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Do I take it or finish interviewing with these other companies?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Is this my market value? Should I negotiate?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Company A is really cool, but I’ll have to move so far. Company B is smaller, but in a better city. How do I choose??&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I don’t plan on moving again for a while, so it was a big decision. The factors that led me to choose Squarespace:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Well established company with a good reputation.&lt;/li&gt;
  &lt;li&gt;Team with a bunch of friendly people and interesting projects.&lt;/li&gt;
  &lt;li&gt;Being close to the Recurse Center and the awesome communities in New York.&lt;/li&gt;
  &lt;li&gt;At the same time, being close enough to Toronto that I can visit easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Places in Vancouver were a close second. I met a bunch of wonderful people there during my time at Mobify. Still sad that I won’t be as close to them as I would like 😢.&lt;/p&gt;

&lt;h3 id=&quot;some-notes-for-past-me&quot;&gt;Some notes for past me&lt;/h3&gt;

&lt;p&gt;Now that it’s all over, what tips would I have for past me?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Prepare early:&lt;/strong&gt; Interviews are a whole other skill-set - you can’t just wing it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Clean up your resume:&lt;/strong&gt; Squishing a year’s worth of activities into one item is confusing. It’s better to break things up properly and skip some details.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Focus on referrals:&lt;/strong&gt; It might be easier to upload your resume everywhere, but your chances are way higher with referrals.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Research the companies:&lt;/strong&gt; Interviews are much more interesting if you can go in knowing what they’re working on and why you want to contribute.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Write more code by hand:&lt;/strong&gt; Interviewing involves a ton of communication. How you work through the problem is just as important as coding the final solution. Practice that thought process.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Focus on interviewing resources:&lt;/strong&gt; Things like HackerRank are fun because you get to write code and test it out. But working code isn’t everything. Resources like “Cracking The Coding Interview” give in depth explanations of all the other things interviewers are looking for. Did you realize there’s a faster solution that uses more memory? Or that assuming a sorted input lets you cut the runtime in half?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Accept the circumstances:&lt;/strong&gt; Some interviews are frustrating. Others are great. Analyzing the problems with one over the other never helps. The system isn’t perfect, but it’s what you have to work with. Do the best that you can with it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Calm. Down.:&lt;/strong&gt; Stop worrying about the pros and cons of job A vs. B. Chances are they’re both equally amazing for completely different reasons. Flip a coin. Make a choice. The second you do, you’ll move on and be excited for what lies ahead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;thanks&quot;&gt;Thanks&lt;/h3&gt;

&lt;p&gt;I couldn’t end without sending out some appreciation…&lt;/p&gt;

&lt;p&gt;To everyone who helped me prep.&lt;br /&gt;
To everyone who read over my resume.&lt;br /&gt;
To everyone who forwarded me along to their HR department.&lt;br /&gt;
To everyone who listened to me rejoice after a good interview.&lt;br /&gt;
To everyone who listened to me vent after a bad rejection.&lt;br /&gt;
To everyone who gave guidance and advice along the way.&lt;/p&gt;

&lt;p&gt;Thanks ❤️.&lt;/p&gt;

&lt;p&gt;It’s been a hectic 2 months, and I’m so excited that it’s over.&lt;/p&gt;

&lt;p&gt;Let the Squarespace adventure begin! 🙌&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to @kracekumar, @zormit and @Khaleed for providing feedback on this post! 🥇&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 16 Mar 2017 00:00:00 -0400</pubDate>
        <link>https://haroldtreen.com/tech/recurse/job/2017/03/16/two-months-of-tech-interviews/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/recurse/job/2017/03/16/two-months-of-tech-interviews/</guid>
        
        
        <category>tech</category>
        
        <category>recurse</category>
        
        <category>job</category>
        
      </item>
    
      <item>
        <title>Applying to the Recurse Center...twice 💌</title>
        <description>&lt;p&gt;The Recurse Center.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A free, self-directed, educational retreat for people who want to get better at programming, whether they’ve been coding for three decades or three months.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I heard about it through some well regarded friends back in 2014.&lt;br /&gt;
In 2015, I finally got up the courage to apply.&lt;/p&gt;

&lt;p&gt;I was promptly rejected (literally the same day 😅).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/rc-rejection-email.jpg&quot; alt=&quot;RC Rejection Email&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It was both disappointing and confusing. What had I done wrong? I thought I’d be a great candidate…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I had just finished my Computer Engineering degree.&lt;/li&gt;
  &lt;li&gt;I had worked at numerous tech companies.&lt;/li&gt;
  &lt;li&gt;I volunteered with diverse, tech focused organizations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I swallowed my pride and moved on.&lt;/p&gt;

&lt;p&gt;Fast-forward to June, 2016. ⏩&lt;/p&gt;

&lt;p&gt;I was travelling South America, working on &lt;a href=&quot;https://epub.press&quot;&gt;some side projects&lt;/a&gt; and starting to crave a better coding atmosphere. Willing to try anything, I decided to reapply to RC.&lt;/p&gt;

&lt;p&gt;A few days later I was invited to interview over Skype.&lt;br /&gt;
Then came an invitation to a pair programming interview.&lt;/p&gt;

&lt;p&gt;…then came an acceptance email! ❤️&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/rc-acceptance-email.jpg&quot; alt=&quot;RC Acceptance Email&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In Fall 2016, I had the joy of attending a 12-week batch at the Recurse Center.&lt;/p&gt;

&lt;h3 id=&quot;diffing-my-applications&quot;&gt;Diffing my applications&lt;/h3&gt;

&lt;p&gt;While at RC, I learned that you can actually look back at past applications. I pulled up my first and second to see what had changed between the two.&lt;/p&gt;

&lt;p&gt;Here’s my &lt;a href=&quot;/assets/posts/rc-application-1.jpg&quot;&gt;first application&lt;/a&gt;.&lt;br /&gt;
Here’s my &lt;a href=&quot;/assets/posts/rc-application-2.jpg&quot;&gt;second application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I definitely think my second attempt was an improvement.&lt;/p&gt;

&lt;p&gt;Here’s some quick thoughts on how my application changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Disclaimer:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;I don’t recruit for RC and have no insight on my applications performance. These are mere humble thoughts.&lt;/em&gt; 🤔&lt;/p&gt;

&lt;h4 id=&quot;code-cracklepop&quot;&gt;&lt;strong&gt;Code CracklePop&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;I think both answers are acceptable.&lt;/p&gt;

&lt;p&gt;The first decouples message generation from message printing, BUT prints the number on every iteration - which is &lt;strong&gt;WRONG&lt;/strong&gt;. (See &lt;a href=&quot;http://wiki.c2.com/?FizzBuzzTest&quot;&gt;problem description&lt;/a&gt;)&lt;br /&gt;
The second is a short function that does everything it needs to do.&lt;/p&gt;

&lt;p&gt;I think we all know why Harold got rejected now. Case closed!&lt;/p&gt;

&lt;h4 id=&quot;please-link-to-a-program-youve-written-from-scratch&quot;&gt;&lt;strong&gt;Please link to a program you’ve written from scratch.&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;I referenced the same project in both applications. In the first I tried talking it up whereas in the second I just left the link and a description.&lt;/p&gt;

&lt;p&gt;I worked on that project more after my first application, so it may have been more complete the second time it was reviewed…&lt;/p&gt;

&lt;h4 id=&quot;what-is-the-most-fascinating-thing-youve-learned-in-the-past-month&quot;&gt;&lt;strong&gt;What is the most fascinating thing you’ve learned in the past month?&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;First application I was obviously trying to appear as sentimental as possible 😅. References a bunch of vague stuff like “being vulnerable” and “connection”&lt;/p&gt;

&lt;p&gt;Second application felt a lot more real. It was a specific and unique thing I’d just learned about myself while travelling.&lt;/p&gt;

&lt;h4 id=&quot;what-do-you-want-to-be-doing-in-two-years&quot;&gt;&lt;strong&gt;What do you want to be doing in two years?&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Kinda funny how similar these two are in places! Both talk about building communities.&lt;/p&gt;

&lt;p&gt;I feel like the second was more specific and direct. It includes a reference to external viewing material and avoids vague phrases like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I want to be working for a company/organization with a strong culture…”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Powerful words… identity shaking, earth shattering words…&lt;/p&gt;

&lt;h4 id=&quot;why-do-you-want-to-attend-the-recurse-center&quot;&gt;&lt;strong&gt;Why do you want to attend the Recurse Center?&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;I think this is where I lost a lot of points.&lt;/p&gt;

&lt;p&gt;From my first application:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For the past 4 years I’ve been doing a lot of work with software, but 90% driven by the organizations and groups I was working with.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not. A. Good. Reason.&lt;/p&gt;

&lt;p&gt;The Recurse Center is 100% self-directed. This sentence basically says.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I’ve been coding for 4 years and never built anything in my spare time. I only code when I’m employed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Compare this to my second application:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Because for the last 5 months I’ve been working on projects in awful environments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So. Much. Better.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I’ve actually been working on things. By myself.&lt;/li&gt;
  &lt;li&gt;I’m working in really poor environments. Coming to RC isn’t just about “time to work on stuff”, it’s about needing a better physical space.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;what-would-you-like-to-work-on-at-the-recurse-center&quot;&gt;&lt;strong&gt;What would you like to work on at the Recurse Center?&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;I listed my ebook building tool in both applications!&lt;/p&gt;

&lt;p&gt;The first time I applied, it was just an idea. I also included a bunch of random explanation as to why I wanted to build it.&lt;/p&gt;

&lt;p&gt;The second time it was a fairly mature project. I also had specific improvements.&lt;br /&gt;
Talking about my desire to experiment with content extraction algorithms also demonstrated an interest in more theoretical concepts. Having a balance between practical and theoretical is important.&lt;/p&gt;

&lt;p&gt;I’m not sure if past applications are referred to, but if they are, demonstrating the progress made on my previous idea probably looked good.&lt;/p&gt;

&lt;h4 id=&quot;describe-your-programming-background-in-a-few-sentences&quot;&gt;&lt;strong&gt;Describe your programming background in a few sentences.&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;My first application contained more than “a few” sentences 😬. It was more like a origin story of entering programming and all the random organizations I’d been a part of.&lt;/p&gt;

&lt;p&gt;My second application was much cleaner. A list of specific technologies that showed a wide range of experience.&lt;/p&gt;

&lt;p&gt;A+ instruction following 👍.&lt;/p&gt;

&lt;h4 id=&quot;have-you-worked-professionally-as-a-programmer&quot;&gt;&lt;strong&gt;Have you worked professionally as a programmer?&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;It’s interesting to note that the first word is the same between both applications, but the punctuation is different.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Application #1:&lt;/strong&gt; “Yes!”&lt;br /&gt;
&lt;strong&gt;Translation:&lt;/strong&gt; “I’m not sure if I’m qualified for RC, so please accept this extra enthusiasm in lieu of reasons for admitting me!”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Application #2:&lt;/strong&gt; “Yes.”&lt;br /&gt;
&lt;strong&gt;Translation:&lt;/strong&gt; “You probably have a million of these to read, so I’ll keep it brief.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First application had more superfluous details. Second application listed past positions and focuses much more succintly.&lt;/p&gt;

&lt;h4 id=&quot;do-you-have-a-computer-science-degree-or-are-you-seeking-one&quot;&gt;&lt;strong&gt;Do you have a Computer Science degree or are you seeking one?&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;In both I just mention my degree, but I love how first Harold also included the exact geographic location of the University.&lt;/p&gt;

&lt;h3 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h3&gt;

&lt;p&gt;It’s easy to laugh about these things now, but being rejected from RC is hard.&lt;/p&gt;

&lt;p&gt;In a job application, you might get rejected because of a technical shortcoming.&lt;br /&gt;
In a RC application, it feels like a personal shortcoming.&lt;/p&gt;

&lt;p&gt;But if you have been rejected from RC, &lt;strong&gt;don’t give up&lt;/strong&gt;.&lt;br /&gt;
RC’s own website states that &lt;a href=&quot;https://www.recurse.com/faq#can-i-reapply-question&quot;&gt;6% of RCers apply at least twice&lt;/a&gt;. I met multiple such people during my batch - they were wonderful.&lt;/p&gt;

&lt;p&gt;Keep programming, keep working on side projects and keep striving to be a better programmer.&lt;/p&gt;

&lt;p&gt;Looking back, I’m actually glad I got rejected.&lt;/p&gt;

&lt;p&gt;Self-directed work is not easy. Learning that skill before going helped me get the most out of my experience. South America was also a much cheaper place to learn than New York.&lt;/p&gt;

&lt;p&gt;But I’m also glad I reapplied.&lt;/p&gt;

&lt;p&gt;It was an awesome 12-weeks of becoming a better programmer and a better person.&lt;br /&gt;
If you’re curious about what I got up to, I &lt;a href=&quot;/tech/recurse/2017/01/27/recurse-center-return-statement/&quot;&gt;wrote up a whole summary&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now that you understand there’s nothing to lose, maybe you should consider &lt;a href=&quot;https://www.recurse.com/apply&quot;&gt;applying&lt;/a&gt;!&lt;/em&gt; 😉&lt;/p&gt;
</description>
        <pubDate>Sun, 26 Feb 2017 00:00:00 -0500</pubDate>
        <link>https://haroldtreen.com/tech/recurse/2017/02/26/applying-twice-to-the-recurse-center/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/recurse/2017/02/26/applying-twice-to-the-recurse-center/</guid>
        
        
        <category>tech</category>
        
        <category>recurse</category>
        
      </item>
    
      <item>
        <title>12 Weeks @ The Recurse Center 🤔</title>
        <description>&lt;p&gt;On December 15th, 2016, my time at the Recurse Center came to an end 😔.&lt;/p&gt;

&lt;p&gt;Since then, I’ve been home with friends and family who have been asking to summarize the experience.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Did you like it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was it what you expected?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was it worth it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So to better collect my thoughts and summarize the experience - I’m going to write this post!&lt;/p&gt;

&lt;h2 id=&quot;applying-to-the-recurse-center&quot;&gt;Applying to the Recurse Center&lt;/h2&gt;

&lt;p&gt;When I applied to the Recurse Center I was in Lima, Peru.&lt;/p&gt;

&lt;p&gt;My plan for the year had been to travel the world and code (7 months in South America and 5 months in Europe). Live out of a backpack, meet locals, get off the beaten path… all that jazz.&lt;/p&gt;

&lt;p&gt;It was fun for a while, but I eventually started getting really burnt out.&lt;/p&gt;

&lt;p&gt;Reasons for that included:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Never-ending uncertainty about where I would sleep/eat.&lt;/li&gt;
  &lt;li&gt;Constant turnover of people.&lt;/li&gt;
  &lt;li&gt;Lack of people with similar goals/interests.&lt;/li&gt;
  &lt;li&gt;Lack of settings where I could explore my interests.&lt;/li&gt;
  &lt;li&gt;Pressure to be continually moving.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I decided I was tired of chasing cities and instead wanted to focus on meeting interesting people and becoming a better programmer. Some options I considered:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Flying somewhere with more nomadic programmers (eg. Southeast Asia)&lt;/li&gt;
  &lt;li&gt;Getting a full-time job&lt;/li&gt;
  &lt;li&gt;A conference for remote workers&lt;/li&gt;
  &lt;li&gt;The Recurse Center&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After exploring the options, I decided the Recurse Center seemed like the best fit.&lt;/p&gt;

&lt;h2 id=&quot;expectations-for-the-recurse-center&quot;&gt;Expectations for the Recurse Center&lt;/h2&gt;

&lt;p&gt;When I decided to go to the Recurse Center, this is what I was looking to get out of it.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Work environment&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Wifi wasn’t great on the road.&lt;/li&gt;
      &lt;li&gt;Hostels were hard to focus in.&lt;/li&gt;
      &lt;li&gt;People regularly warned against carrying a laptop in public, which discouraged me from going to coffee shops.&lt;/li&gt;
      &lt;li&gt;A city/space with more opportunities to pursue my interests.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;People&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Interactions that would last for more than a week.&lt;/li&gt;
      &lt;li&gt;Guidance on my projects from more experienced people.&lt;/li&gt;
      &lt;li&gt;Exposure to new ideas and encouragement towards personal growth.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things lacking from these lists:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Dedicated time to program&lt;/strong&gt;: I took a lot of time while travelling to focus on coding. Being at RC gave me a 3 month block of time to code, but I was already dedicating time to code.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Build/Learn X&lt;/strong&gt;: While I did come to RC to learn new things, I didn’t have some grand vision for what success would look like. I was mainly looking to collaborate with others and learn from those experiences.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-environment-at-the-recurse-center&quot;&gt;The environment at the Recurse Center&lt;/h2&gt;

&lt;p&gt;Coming in, I had a certain set of expectations for the environment at RC:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Room full of programmers.&lt;/li&gt;
  &lt;li&gt;Talk about technical stuff.&lt;/li&gt;
  &lt;li&gt;Work on technical stuff.&lt;/li&gt;
  &lt;li&gt;Programming nirvana, please discuss your non-technical interests elsewhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was reinforced by what I read in the &lt;strong&gt;&lt;a href=&quot;https://www.recurse.com/manual#sec-principles&quot;&gt;RC Manual&lt;/a&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You should be here primarily because you want to become a better programmer and spend the majority of your time here programming and doing things directly related to programming.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Well, we could ask you to be respectful of speakers and keep conversations on-topic in the Recurse Center space during the day (i.e. if you want to take a break and chat about your weekend, go grab a coffee).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That wasn’t my experience of the space.&lt;/p&gt;

&lt;p&gt;How I came to see it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Room full of curious, friendly, wonderful people from all all walks of life.&lt;/li&gt;
  &lt;li&gt;Talk about technical stuff. Talk about emotional stuff. Talk about what excites you.&lt;/li&gt;
  &lt;li&gt;Work on technical stuff during the day. Attend events and explore non-technical interests in the evenings.&lt;/li&gt;
  &lt;li&gt;Educational nirvana, with a primary focus on programming and a secondary focus on everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was the best learning environment I’ve ever been in ❤️.&lt;/p&gt;

&lt;p&gt;Best doesn’t mean perfect though. Working at RC was at times inspiring and exciting. At other times difficult and confusing.&lt;/p&gt;

&lt;p&gt;Here’s my breakdown of those two sides.&lt;/p&gt;

&lt;h2 id=&quot;the-hard-parts-&quot;&gt;The Hard Parts 😰&lt;/h2&gt;

&lt;h3 id=&quot;imposter-syndrome&quot;&gt;Imposter Syndrome&lt;/h3&gt;

&lt;p&gt;You could probably relate much of what felt “bad” back to imposter syndrome.&lt;/p&gt;

&lt;p&gt;Imposter syndrome is normally used to describe people who are doubtful of their programming abilities. My imposter syndrome was more doubting my value as an RCer.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Those people are reading academic papers and reimplementing Raft… but I just want to build silly web apps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Those people just finished their bittorent clients… but I spent my entire day writing a presentation on Non-Violent Communication.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;That person just shared a tech meetup and everyone seems excited… I just shared a concert and nobody wants to go.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The comparisons started making me wonder.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Am I working on what I’m supposed to?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Am I less technical than these people?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Is my presence distracting?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first time I applied to RC I was rejected. Thinking about that didn’t help calm the worries that maybe I wasn’t a good fit.&lt;/p&gt;

&lt;p&gt;Logically, I knew it was silly. RC has lots of other people interested in the same things that I am. I gained a ton from putting my ideas out there and finding others to collaborate with.&lt;/p&gt;

&lt;p&gt;But the imposter syndrome was always lurking in the back of my head - ready to flare up if things weren’t going the way I wanted.&lt;/p&gt;

&lt;h3 id=&quot;people-vs-projects&quot;&gt;People v.s. Projects&lt;/h3&gt;

&lt;p&gt;People and projects were two opposing forces that took a lot of energy to keep in balance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Projects:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I have 3 months to focus on whatever I want!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I’m surrounded by knowledgeable people who can give project advice and help me progress.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I need to code as much as possible because I’m here to be a better programmer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;People:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There’s so many interesting people! I just want to talk to them all day.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I can code anytime and anywhere. Being here is special because of all the people around me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;There’s so many things to do in New York and so many curious people willing to do them with me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I definitely leaned a lot more towards the &lt;strong&gt;people&lt;/strong&gt; end of the spectrum. At the end of my batch I felt so excited about all the interactions I had, but disappointed about the amount of programming I had done.&lt;/p&gt;

&lt;p&gt;Other people leaned a lot more towards &lt;strong&gt;projects&lt;/strong&gt;. I didn’t see them at many events, but by the end of their batch they’d built some really cool things.&lt;/p&gt;

&lt;p&gt;It was interesting talking to the project people.&lt;br /&gt;
I lamented not having accomplished as much as them. They lamented not getting to know more people.&lt;/p&gt;

&lt;p&gt;Grass is always greener 🐄.&lt;/p&gt;

&lt;p&gt;I don’t regret anything, but it’s definitely a balance I worried about during my batch.&lt;/p&gt;

&lt;h3 id=&quot;rc-bubble&quot;&gt;RC Bubble&lt;/h3&gt;

&lt;p&gt;It’s easy to get immersed in RC.&lt;/p&gt;

&lt;p&gt;Coming from Toronto, I didn’t really have any social group when I arrived in New York. If I wanted to be social I could:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Hang out at RC, where everyone is friendly and willing to chat.&lt;/li&gt;
  &lt;li&gt;Go out to things by myself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Option 1 was always the easiest/default. But always being in RC would tire me out. It meant constantly talking about projects and programming.&lt;/p&gt;

&lt;p&gt;Interacting exclusively within RC also made the relationships feel RC dependent… context dependent.&lt;/p&gt;

&lt;p&gt;Sure, we could talk and hang out… but I felt like we were hanging out as RCers, not friends.&lt;/p&gt;

&lt;p&gt;People would always be keen on hanging out at RC, or going as a group to do things. It was a lot more rare to hear:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Hey Harold, I’m hosting a thing and wanted to invite you!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I fell victim to this too. It just felt easier to put general invitations out rather than try and make time with individuals. It’s also something that takes a while to happen… 12 weeks isn’t a lot of time to navigate all the people and opportunities within RC.&lt;/p&gt;

&lt;p&gt;Nevertheless, getting to know people as friends as opposed to batch mates was something I frequently craved.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Thanks to all the people who did put themselves out there and made stuff happen outside of RC. It was very much appreciated ❤️.)&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-awesome-parts-&quot;&gt;The Awesome Parts 😃&lt;/h2&gt;

&lt;h3 id=&quot;learning-from-others&quot;&gt;Learning from others&lt;/h3&gt;

&lt;p&gt;RC provided so many opportunities to learn from others.&lt;/p&gt;

&lt;p&gt;The diversity of experiences meant that whatever you were learning, there was someone who knew it.&lt;/p&gt;

&lt;p&gt;People would pair together, answer questions on Zulip and share their favorite resources.&lt;br /&gt;
People would organize reading groups, presentations and viewings of screencasts.&lt;br /&gt;
People openly talked about their failures, their struggles and their 4 hour debugging sessions.&lt;/p&gt;

&lt;p&gt;The whole environment at RC made learning collaborative and fun.&lt;/p&gt;

&lt;p&gt;RC also hosted a variety of residents - experienced programmers who were willing to sit down and provide insight on a wide range of topics.&lt;/p&gt;

&lt;p&gt;Outside of RC there was all of New York. A bustling city full of interesting events and meetups.&lt;/p&gt;

&lt;p&gt;So grateful for all the learning that was shared!&lt;/p&gt;

&lt;h3 id=&quot;redefining-programmer&quot;&gt;Redefining “Programmer”&lt;/h3&gt;

&lt;p&gt;Before RC, I had this idea of “tech culture” that I didn’t feel comfortable identifying with.&lt;/p&gt;

&lt;p&gt;In tech, I’ve felt like my interactions with others had to be technical or not happen. Asking questions about interests and hobbies drew blank stares. Not knowing about the latest framework or tool meant you were a bad programmer.&lt;/p&gt;

&lt;p&gt;Other friends had felt it too. We’d even talk about tech as some other entity we just had to deal with.&lt;/p&gt;

&lt;p&gt;The people at RC wiped all those assumptions away.&lt;/p&gt;

&lt;p&gt;“Nerdy sweethearts” is how one RCer described the group. Thoughtful, passionate, empathetic and friendly are other adjectives that come to mind… but that’s all pretty vague.&lt;/p&gt;

&lt;p&gt;To put it in more concrete terms - “programmer” was redefined for me:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;At non-technical talks, when people talked about Brexit or &lt;em&gt;“How did blue/black become the most used inks?”&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;During feelings checkins, where everyone would sit and share their emotional state from that week.&lt;/li&gt;
  &lt;li&gt;At after hour events, which ranged from RCers doing improv together to learning hip hop dance.&lt;/li&gt;
  &lt;li&gt;On &lt;a href=&quot;https://www.recurse.com/blog/112-how-rc-uses-zulip&quot;&gt;Zulip&lt;/a&gt;, where alumni from 2012 still hang around to share and ask advice.&lt;/li&gt;
  &lt;li&gt;In the homes of RCers who organized potlucks to bring everyone together (and seeing the culinary talents of coding accomplices 😋).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and so many other wonderful moments.&lt;/p&gt;

&lt;p&gt;All moments which were created/proposed/executed by RCers. People willing to put out there ideas, and people excited to support those ideas and run with them.&lt;/p&gt;

&lt;p&gt;I once again feel excited to call myself a programmer.&lt;/p&gt;

&lt;h3 id=&quot;spirit-of-experimentation&quot;&gt;Spirit of experimentation&lt;/h3&gt;

&lt;p&gt;The curiosity at RC makes it such a great place for experimentation.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Should we do in person checkins? Zulip checkins? End of day checkouts? Try them all and choose for yourself!&lt;/li&gt;
  &lt;li&gt;Want to try being nocturnal? The space is accessible 24/7!&lt;/li&gt;
  &lt;li&gt;Interested in academic papers? Start a reading group!&lt;/li&gt;
  &lt;li&gt;Want to get into meditation? Join the meditation sessions!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anything you could want to experiment with, there’s a way to do it at RC. There’s also probably a handful of curious individuals willing to try it out with you.&lt;/p&gt;

&lt;p&gt;It’s so much fun getting to try all the things!&lt;/p&gt;

&lt;h3 id=&quot;being-myself&quot;&gt;Being myself&lt;/h3&gt;

&lt;p&gt;At RC, I felt like I was working on more parts of myself than in any other community.&lt;/p&gt;

&lt;p&gt;Any interest I had, there was someone equally curious about it and willing to chat.&lt;br /&gt;
Any feeling I was experiencing, I could share without fear of judgement or shame.&lt;/p&gt;

&lt;p&gt;It was a pretty awesome feeling.&lt;/p&gt;

&lt;p&gt;I should note that it’s something that took time to feel. At first I definitely came in with worry and imposter syndrome:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Omg, these people are so much more socially aware than I am… I’m going to screw this up… I’m going to break a social rule.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Is this thing I’m writing going to offend someone? Did I just say something -ismy? Oh god oh god 😬.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Oh god, I just wrote a blog post that was 90% feels… I’m not programmer enough to be here 😨.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But with each interaction and conversation, I felt more and more at home.&lt;/p&gt;

&lt;h3 id=&quot;overall&quot;&gt;Overall&lt;/h3&gt;

&lt;p&gt;So…&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Did you like it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;YES ❤️&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was it what you expected?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;NO ❤️&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was it worth it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ABSOLUTELY ❤️&lt;/p&gt;

&lt;p&gt;The Recurse Center provided total freedom to work on what I wanted. It surrounded me with a wonderful group of people to work on those things with.&lt;/p&gt;

&lt;p&gt;Did I become a &lt;strong&gt;significantly&lt;/strong&gt; better programmer?&lt;/p&gt;

&lt;p&gt;Not through lines of code, or deep dives into new languages.&lt;br /&gt;
But I got to work on all kinds of things that left me feeling like a better person.&lt;/p&gt;

&lt;p&gt;And becoming a better person makes you a better programmer. 😊&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Thanks to all the staff for all the work you do to keep RC running. &lt;br /&gt;
Thanks to all the RCers who invested their energy into making RC such a great place to be. ❤️&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you’re looking to become a better programmer, you should &lt;a href=&quot;https://www.recurse.com/apply&quot;&gt;apply&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 27 Jan 2017 00:00:00 -0500</pubDate>
        <link>https://haroldtreen.com/tech/recurse/2017/01/27/recurse-center-return-statement/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/recurse/2017/01/27/recurse-center-return-statement/</guid>
        
        
        <category>tech</category>
        
        <category>recurse</category>
        
      </item>
    
      <item>
        <title>Week[11] @ The Recurse Center 🏆</title>
        <description>&lt;p&gt;Published before the end of the year! What an achievement!&lt;/p&gt;

&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;

&lt;p&gt;My time at the Recurse Center is complete. I am both incredibly grateful for my time there and excited to be moving on.&lt;/p&gt;

&lt;h3 id=&quot;emotional-&quot;&gt;Emotional 😱&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Moving Stress&lt;/strong&gt;&lt;br /&gt;
No matter where I go or what I do, transitions are stressful. A sort of impending doom that can’t wait to get over with.&lt;/p&gt;

&lt;p&gt;The last week also started loading on the thoughts of&lt;br /&gt;
“Have I done enough?”,&lt;br /&gt;
“Have I seen enough in New York?”,&lt;br /&gt;
“Will I have a chance to say bye to everyone?”.&lt;/p&gt;

&lt;p&gt;Gah! Get me to Toronto already!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Defeat&lt;/strong&gt;&lt;br /&gt;
Perhaps as a result of the stress, I allowed myself to feel defeated.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Game over. No coding is getting done this week. Focus on moving, exploring and socializing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Coding needs a certain amount of mental focus that I just didn’t have. Others seemed to feel similar.&lt;/p&gt;

&lt;h3 id=&quot;social-&quot;&gt;Social 🎉&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Trip to New Jersey&lt;/strong&gt;&lt;br /&gt;
In 2013, I did a trip to Asia and met a bunch of cool people.&lt;/p&gt;

&lt;p&gt;In 2014, one of those cool people (who I met in Japan 🇯🇵 !) was going to be in Niagara Falls. Naturally I bussed down from Toronto to meet up with her.&lt;/p&gt;

&lt;p&gt;It’s 2016 and that cool person now lives in New Jersey. I had meant to make a visit, and the last week motivation finally made it happen.&lt;/p&gt;

&lt;p&gt;Got to take a little walk around the other side of the water and catch up with my friend.&lt;/p&gt;

&lt;p&gt;With all the moving around, I run into a bunch of people and always leave wondering when/if I’ll ever see them again. Encounters like this one (still being in touch with someone I met in Japan 3 years ago) give me hope.&lt;/p&gt;

&lt;p&gt;(If you’re reading this and want to meet up, &lt;a href=&quot;/contact&quot;&gt;let’s make it happen&lt;/a&gt;!)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Circling&lt;/strong&gt;&lt;br /&gt;
@sofiajeanne ran another round of Circling sessions this week. So many people were interested that the groups needed to be split into 2.&lt;/p&gt;

&lt;p&gt;I showed up in the morning to find only 3 other people had arrived on-time. We got to have a really nice session with just the 4 of us.&lt;/p&gt;

&lt;p&gt;This week I worked on being less protective of others. Being able to speak to my experience and not worry about how it affects others. Letting others have their feelings without the need to comfort them or push them towards other feelings.&lt;/p&gt;

&lt;p&gt;Really loved it - so thanks for sharing it with us Sofia-Jeanne!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RC Goodbye/Christmas Party&lt;/strong&gt;&lt;br /&gt;
As with every goodbye, RC threw a party!&lt;/p&gt;

&lt;p&gt;One of the things mentioned in the party description was that it would have no dress-code. The example of &lt;strong&gt;pajamas&lt;/strong&gt; was given as an acceptable outfit.&lt;/p&gt;

&lt;p&gt;So naturally…&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/pajama-party.jpg&quot; alt=&quot;Harold in Pajamas&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It was nice to have one last night of silliness with all the pals. 😊&lt;/p&gt;

&lt;p&gt;A bunch of alumnus were also in attendance, which was super lovely! Was a good chance to say all the goodbyes.&lt;/p&gt;

&lt;p&gt;Ended the night at 3am, sitting in a circle, being nostalgic.&lt;/p&gt;

&lt;h3 id=&quot;intellectual-&quot;&gt;Intellectual 📡&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Make RC Better Meeting&lt;/strong&gt;&lt;br /&gt;
One of my favorite things at my last company were the weekly “Retrospectives”. They were a time for the team to discuss the past week and how things went.&lt;/p&gt;

&lt;p&gt;At the end of the last half, I asked a few people if they thought a reflection meeting at the end of the batch would be useful. Most said no ☹️.&lt;/p&gt;

&lt;p&gt;BUT RC ORGANIZED ONE THIS TIME AND I REALLY ENJOYED IT.&lt;/p&gt;

&lt;p&gt;The focus was mainly on the first day. I found that a bit strange… RC is so much more than the first day.&lt;/p&gt;

&lt;p&gt;One of my realizations from the meeting was that many people wanted there to be more group projects. When I came to RC, I felt very primed for taking ownership of my own learning and doing my own projects. The application process even asks what you will work on. In a way, knowing what you want to work on is a criteria for getting in.&lt;/p&gt;

&lt;p&gt;So with that, I had not been thinking about group work.&lt;/p&gt;

&lt;p&gt;Some interesting ideas passed around about how to get more long-term collaborations. Hopefully that gets integrated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-technical Talks&lt;/strong&gt;&lt;br /&gt;
On Monday, there was another round of non-technical talks.&lt;/p&gt;

&lt;p&gt;I had been really interested in presenting, but when Monday rolled around I felt totally unprepared. I took my name off the list, felt bad for not giving presenting one more go, put it back on, took it off. Bleh.&lt;/p&gt;

&lt;p&gt;Shouldn’t have spent so much time hanging out with people!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job Interviews&lt;/strong&gt;&lt;br /&gt;
This week I had some job calls. In retrospect, I really wish I hadn’t started getting in touch with places. Having to take calls and practice for interviews during the last week was very stressful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Niceties&lt;/strong&gt;&lt;br /&gt;
As with the past outgoing batch, everyone took some time this week to write nice thoughts for each other. This was WAY more time consuming than before. Mainly because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;There was now 2 batches worth of people to write messages for.&lt;/li&gt;
  &lt;li&gt;Having spent more time with people, there was much more to write.&lt;/li&gt;
  &lt;li&gt;After spending 12 weeks with people, I had nice things to say about almost anyone. I needed to actively stop myself from getting it all out (so if you didn’t get one from me, it’s not because of 💔 - just had to stop after 4 hours of writing. Hearts for you! ❤️).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Logging “Experiments”, “Activities” and “Events”&lt;/strong&gt;&lt;br /&gt;
When I first got to RC I did not expect how welcoming, open and supportive RC is. The breadth of events/activities/traditions/experiments/whatever you what to call them - it’s ridiculous.&lt;/p&gt;

&lt;p&gt;Unfortunately, I couldn’t find a comprehensive log of all the things that had been done at RC.&lt;/p&gt;

&lt;p&gt;So now that my last week of RC is complete, I’ve been trying to create that log. Within the RC wiki, I’ve been creating new sections for highlighting all the things that happen at RC.&lt;/p&gt;

&lt;p&gt;Really happy with how things have turned out, and hope others get inspiration from seeing the history of events.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No Coding&lt;/strong&gt;&lt;br /&gt;
As hinted to above, got NO coding done this week. That was a bit sad 🙁.&lt;/p&gt;

&lt;h2 id=&quot;physical-️&quot;&gt;Physical ⛳️&lt;/h2&gt;

&lt;p&gt;This has been the most useless section. I neglect my health so bad!&lt;/p&gt;

&lt;p&gt;…I guess I danced a bunch at the social&lt;br /&gt;
…and finished most of my groceries&lt;br /&gt;
…so those are things.&lt;/p&gt;

&lt;p&gt;¯\_(ツ)_/¯&lt;/p&gt;

&lt;h2 id=&quot;end&quot;&gt;&amp;lt;/End&amp;gt;&lt;/h2&gt;

&lt;p&gt;So there you have it! A rough, incomplete and angsty summary of my time at RC.&lt;/p&gt;

&lt;p&gt;It’s been a time writing this log.&lt;/p&gt;

&lt;p&gt;Much love to all the RCers who helped me review it at some point or another. Definitely gone mad overthinking what I should write some weeks.&lt;/p&gt;

&lt;p&gt;I’ll go through all the posts and create some sort of &lt;strong&gt;Return Statement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;RC has definitely been one of the coolest things I’ve ever been a part of. The people, the projects, the space.&lt;/p&gt;

&lt;p&gt;So with that, I’ll sign off one last time! 👋&lt;/p&gt;

&lt;p&gt;Much love everyone, it’s been a blast 🚀❤️!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to @vaibhavsagar for providing updates via PRs 😊.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 26 Dec 2016 00:00:00 -0500</pubDate>
        <link>https://haroldtreen.com/tech/recurse/2016/12/26/recurse-center-week-12/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/recurse/2016/12/26/recurse-center-week-12/</guid>
        
        
        <category>tech</category>
        
        <category>recurse</category>
        
      </item>
    
      <item>
        <title>Week[10] @ The Recurse Center 🌈</title>
        <description>&lt;p&gt;(It’s currently December 21st! I’ll be trying to backfill using my daily log. Where has the time gone?!)&lt;/p&gt;

&lt;h3 id=&quot;overall&quot;&gt;Overall&lt;/h3&gt;

&lt;p&gt;The end of the batch is nearing. I feel both pressure to do all the things and apathy for doing all the things. What a combo!&lt;/p&gt;

&lt;h3 id=&quot;emotional-&quot;&gt;Emotional 🥕&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Batch Gift Angst&lt;/strong&gt;&lt;br /&gt;
There were a few things this week that stressed me out. The first was the batch gift.&lt;/p&gt;

&lt;p&gt;It’s a tradition that every batch gets a gift for RC. I was aware of this, but didn’t feel like gift planning was something I wanted to get super involved in.&lt;/p&gt;

&lt;p&gt;Luckily, a fellow batch-mate picked up the job of rallying people to brainstorm gifts.&lt;/p&gt;

&lt;p&gt;A bunch of ideas were thrown around (I suggested Emoji pillows 😂), but there was nothing that everyone agreed on.&lt;/p&gt;

&lt;p&gt;Attempts were made at arranging a meeting, but they were too last minute and people weren’t RSVPing. Gah!&lt;/p&gt;

&lt;p&gt;I figured that it was hard to vote in a chat thread. I decided to gather all the ideas and take a poll. I started reading the ideas to do so, but it quickly became too stressful. All the serious ideas were mixed in with ridiculous (or so I assumed…) ideas.&lt;/p&gt;

&lt;p&gt;I pictured trying to sort through and having to decide what was “serious” vs. “joke”. I got frustrated by the extra work that would be involved because people weren’t taking it seriously. So I just gave up. That was bleh 🙁.&lt;/p&gt;

&lt;p&gt;Eventually people gathered and we figured it out.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: I proposed some jokes too… oops!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dinner Party Angst&lt;/strong&gt;&lt;br /&gt;
The second thing was a dinner party.&lt;/p&gt;

&lt;p&gt;It had been planned a week back and a few people had RSVPed. The day of, I was doubtful that anyone was going to show up. Nobody had really said what they were bringing and only a few people still seemed engaged.&lt;/p&gt;

&lt;p&gt;I kinda wanted to flake. Say screw it. I didn’t want to do all the prep work if it was potentially just going to be me and a couple others.&lt;/p&gt;

&lt;p&gt;Luckily @hsubox joined forces with me and we decided to commit. Jennifer went and grabbed a bunch of supplies so we could cook/bake (thank you!). We ended up having a good time baking up a storm. I posted baking pictures on Zulip to reassure any other potential doubters that things were on.&lt;/p&gt;

&lt;p&gt;We ended up going and being greeted by a swarm of people. The dinner party was awesome. Worries were unfounded. Yay! 🎉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passiveness&lt;/strong&gt;&lt;br /&gt;
With only 2 weeks left, I was feeling very passive towards work. I felt drawn towards socializing and checking off some end of batch plans… so I did that.&lt;/p&gt;

&lt;h3 id=&quot;social-&quot;&gt;Social 🍕&lt;/h3&gt;

&lt;p&gt;Did a bunch of social stuff this week. Time with RC people is running out - so why nawt!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Firepit&lt;/li&gt;
  &lt;li&gt;Dinner Party @ RC&lt;/li&gt;
  &lt;li&gt;Glassroom&lt;/li&gt;
  &lt;li&gt;Circling&lt;/li&gt;
  &lt;li&gt;Board games&lt;/li&gt;
  &lt;li&gt;Cleaning party&lt;/li&gt;
  &lt;li&gt;Visit w/ @spiside&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The RC dinner party was a lot of fun… I’m a sucker for dinner parties (something about a group made meal shared amongst friends makes me 😍).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/rc-dinner-party.jpg&quot; alt=&quot;rc-dinner-party&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;Dinner partying it up @ The Recurse Center 🍽&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Circling&lt;/strong&gt;&lt;br /&gt;
Circling was another really unique experience. You can think of it like group meditation.&lt;/p&gt;

&lt;p&gt;Everyone sits in a circle and shares their experience of the moment. As people share, thoughts and feelings start to bubble up which then feed into the discussion.&lt;/p&gt;

&lt;p&gt;The experience didn’t strike me as particularly enlightening at the time. It wasn’t until the following days I noticed how much it affected me. Suddenly I felt much more aware in my interactions. I also became likelier to vocalize my feelings while interacting with others.&lt;/p&gt;

&lt;p&gt;Sooo now I’m hooked and will be seeking more when I return home 😊.&lt;/p&gt;

&lt;h3 id=&quot;intellectual-&quot;&gt;Intellectual 🌶&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;R0ml&lt;/strong&gt;&lt;br /&gt;
This week was the last week of R0ml’s residences. His speeches are very much geared towards stirring the pot and getting people to question their assumptions.&lt;/p&gt;

&lt;p&gt;During Monday’s talk he discussed anti-patterns. In particular, the following were some of the things described as anti-patterns:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Having code in separate files.&lt;/li&gt;
  &lt;li&gt;Build pipelines.&lt;/li&gt;
  &lt;li&gt;Interpreted languages.&lt;/li&gt;
  &lt;li&gt;3rd party libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was interesting watching everyones reactions to the talk. Some people were really frazzled. R0ml has a conviction while speaking which is hard to argue…regardless of whether you agree.&lt;/p&gt;

&lt;p&gt;Also had a good chat with R0ml about the future of programming education.&lt;/p&gt;

&lt;p&gt;His main idea was that we are wasting our time teaching people to code. There’s already tons of code in the world and there’s people always writing more.&lt;/p&gt;

&lt;p&gt;What the world does need is people to combine existing software in new and interesting ways. People who can submit bug reports and small code fixes.&lt;/p&gt;

&lt;p&gt;Sure, some coding is necessary for that - but in general its a different skill set then teaching programming from the bottom up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing time&lt;/strong&gt;&lt;br /&gt;
I love testing.&lt;/p&gt;

&lt;p&gt;Over the course of my batch, my testing pride brought people to me asking testing related questions. Many people were very confused about how to test, what to test, when to test, etc..&lt;/p&gt;

&lt;p&gt;I don’t blame them.&lt;/p&gt;

&lt;p&gt;Writing a test suite can feel like a completely separate project. Technically it’s not even necessary. Sure a good test suite can make your life 100x easier, but it requires an upfront investment of time.&lt;/p&gt;

&lt;p&gt;I don’t think this is a problem with the materials. There’s lots of GREAT content for learning about testing and TDD. If anyone wanted they could do a google search and find relevant tutorials.&lt;/p&gt;

&lt;p&gt;What there isn’t a lot of is people who are excited about testing and willing to push others to start. I only got into TDD because I pair programmed with some awesome people who showed me the way. Before then, I was happily writing out code without a worry for whether it was tested.&lt;/p&gt;

&lt;p&gt;With time at RC running out, I decided to run a collaborative work session called “Testing Time 🕑”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The plan:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;People would bring existing projects they wanted to test.&lt;/li&gt;
  &lt;li&gt;I’d provide a bunch of testing related “challenges” that could be applied to a variety of projects.&lt;/li&gt;
  &lt;li&gt;As a group we’d work through the challenges and learn by doing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There was a reasonable amount of interest. Some people came and only stayed for the talk. Others stuck around and did the collaborative portion. I had a lot of fun helping people setup linters and get their test suites up and running.&lt;/p&gt;

&lt;p&gt;I like to think it helped people chip away at their testing fears.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Haskelling&lt;/strong&gt;&lt;br /&gt;
I worked through more of the &lt;code class=&quot;highlighter-rouge&quot;&gt;NICTA&lt;/code&gt; course. I managed to finished &lt;code class=&quot;highlighter-rouge&quot;&gt;Functors&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Applicatives&lt;/code&gt;… less than I would have liked…&lt;/p&gt;

&lt;p&gt;But socializing!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resume review &amp;amp; job applications&lt;/strong&gt;&lt;br /&gt;
One of the under appreciated aspects of RC is the career guidance.&lt;/p&gt;

&lt;p&gt;This week I had Nancy review my resume. It was encouraging to get feedback from someone who has seen a lot of tech resumes.&lt;/p&gt;

&lt;p&gt;She gave some good feedback and I spent part of the week trying to clean it up. Felt very torn between:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;RC is for becoming a better programmer. I can do this when I get home.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I should really get on this so I’m not running around last minute looking for jobs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Who knows  ¯\_(ツ)_/¯.&lt;/p&gt;

&lt;h3 id=&quot;physical-&quot;&gt;Physical 🍿&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Sick&lt;/strong&gt;&lt;br /&gt;
Been noticing that even small amounts of alcohol at RC social events have left me feeling sick.&lt;/p&gt;

&lt;p&gt;It’s extra crappy when it happens on days where I slept in…&lt;br /&gt;
and an RC social event is in the afternoon…&lt;br /&gt;
and I get no work in before having a beer and getting a horrible migraine 🤒.&lt;/p&gt;

&lt;p&gt;No more drinking!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Living off limited groceries&lt;/strong&gt;&lt;br /&gt;
With the batch coming to an end, I’m trying to be aware of all the food I need to finish.&lt;/p&gt;

&lt;p&gt;I always find myself hesitant to grocery shop when I’m staying somewhere short term. It surfaces worries that I won’t be able to finish whatever I buy.&lt;/p&gt;

&lt;p&gt;In practice groceries are WAY cheaper and not that hard to finish. But even leaving a few $2 bags of pasta unfinished gives me angst!&lt;/p&gt;

&lt;p&gt;So gotta chow down before leaving.&lt;/p&gt;

&lt;h3 id=&quot;end&quot;&gt;&amp;lt;/End&amp;gt;&lt;/h3&gt;

&lt;p&gt;Did it! Another week done.&lt;/p&gt;

&lt;p&gt;These have been exceedingly harder to write as time has moved on.&lt;/p&gt;

&lt;p&gt;Maybe it’s the thought that I’m being boring…&lt;br /&gt;
Or the worry that I’m holding back in person and then revealing way more in this blog…&lt;br /&gt;
Or embarrassment for not having more done…&lt;/p&gt;

&lt;p&gt;In any case, I think it’s been a good experience. One of my more uncomfortable pursuits.&lt;/p&gt;

&lt;p&gt;One more to go! ❤️&lt;/p&gt;
</description>
        <pubDate>Wed, 21 Dec 2016 00:00:00 -0500</pubDate>
        <link>https://haroldtreen.com/tech/recurse/2016/12/21/recurse-center-week-11/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/recurse/2016/12/21/recurse-center-week-11/</guid>
        
        
        <category>tech</category>
        
        <category>recurse</category>
        
      </item>
    
      <item>
        <title>Week[9] @ The Recurse Center 🔎</title>
        <description>&lt;h3 id=&quot;overall&quot;&gt;Overall&lt;/h3&gt;

&lt;p&gt;I’m currently trying to distill through what is essential, and focusing on that. Stripping away the excess has left more energy for the important pursuits.&lt;/p&gt;

&lt;h3 id=&quot;emotional-&quot;&gt;Emotional 😰&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Frantic&lt;/strong&gt;&lt;br /&gt;
Feels have been evolving recently, but at the moment I feel frantic. There’s now only &lt;strong&gt;2&lt;/strong&gt; weeks left.&lt;/p&gt;

&lt;p&gt;Looking back, it seems like I got more done in the first half…&lt;br /&gt;
So far I’ve done a bunch into Haskell but haven’t made progress on any &lt;strong&gt;projects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’m disappointed that I haven’t built some “Pièce De Résistance”. I’ll have completed all the Haskell resources, but typing out function definitions isn’t that gratifying.&lt;/p&gt;

&lt;p&gt;I feel frantic to build something in the next two weeks that will prove &lt;strong&gt;I’m a better programmer&lt;/strong&gt;. A &lt;strong&gt;DRASTICALLY&lt;/strong&gt; better programmer.&lt;/p&gt;

&lt;p&gt;This desire has kept me constantly working.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It’s 9pm… but I don’t feel accomplished. Gah! Stay later, work longer, we’ll be drastically better soon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maybe if I went back 3 months, the improvement would be more obvious. I feel drastically better than a year ago, but it’s hard to know how much of that has come from RC.&lt;/p&gt;

&lt;p&gt;Anyway… I’m frantic to feel accomplished, and it hasn’t hit me yet. 😓&lt;/p&gt;

&lt;h3 id=&quot;social-&quot;&gt;Social 🍪&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cookies and Blanket Forts&lt;/strong&gt;&lt;br /&gt;
On Saturday, some housemates and I baked cookies! Turns out the house had all the extra ingredients I bought… oops!&lt;/p&gt;

&lt;p&gt;In addition to cookies, we also constructed a blanket fort. The cookies were then consumed in the blanket fort while watching a movie. It was glorious:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/blanket-fort.jpg&quot; alt=&quot;blanket-fort&quot; class=&quot;center-image&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;@hsubox &amp;amp; @NEIA20 critiquing the cinematic qualities of “Finding Dory” in “Chateau Del Sheets”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weapons of Math Destruction&lt;/strong&gt;&lt;br /&gt;
On Thursday I went to a meetup hosted at &lt;a href=&quot;https://postlight.com/&quot;&gt;Postlight&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was partly motivated to go by the talk, and partly motivated to learn more about Postlight. I got a chance to talk to some employees about their projects, a few of which had overlaps with what I’m working on. The rumors of it being an interesting company were true.&lt;/p&gt;

&lt;p&gt;The main event was a talk by &lt;a href=&quot;https://en.wikipedia.org/wiki/Cathy_O'Neil&quot;&gt;Cathy O’Neil&lt;/a&gt; on problems arising from the use of Big Data. It was really scary to hear how algorithms can obfuscate problematic systems. Looking forward to reading her book - “Weapons of Math Destruction”.&lt;/p&gt;

&lt;h3 id=&quot;intellectual-ƛ&quot;&gt;Intellectual ƛ&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Changing Project Plans&lt;/strong&gt;&lt;br /&gt;
When I first started reading up on Haskell, I was really interested in using it to build a javascript code generator. Pattern matching and types made it seem like a good fit for the task.&lt;/p&gt;

&lt;p&gt;After finishing my Haskell course, I felt differently. I was still interested in that project, but my understanding of Haskell still felt too fresh to be really productive on a project. I also was worried the project would involve more Javascript grammar definitions than actual coding.&lt;/p&gt;

&lt;p&gt;Instead, I want to continue improving my Haskell knowledge. So rather than start a project, I’ve begun working on a second Haskell course. (For those interested, it’s the &lt;a href=&quot;https://github.com/NICTA/course&quot;&gt;NICTA course&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;One of the main features of the course is a test suite, which I LOVE. Why can’t every course just be a bunch of unit tests to fix 😍.&lt;/p&gt;

&lt;p&gt;Doing another course doesn’t feed my need to accomplish a big project while I’m here - but I can build a project in Haskell after RC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interview Preps&lt;/strong&gt;&lt;br /&gt;
This past week I did 2 interview prep sessions. These have been super helpful.&lt;/p&gt;

&lt;p&gt;I’ve done interview prep with friends in the past, but nothing to the level of detail done at RC. Since first starting interview prep at RC, I’ve become much more systematic in my whiteboard interviews.&lt;/p&gt;

&lt;p&gt;Some things I’m trying to do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Restate the problem&lt;/li&gt;
  &lt;li&gt;Write down assumptions&lt;/li&gt;
  &lt;li&gt;Write out an example input and output&lt;/li&gt;
  &lt;li&gt;Brainstorm out loud possible solutions and write them down (noting the tradeoffs)&lt;/li&gt;
  &lt;li&gt;Write out the API for my code (eg. “I’m going to write a function &lt;code class=&quot;highlighter-rouge&quot;&gt;X&lt;/code&gt; that will accept an object with properties &lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;b&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;c&lt;/code&gt;”).&lt;/li&gt;
  &lt;li&gt;Be as verbose as possible with any doubts getting me stuck. Ask questions.&lt;/li&gt;
  &lt;li&gt;Create test cases and walk through the final implementation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is way better than my previous strategy:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Code a solution while being as verbose as possible.&lt;/li&gt;
  &lt;li&gt;Walk through it if the interviewer asks you to.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advent of Code&lt;/strong&gt;&lt;br /&gt;
I’ve passively been working through &lt;a href=&quot;http://adventofcode.com/&quot;&gt;Advent of Code&lt;/a&gt;. It’s an Advent Calendar that hands out difficult coding problems instead of delicious chocolate.&lt;/p&gt;

&lt;p&gt;It’s fun, and many people are doing it which has lead to good discussions. On the other hand, I’ve been feeling less enthused about random coding problems. I’m more interested in working on projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Essentialism&lt;/strong&gt;&lt;br /&gt;
I’ve started reading “&lt;a href=&quot;https://www.goodreads.com/book/show/18077875-essentialism&quot;&gt;Essentialism: The Disciplined Pursuit of Less&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;Ironically, I think reading about time management is non-essential - but I’m going to put that aside and pretend it’s the book teaching me that 🤓.&lt;/p&gt;

&lt;p&gt;In the past week I’ve been thinking a lot about what is essential. Sometimes I think of things to strip away, without any immediate idea of what to replace them with. My plan is to fill a lot more of my time journalling and meditating.&lt;/p&gt;

&lt;h3 id=&quot;physical-&quot;&gt;Physical 🚶&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Park walk&lt;/strong&gt;&lt;br /&gt;
On Sunday I went for a walk through Prospect Park with some housemates. It was nice to be away from computers and technology and just stroll about. Fresh air always makes me feel better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blob&lt;/strong&gt;&lt;br /&gt;
Days on end of sitting at a computer is really starting to make me feel out of shape. REALLY looking forward to settling in somewhere and being able to do a better job of focusing on my health.&lt;/p&gt;

&lt;h3 id=&quot;end&quot;&gt;&amp;lt;/End&amp;gt;&lt;/h3&gt;

&lt;p&gt;Woo! We did it!&lt;/p&gt;

&lt;p&gt;While I may not be feeling like a massively better programmer at the moment, I sure feel like a much better person.&lt;/p&gt;

&lt;p&gt;I was thinking about how much time I’ve invested in blogging and reflecting. It can be exhausting having to reflect on every week. At the same time, I’m excited to have this log to look back on. It’s super interesting seeing all the ups and downs I’ve felt throughout the batch.&lt;/p&gt;

&lt;p&gt;Thanks for reading ❤️.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to @vaibhavsagar and @stanzheng for providing this weeks round of blog feedback.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 08 Dec 2016 00:00:00 -0500</pubDate>
        <link>https://haroldtreen.com/tech/recurse/2016/12/08/recurse-center-week-10/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/recurse/2016/12/08/recurse-center-week-10/</guid>
        
        
        <category>tech</category>
        
        <category>recurse</category>
        
      </item>
    
      <item>
        <title>Week[8] @ The Recurse Center 🦃</title>
        <description>&lt;p&gt;Just another week late post! No. Big. Deal. 😁&lt;/p&gt;

&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;

&lt;p&gt;A lot of recovery from the Hackathon. RC was also closed most of the week for Thanksgiving, so not as productive as usual.&lt;/p&gt;

&lt;h3 id=&quot;emotional-&quot;&gt;Emotional 😩&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Apathy&lt;/strong&gt;&lt;br /&gt;
This has become a big feel:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“There’s no point…”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s how it goes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Outgoing Me: “I should ask X to do Y.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Apathetic Me: “There’s no point. I don’t know X that well / They probably won’t want to do Y / They will be too busy.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Outgoing Me: “Who cares! How do you know? You want to, so try!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Apathetic Me: “…I only have 3 weeks left. It’s not enough time to significantly improve my relationships with anyone / I should be focusing on coding.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s been bothering me.&lt;/p&gt;

&lt;p&gt;I’ve been really enjoying coding and do want to give that more energy…&lt;br /&gt;
But I’m also in this new city with cool people… maybe I should leave the coding for when I’m at home…&lt;/p&gt;

&lt;p&gt;Deep down, I know time with people is what I really want. When invitations come my way, I happily drop what I’m doing to hang out.
But when I start thinking about initiating that time myself, that’s when the stories of “Coding is more important” pop-up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nervousness and Fear&lt;/strong&gt;&lt;br /&gt;
I was reading books to try and better understand my apathy and came across an idea that clicked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apathy is a defense mechanism. It’s a way of avoiding what we’re afraid of.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It rings true for me. The things I want to do make me uncomfortable.&lt;/p&gt;

&lt;p&gt;But I don’t want to acknowledge that discomfort (thinking of myself as fearless and in control is way nicer 😎).&lt;/p&gt;

&lt;p&gt;So instead I deny it.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Apathy = Fear + Denial&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s not that I’m &lt;strong&gt;afraid&lt;/strong&gt;.&lt;br /&gt;
I just &lt;strong&gt;don’t care&lt;/strong&gt;  ¯\_(ツ)_/¯.&lt;/p&gt;

&lt;p&gt;Since starting to ponder this I’ve been better at noticing it and acting anyway.&lt;/p&gt;

&lt;h3 id=&quot;social-&quot;&gt;Social 🍲&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Chill time with friends&lt;/strong&gt;&lt;br /&gt;
Despite my apathy, it’s been really nice getting opportunities to hang out with people outside of RC.&lt;/p&gt;

&lt;p&gt;On Monday, I finally got to see a friend from my Microsoft Intern days.&lt;br /&gt;
On Friday, I went with some other RCers to a board games cafe.&lt;/p&gt;

&lt;p&gt;Hearts for low-key socializing! ❤️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Potlucks and parties&lt;/strong&gt;&lt;br /&gt;
Thanksgiving caused RC to be closed for the majority of the week. A bunch of us aren’t from New York / didn’t have plans, so @ebb-tide hosted a Thanksgiving potluck.&lt;/p&gt;

&lt;p&gt;It brought me back to my dinner party days in Vancouver.&lt;br /&gt;
Tables full of food and drink. Couches to snuggle up on. Wonderful humans to talk to.&lt;/p&gt;

&lt;p&gt;Was so full of gratitude and happiness the whole evening. Gah! 😍&lt;/p&gt;

&lt;p&gt;Wednesday there was a smaller gathering. It was nice being with close pals and also meeting some people from outside the RC community. 🙂&lt;/p&gt;

&lt;p&gt;Such a lovely mélange of socializing this week!&lt;/p&gt;

&lt;h3 id=&quot;intellectual-&quot;&gt;Intellectual 🔮&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Building communities&lt;/strong&gt;&lt;br /&gt;
I had a lot of great conversations throughout the week about &lt;em&gt;“What comes after RC?”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Another idea that’s had me excited is starting a coliving space. I spent most of Saturday:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Asking people about past experiences with coops/coliving.&lt;/li&gt;
  &lt;li&gt;Researching existing coops/coliving spaces.&lt;/li&gt;
  &lt;li&gt;Aggregating lists of resources.&lt;/li&gt;
  &lt;li&gt;Debating ideas with friends.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve started looking for spaces to visit or apply to. One consistent piece of advice was to give it a try before diving in.&lt;/p&gt;

&lt;p&gt;Nevertheless, questions around community building have been fascinating me and it seems like a stream of enthusiasm worth following.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to spend my time?&lt;/strong&gt;&lt;br /&gt;
Another question I’ve been pondering is &lt;em&gt;“How do I want to spend my time?”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;My one approach to making time decisions, is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What are my goals? Is this the most impactful way to move towards them?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s interesting how this changes the way I spend time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I used to read a lot online. In fact, &lt;a href=&quot;https://epub.press&quot;&gt;EpubPress&lt;/a&gt; was created to help me manage my intake of reading material.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Quora&lt;/li&gt;
  &lt;li&gt;HackerNews&lt;/li&gt;
  &lt;li&gt;Newspapers&lt;/li&gt;
  &lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve since realized the majority of what I read isn’t immediately useful to me.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“How we scale @ {insert_startup}”&lt;br /&gt;
Ooo! How DO they scale? 😱&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;I don’t know… but why does it matter? I see no need to create a hyper growth system any time soon. If I ever do, I’m sure there’s better resources than something from HackerNews.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Introducing {insert_generic_word}. A simple, elegant and intuitive JS framework”&lt;br /&gt;
Ooo, I write Javascript! I haz need for this 😱!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;No you don’t, Harold. You’re in no need of a framework… in fact, nobody writing Javascript needs another framework.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’ve generally found this value has pushed my time towards more fulfilling activities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Haskell Progress&lt;/strong&gt;&lt;br /&gt;
The other day I finished my CIS194 course! 🎓&lt;/p&gt;

&lt;p&gt;By the end of it, I really started enjoying Haskell. It’s so different from Javascript and required learning a whole other set of concepts.&lt;/p&gt;

&lt;p&gt;I think it was the right choice 😊.&lt;/p&gt;

&lt;h3 id=&quot;physical-&quot;&gt;Physical 🛌&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;So much sleep!&lt;/strong&gt;&lt;br /&gt;
The Hackathon last week in addition to the night-owling really messed up my sleep schedule. On Wednesday night I got home at 3am and cooked myself dinner…&lt;/p&gt;

&lt;p&gt;Getting things back on schedule so I can live a more normal life again. @hsubox also found me a pillow, so goodbye pillowcase stuffed with sweater! 😁&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pending baking fiasco&lt;/strong&gt;&lt;br /&gt;
I cooked Chicken Parmesan again last week!&lt;/p&gt;

&lt;p&gt;I also bought 2.25 kilograms of flour a month ago because my Eggplant Parmesan recipe called for a 1/2 cup of flour…so I’m currently rolling in excess flour.&lt;/p&gt;

&lt;p&gt;Decided to just go all in and buy a bunch of cookie ingredients. So hopefully no wasted flour! Look at me, making sure none of my $2.50 bag of flour is wasted by buying an additional $10 of ingredients. #Smart 🤓&lt;/p&gt;

&lt;h3 id=&quot;end&quot;&gt;&amp;lt;/End&amp;gt;&lt;/h3&gt;

&lt;p&gt;Done! Made it! Fantastic!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Action items:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wake up to what an opportunity these next few weeks are. Make the most of them!&lt;/li&gt;
  &lt;li&gt;Keep reshuffling time towards better priorities.&lt;/li&gt;
  &lt;li&gt;Bake five-dozen batches of cookies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Can’t. Wait.&lt;/p&gt;

&lt;p&gt;Hearts for you dear reader! ❤️&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to @vaibhavsagar and @yuliaju for easing my blogging worries through feedback.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 02 Dec 2016 00:00:00 -0500</pubDate>
        <link>https://haroldtreen.com/tech/recurse/2016/12/02/recurse-center-week-9/</link>
        <guid isPermaLink="true">https://haroldtreen.com/tech/recurse/2016/12/02/recurse-center-week-9/</guid>
        
        
        <category>tech</category>
        
        <category>recurse</category>
        
      </item>
    
  </channel>
</rss>
