<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Randall Koutnik</title>
    <description>You've found my corner of the internet! I opine on various topics that interest me (mostly tech, startups &amp; the like). Stick around and enjoy yourself!
</description>
    <link>https://rkoutnik.com/</link>
    <atom:link href="https://rkoutnik.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Mon, 25 Jul 2022 21:00:06 +0000</pubDate>
    <lastBuildDate>Mon, 25 Jul 2022 21:00:06 +0000</lastBuildDate>
    <generator>Jekyll v3.9.2</generator>
    
      <item>
        <title>Passing the generic tech interview</title>
        <description>&lt;p&gt;The software industry sucks at interviews.  Most companies don’t have a standardized way of comparing candidates and those that do don’t put much thought into them.  It’s usually convening the hiring panel and getting a thumbs-up from everyone.  This means that the job of an interviewee is not to demonstrate that they have the skills needed for the job at hand.  Instead, an interviewee’s primary goal is to get the interviewer to like them.&lt;/p&gt;

&lt;p&gt;I hate this.  I’d much rather be judged by my ability to do the job at hand instead of playing these psychological games.  Unfortunately, that’s the reality we live in.  Here’s a few lessons I’ve learned over the years.  While the advice in this post is very “works on my machine”, I hope you can pick up a few things that’ll help you in your future job-seeking endeavours.&lt;/p&gt;

&lt;p&gt;I’ve interviewed a lot, thanks to my status as “the Typhoid Mary of startups” requiring that I find a new job a little too often for my own comfort.  When I’m sitting down for an interview, my initial goal is to figure out what the interviewer across the table wants.  Usually, I do some backchannel communication to figure out what the interview culture is like at the company.  Occasionally, the company has put some thought into interviewing and the following doesn’t apply (i.e. Netflix).&lt;/p&gt;

&lt;p&gt;In most cases, I need to gear up and reread How To Win Friends and Influence People.  Once I’m at the interviewing table, it’s all about making the person across from me happy. I’ve found that interviewers usually fall into a few broad categories:&lt;/p&gt;

&lt;h3 id=&quot;here-because-they-were-told-to&quot;&gt;Here because they were told to&lt;/h3&gt;

&lt;p&gt;The company has done nothing to help this person become a good interviewer.  They almost certainly googled “JavaScript Interview Questions” five minutes ago.  It helps to know the answers to the interviewer’s questions, but it’s more about making them relaxed. Crack jokes, lob softball questions at them, add comments about how cool the company is. I want them to walk out thinking “that wasn’t so bad, Randall’s a pretty cool guy”.  Bonus points if you’ve got something impressive to show off (open source work, a neat tech talk).  Try to work that in somewhere if possible.&lt;/p&gt;

&lt;h3 id=&quot;here-to-show-off-how-smart-they-are&quot;&gt;Here to show off how smart they are&lt;/h3&gt;

&lt;p&gt;Oh boy.  They’re here to interrogate you and “prove” they’re smarter than you are with tricky questions.  These questions usually take the form of a simple task, with increasingly-difficult-yet-absurd burdens added in (“now do it without if statements”).  Other times it’s time for JavaScript Pub Trivia, with a side helping of sneering disdain if you get anything wrong.  If I’m interviewed by someone in this category, the company immediately gets tossed into the “absolutely not” bucket.  Usually I just go with rote answers or, if I’m feeling cheeky, dance around the tricky questions they ask.&lt;/p&gt;

&lt;h3 id=&quot;here-to-ask-the-specific-question&quot;&gt;Here to ask The Specific Question&lt;/h3&gt;

&lt;p&gt;Often, interviewers have one big question they ask at every interview.  These can be fun.  I try to make it a back-and-forth thing, instead of me sitting there silently solving away.  They’ve probably seen dozens of solutions, so I try to ask questions around the problem (“what about this?”  “What happens when X?“).  Even if we don’t cover those areas, I want to stand out in their mind from everyone else who just followed instructions.&lt;/p&gt;

&lt;p&gt;(When I’m interviewing without guidance, &lt;a href=&quot;https://rkoutnik.com/articles/How-I-Interview.html&quot;&gt;this is the style I use&lt;/a&gt;)&lt;/p&gt;

&lt;h3 id=&quot;the-culture-fit-interview&quot;&gt;The Culture Fit Interview&lt;/h3&gt;

&lt;p&gt;“Tell me about a time when….“.  Luckily I’ve got tons of stories (see Typhoid Mary).  The key is to spend about 40% of the storytelling time talking about my own failings and what I’ve learned.  Bonus points if I can follow it up with another story where I applied what I learned.  Most folks on my side of the table only talk about their successes, which makes sense on the surface (it’s an interview, show off your good side) but from a “make this person like me” standpoint, it just comes off as arrogant.&lt;/p&gt;

&lt;p&gt;One common thing I do in all but the showoff category is that I ask about what they do at the company.  This helps me figure out a bit more about the company itself but the primary purpose is to get the interviewer talking about something that’s important to them.  (People who feel their job isn’t important usually don’t get picked for interview panels).  Once I know what their role is, I can reflectively listen.  This ends up being pretty flattering to the interviewer without actually coming across as such.&lt;/p&gt;

&lt;p&gt;Usually, I’m asked for feedback immediately after the interview.  If asked for feedback, I’m not going to be honest.  That doesn’t mean I’m going to lie, it means I’m going to give the feedback I think the interviewer wants to hear.  In most places, that means something that looks like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“Oh, that was great!”&lt;/li&gt;
  &lt;li&gt;“I especially appreciated… (point out something that was nice)”   Some examples: “Everyone made time for me to ask questions” or “thanks for bringing me water, my throat was parched!”&lt;/li&gt;
  &lt;li&gt;“One concern I have is… (here’s a great opportunity to provide a layup for the interviewer/recruiter to answer)”  Usually I mention something I know they can solve (commute =&amp;gt; WFH/shuttles) that hasn’t been mentioned yet in the interviews.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, all of this is a moot point if the company’s put some serious thought into what sort of candidates they’re looking for and how their interview process selects for that.  But that’s a rarity, and this philosophy has worked out for me - I haven’t had trouble finding a job in my 7(!) job searches.  Caveats apply, but this post is already too long.&lt;/p&gt;

&lt;p&gt;Also notable is that this strategy optimizes for offers, not finding the best fit for me.  I’ve pretty much given up on determining the latter via interview, as &lt;a href=&quot;https://rkoutnik.com/2020/05/03/corporate-culture-gap.html&quot;&gt;everyone’s faking it on all sides of the table&lt;/a&gt;.  The only effective thing I’ve found is knowing someone on the inside who can be blunt with me about the real culture (and even that doesn’t always work).&lt;/p&gt;
</description>
        <pubDate>Mon, 17 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://rkoutnik.com/2020/08/17/passing-the-generic-tech-interview.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2020/08/17/passing-the-generic-tech-interview.html</guid>
        
        
      </item>
    
      <item>
        <title>The Corporate Culture Gap</title>
        <description>&lt;p&gt;I was involved in a recent chat conversation around the concept of “Culture Buddies.”  The idea is to help onboard new employees by having a current employee assigned to them with the specific task of helping the new employee acclimate to the company’s culture.&lt;/p&gt;

&lt;p&gt;I had a direct and immediate dislike of the idea.&lt;/p&gt;

&lt;p&gt;(Note: this is different from finding a trusted friend at a company to help you navigate the sticky parts - something I strongly recommend).&lt;/p&gt;

&lt;p&gt;The fact is, virtually every software company has a significant gap between culture-as-imagined and culture-as-practiced.  For example, many companies claim to “hire the best” but still pay below-market.  However, pointing out this contradiction is not a great way to further your career.&lt;/p&gt;

&lt;p&gt;Now let’s imagine a corporate Culture Buddies program. The type of person who’d be selected to be a “Culture Buddy” is likely someone who will present culture-as-imagined even when it does not line up with culture-as-practiced.  The company wants to present culture-as-imagined to new hires.  When I start a new job, I’m looking for the opposite - I want to know what the exceptions to the stated culture are so I don’t end up running face-first into them (which I’ve done many times in my career).&lt;/p&gt;

&lt;p&gt;Often the difference between culture-as-imagined (CAI) and culture-as-practiced (CAP) isn’t visible to those higher up, as those lower down smooth over issues to preserve the image.
If your company has a significant gap between CAI and CAP, then a buddy system designed by those very same higher-ups won’t help you.  You have bigger problems.  Oh, and your company definitely has a significant gap.  Basically everyone does.&lt;/p&gt;

&lt;p&gt;So what should we do?&lt;/p&gt;

&lt;h2 id=&quot;the-corporate-culture-gap&quot;&gt;The Corporate Culture Gap&lt;/h2&gt;

&lt;p&gt;A company needs a goal.  Without a goal, you can’t have alignment - there isn’t anything to align towards.  Without alignment, you can’t build trust, and without trust, you’re lost in a hopeless maze of micromanaging.&lt;/p&gt;

&lt;p&gt;So you need a goal.  What makes for a good goal is a bit out of the scope of this discussion.  As the leader of a company, you need to:
Make sure everyone knows the goal of the company (so repeat it whenever you can!)
Make sure everyone knows their part of the goal&lt;/p&gt;

&lt;p&gt;The most egregious splits between CAI and CAP I’ve seen were because there was a stated goal (or worse, multiple stated goals) and it was abundantly clear to those paying attention that the actions of the company (and the orgs within the company) were not in alignment with the goal.  This is called the Corporate Culture Gap.  Speaking up about actions not being aligned with stated goals results in being labeled “not a culture fit”.  This label does significant harm to your career, and can often result in termination.&lt;/p&gt;

&lt;p&gt;Some people just don’t care about the culture gap.  They just go into work, move some tickets from left to right, and go home.  Others are culture cheerleaders.  They focus just on CAI and ignore/justify the difference.  Some people just want to be a follower (and that’s ok!).  Finally, there are people who care deeply about key pieces of culture-as-imagined.  Most likely, the gap impacts them directly.  (CAI: “We Value Diversity”, CAP: “We Underpay Everyone Who’s Not A White Dude”).  For the group that cares deeply, there are those that speak up, and those that pretend to be cheerleaders.  In any company with a non-trivial gap, those that speak up are not appreciated.  Those that pretend can end up being effective, if miserable.&lt;/p&gt;

&lt;p&gt;To put it simply, the cruel irony of company culture is that you can only speak up to say “This is a psychologically unsafe environment” in a safe environment.&lt;/p&gt;

&lt;p&gt;So, I started this section by talking about goals.  What’s the goal of our culture buddy program?&lt;/p&gt;

&lt;p&gt;As a new employee, my goal is to learn as much about CAP as possible so that I can be effective within the system.  I won’t trust a buddy given to me by the company, because I’m looking to find the parts of the company’s culture that it can’t (or won’t) see.&lt;/p&gt;

&lt;h2 id=&quot;small-gaps&quot;&gt;Small Gaps&lt;/h2&gt;

&lt;p&gt;If there isn’t a significant culture gap, then that’s awesome!  Any engineer who’s had a few jobs has been burned by this gap enough that they’ll need some really solid proof that the company means what it says.  Personally, I’ll write off anyone assigned as a cheerleader.&lt;/p&gt;

&lt;p&gt;In this small-gap case, new employees take some time to adjust, but get there eventually.  This happened to pretty much everyone who joined Netflix.  There’d be an initial period where they’d be thinking “you don’t actually mean you let engineers do what they want” but as newcomers tested and experimented, they’d realize that yes, for the most part, Netflix lived up to its culture.  (Was there a gap?  Certainly.  But it’s the smallest gap I’ve seen and management was open about times when the culture failed.)&lt;/p&gt;

&lt;p&gt;So in the small-gap case, from management’s perspective, a culture buddy may help things along and get the new employee adjusted a bit faster.  Though not that much faster, because in the small-gap case, everyone’s living the culture anyway so a specific person may not be that helpful.&lt;/p&gt;

&lt;p&gt;In the large-gap case, on the other hand…&lt;/p&gt;

&lt;h2 id=&quot;large-gaps&quot;&gt;Large Gaps&lt;/h2&gt;

&lt;p&gt;If you’re a manager at a large-gap company and are aware of (and dislike) the gap, then the goal is to build a small-gap team.  An onboarding buddy will be enormously helpful here to help the new employee guide the rough waters that would result in the cultural mismatch between a small-gap, goal-driven team and the wider, large-gap company.  However, this’d be a pretty high-touch situation, for obvious reasons.&lt;/p&gt;

&lt;p&gt;If you’re a manager/leader at a large-gap company and either unaware of the gap (or aware and don’t care, which is the same thing), then the purpose of a culture buddy system is a little more vague.  I find it a bit more difficult to write about this situation without just getting all cynical everywhere.&lt;/p&gt;

&lt;h2 id=&quot;an-example-gap&quot;&gt;An Example Gap&lt;/h2&gt;

&lt;p&gt;Let’s look at a specific example to illustrate the difference between Culture As Imagined and Culture As Practiced: Feedback.&lt;/p&gt;

&lt;p&gt;Culture-as-imagined (CAI), every company ever says that feedback is important.  Feedback becomes a Key Cultural Value, companies offer classes on effective feedback, managers talk about how valuable feedback was to them, etc, etc.  This looks great until someone actually gives constructive feedback.  Suddenly, the culture gap becomes very visible.&lt;/p&gt;

&lt;p&gt;Some managers treat feedback as confusion, and instead of responding to the feedback, they keep on explaining, as if it was abundantly clear how they were right.  Feedback was something tossed into a void.  In this case, employees learn to shut up and nod.  Worse, these managers think they’re doing a great job!  After all, if they were doing a bad job, someone would say something.  Other managers start screaming fits whenever they’re questioned.  Heck, one place I worked, all feedback was just straight-up ignored.&lt;/p&gt;

&lt;p&gt;Early on in my career, I would run into this cultural mismatch right off the bat.  I’d see something that could be improved and give feedback - just like the culture docs said!  At best it would fall by the wayside and I’d discover that the company wasn’t really interested in my feedback.  At worst, I’d endure a public berating in front of all of my new teammates.  Either way, I burned a lot of social capital because I followed the company’s stated values.&lt;/p&gt;

&lt;p&gt;I can’t say I always gave feedback well - this is something I’ve improved a lot over the years, with a long way to go - but the companies set new employees up to fail.  This might even be the catalyst for a culture buddy system!  “Hey, new folks end up with a rough start, maybe we could help them out.”  Good intentions, but the problem here isn’t the onboarding, the problem is you’re lying to your employees.  Fix that, and the onboarding problem gets fixed too.&lt;/p&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;Any leader who wants to be a good leader (and not just “in charge”) needs to keep the corporate culture gap in mind through all of their decisions, large and small.  Adding a “culture buddies” program is just a band-aid on a much larger problem.  The best companies out there recognize the key to a smooth onboarding isn’t further indoctrination but building trust by being open and honest internally about how the corporate culture works in practice.&lt;/p&gt;

&lt;p&gt;Thoughts?  I’d love to hear them.  You can reach me at &lt;a href=&quot;mailto:blog@rkoutnik.com&quot;&gt;blog@rkoutnik.com&lt;/a&gt; or in shorter form at https://twitter.com/rkoutnik&lt;/p&gt;
</description>
        <pubDate>Sun, 03 May 2020 00:00:00 +0000</pubDate>
        <link>https://rkoutnik.com/2020/05/03/corporate-culture-gap.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2020/05/03/corporate-culture-gap.html</guid>
        
        
      </item>
    
      <item>
        <title>Exploring JavaScript's types</title>
        <description>&lt;p&gt;You’ve seen the &lt;a href=&quot;https://rkoutnik.com/2018/09/24/why-typescript-great.html&quot;&gt;hype around TypeScript&lt;/a&gt; and are wondering exactly how these types help us programmers out.  If you’ve made it this far into your career without learning about intuitionistic type theory or what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T = ∃X { a: X; f: (X → int); }&lt;/code&gt; means, that’s just fine.  There are plenty of fantastic languages out there that don’t require knowing what a “type” is, so it’s possible to get quite far without diving into the complicated stuff.  For the record though, I have no idea what those things are either, I just ripped them off Wikipedia.&lt;/p&gt;

&lt;p&gt;Anyway - on to TypeScript, a much more approachable typed language.&lt;/p&gt;

&lt;h2 id=&quot;whats-a-type&quot;&gt;What’s a ‘type’?&lt;/h2&gt;

&lt;p&gt;A ‘type’ means ‘some category of value’ and is usually assigned to a variable.  We can say “this variable will contain a number” with the following syntax:&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;userAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&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;At this point, we haven’t defined what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;someVariable&lt;/code&gt; is, just that it can only contain a number.  If we try to stick something in there that isn’t a number, then we’ll get a big ol’ complaint from TypeScript:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/angrysquiggle.png&quot; alt=&quot;Angry red squiggle&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The angry red squiggle here is because we’ve told TypeScript that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;userAge&lt;/code&gt; is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; and what we’re assigning is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;.  No need to worry about structural type systems vs nominative type systems, this is all stuff you probably know already but lacked the vocabulary to explain.&lt;/p&gt;

&lt;p&gt;There’s a whole bunch of types that come out of the box in the JavaScript language:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;String&lt;/li&gt;
  &lt;li&gt;Number&lt;/li&gt;
  &lt;li&gt;Boolean&lt;/li&gt;
  &lt;li&gt;Null&lt;/li&gt;
  &lt;li&gt;Undefined&lt;/li&gt;
  &lt;li&gt;Object&lt;/li&gt;
  &lt;li&gt;Symbol (added in ECMAScript 6)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These types are known as &lt;em&gt;primitive&lt;/em&gt; types because they’re the basic building blocks every other type is made up of.  They’re a bit like &lt;a href=&quot;https://www.youtube.com/watch?v=Uy0m7jnyv6U&quot;&gt;the elements&lt;/a&gt; in physics.  The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typeof&lt;/code&gt; operator&lt;/a&gt; will return a string definition of the type…mostly.&lt;/p&gt;

&lt;p&gt;Most of these are pretty straightforward, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; is a number, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boolean&lt;/code&gt; is true or false and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Symbol&lt;/code&gt; is something fancy to give conference talks about.  (Kidding - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Symbol&lt;/code&gt; does have its uses but that’s another post).  The most important type here is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object&lt;/code&gt;: A variable that has properties of its own.  Each property can have its own type.  However, there’s a few surprises in this list: there’s no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; are separate types.&lt;/p&gt;

&lt;h3 id=&quot;null-vs-undefined&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Mostly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined&lt;/code&gt; were both added to the language because it was whipped together so fast.  Some argue that only one is needed (both represent “there’s nothing here!”) but they’ve come to mean different things.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; is deliberate - the programmer has intentionally set this variable to nothing.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined&lt;/code&gt; means that no value has been set yet.  This is just a convention, so don’t expect everyone to agree on it.&lt;/p&gt;

&lt;h3 id=&quot;whered-array-and-function-go&quot;&gt;Where’d &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function&lt;/code&gt; go?&lt;/h3&gt;

&lt;p&gt;There are two big omissions in the list of primitive types.  They certainly still exist, but this is one of the quirks of JavaScript, thanks version 1 to being defined in a little less than 2 weeks.  &lt;em&gt;Technically&lt;/em&gt; speaking, both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function&lt;/code&gt; are of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object&lt;/code&gt;, though the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typeof&lt;/code&gt; operator kinda gets this right:&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;arr&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;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typeof&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;c1&quot;&gt;// 'object'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 'function'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In JavaScript, arrays and functions are just objects with some special abilities added on, which is why the following works:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;let arr = [];
arr.foo = 'bar';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We just added an entirely new property to this array instance!  We can do this because an array is still an object, and objects let us define arbitrary properties.  (TypeScript will still get mad at you).  Arrays are “An object that can contain a list of things and has some methods and properties related to that” and functions are “an object that can be called (that is, do something when parentheses are added)”.  Both of these are built by starting with an object and adding some extra properties onto it.&lt;/p&gt;

&lt;h2 id=&quot;assigning-types-in-typescript&quot;&gt;Assigning types in TypeScript&lt;/h2&gt;

&lt;p&gt;In TypeScript, a colon is used to indicate a type definition, like above with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let userAge: number&lt;/code&gt;.  An array of things can be defined by adding square brackets after whatever type of thing it is, so an array of numbers is defined by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let userAges: number[]&lt;/code&gt;.  Functions are usually defined at the time of assignment (see Type Inference below) but in a pinch can be assigned as such:&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;c1&quot;&gt;// takes an int and returns a string&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&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;kr&quot;&gt;string&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;h3 id=&quot;the-special-any-type&quot;&gt;The special any type&lt;/h3&gt;

&lt;p&gt;JavaScript is a loose language (to put it politely) and so sometimes we may just throw our hands up and say “I have no idea what type this is!”  In that particular case, TypeScript provides the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;any&lt;/code&gt; type.&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;numArr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// legal&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;numArr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// illegal&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;numArr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;whateverArr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// both legal&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;whateverArr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;whateverArr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// It's still an array though!&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;whateverArr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&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;h2 id=&quot;creating-your-own-types&quot;&gt;Creating your own types&lt;/h2&gt;

&lt;p&gt;This set of primitive types is great to start out with, but any serious application will need to define its own types.  Fortunately, that’s provided through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type&lt;/code&gt; keyword - used like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const&lt;/code&gt; but for declaring a type.  For instance, &lt;a href=&quot;https://rkoutnik.com/2018/09/24/why-typescript-great.html&quot;&gt;the previous post&lt;/a&gt; had an array of user objects:&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;users&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;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Robert&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Smith&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Dana&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Jones&lt;/span&gt;&lt;span class=&quot;dl&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;In this case, a user is an object, and that object has three properties, two strings and a number.  (Starting to see how we build more complex things from primitive types?)  Adding in the type looks like this:&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;User&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;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&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;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Robert&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Smith&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Dana&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Jones&lt;/span&gt;&lt;span class=&quot;dl&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;A little more verbose, but this means that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;users&lt;/code&gt; array will be used consistently around your entire application and catch a whole bunch of bugs before they get a chance to mess everything up (for instance, typing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;userId&lt;/code&gt; when you meant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;).  The larger the application (and the team working on it) the more powerful these benefits become.&lt;/p&gt;

&lt;h2 id=&quot;type-inference&quot;&gt;Type Inference&lt;/h2&gt;

&lt;p&gt;If all this talk about defining all these kinds of types sounds tedious, don’t worry!  TypeScript is smart enough that it can figure out most types without any input from you.&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;c1&quot;&gt;// TS knows age is just a number&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Even without type definitions, this will cause an error&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;I am &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; years old&lt;/span&gt;&lt;span class=&quot;dl&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;h1 id=&quot;finally&quot;&gt;Finally&lt;/h1&gt;

&lt;p&gt;If you have a headache, I don’t blame you.  This was supposed to be simple, and then JavaScript has to make things all complicated with the various asterisks and exceptions.  Unfortunately, it gets worse.  Next week, we’ll talk about how to use generic types and create our own version of an array.&lt;/p&gt;
</description>
        <pubDate>Sun, 30 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://rkoutnik.com/2018/09/30/intro-to-typescript.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2018/09/30/intro-to-typescript.html</guid>
        
        
      </item>
    
      <item>
        <title>Why is TypeScript so great?</title>
        <description>&lt;p&gt;In my developer career, I don’t think I’ve met anything as revolutionary as &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;.  There are plenty of shoulders TypeScript is standing on (everyone who worked to get JS devs to accept build systems!) but TypeScript is a brilliant cumulation of that work that’s fundamentally changed how I do my job.  So much so, that I finally switched off my beloved Sublime Text to Visual Studio Code for better TypeScript support.&lt;/p&gt;

&lt;p&gt;(As an aside, the fact that I’m using a Microsoft editor to write a Microsoft language and that both are open source still feels weird)&lt;/p&gt;

&lt;p&gt;For those of you new to frontend development (or those who are returning after a long hiatus), TypeScript is a new language that’s a superset of JavaScript that adds optional types into the mix.  Here’s a snippet of TypeScript:&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;currentUserId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;users&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;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Robert&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Smith&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Dana&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Jones&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}];&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currentUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;u&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;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currentUserId&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;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Hello,&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currentUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;dl&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;Most importantly, you’ll notice that there aren’t any type annotations or other funky business in this snippet.  &lt;em&gt;All JavaScript is also valid TypeScript&lt;/em&gt;.  This is TypeScript’s greatest asset.  All you need to do to convert a codebase to TypeScript is a single command:&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;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*.js&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'mv &quot;$1&quot; &quot;${1%.js}&quot;.ts'&lt;/span&gt; - &lt;span class=&quot;s1&quot;&gt;'{}'&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(ok, ok, so there’s more to it than that.  We’ll get to that later).&lt;/p&gt;

&lt;p&gt;So all your JavaScript is valid TypeScript.  So what?  The answer lies in just how dang &lt;em&gt;smart&lt;/em&gt; TypeScript is.  It’s not just “We jammed a bunch of types into JavaScript”, but an entire ecosystem of tooling around that, all built with the developer in mind.  It took some time to get where we are today (I gave up on TypeScript several times in the dark days of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v0.x&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;TypeScript takes a look at the above snippet and knows that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;users&lt;/code&gt; is an array of objects and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt; is a method on an array that returns another array.  Therefore, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentUser&lt;/code&gt; is an array and …wait a minute!  Arrays don’t have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firstName&lt;/code&gt; property!  TypeScript then slams a red squiggle underneath this glaring issue, allowing you to fix it right in the editor itself.  No need to content switch to the browser, stare at a bizarre &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined&lt;/code&gt; that shouldn’t be there, and eventually track it down to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt; that should be a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before TypeScript, I made these kinds of mistakes all the time and caught &lt;em&gt;most&lt;/em&gt; of them before they got to production.  Now I still make these sorts of mistakes all the time but they’re caught immediately instead of creating incredibly quirky bugs.&lt;/p&gt;

&lt;p&gt;TypeScript changed the game even without needing to modify our code at all.  Even at the start, it’s a super-linter that allows us to offload an enormous amount of working memory about our codebase and JavaScript to a tool, allowing us to spend those brain cells on a better architecture and writing mushy love letters masquerading as blog posts about said tools.&lt;/p&gt;

&lt;p&gt;TypeScript is incredibly powerful as a super-linter and would be just fine if that’s all it did.  Next time we’ll talk about types, how to define them in TypeScript, and just why that’s useful.&lt;/p&gt;
</description>
        <pubDate>Mon, 24 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://rkoutnik.com/2018/09/24/why-typescript-great.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2018/09/24/why-typescript-great.html</guid>
        
        
      </item>
    
      <item>
        <title>Stateful Filters in RxJS</title>
        <description>&lt;p&gt;I’m just finishing the last stages of writing &lt;a href=&quot;https://pragprog.com/book/rkrxjs/build-reactive-websites-with-rxjs&quot;&gt;Building Reactive Websites with RxJS&lt;/a&gt;, to be published through Pragmatic Publishing.  I’m a huge fan of RxJS, even if it is a bit complicated to get used to.  In an effort to demystify this library, I’d like to walk through a few case studies over the next few weeks and analyze how to use it in real-world scenarios.&lt;/p&gt;

&lt;p&gt;The first case study comes from one of my old jobs at a cybersecurity company.  This company had an offering where they’d crawl The Dark Web (I still can’t belive sales folks said that with a straight face) and look for keywords set up by clients.  Ostensibly, this tool could be used to detect leaks of software and/or internal documents.  In order to achieve this scanning ability, we need to build a filter that can be dynamically updated.&lt;/p&gt;

&lt;p&gt;The crucial thing to think about when writing software using RxJS is to model everything as a stream of events over time.  If your application does not lend itself well to this modeling, RxJS may not be for you.  Fortunately, this task is easy to model as two separate streams.  One, from Kafka, is new data from the crawler.  The other comes from a database poller and contains the keywords our filter needs to test against.&lt;/p&gt;

&lt;p&gt;We’ll start off with two magic variables that represent these streams, as dealing with Kafka is outside the scope of this post.  Appending a dollar sign to the end of the variable is a convention used to show that variable is an observable.&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;crawlResults$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;latestKeywords$&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;RxJS already has a built-in filter operator, so this would work, at least until the list of keywords was updated.&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;crawlResults$&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyword&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 tricky part of this challenge is that we’re implementing a &lt;em&gt;stateful&lt;/em&gt; filter.  Clients could update the keyword list at any time.  We’ll need to store that state somewhere.  One option is to just create an array of keywords and manually keep it updated:&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;filterKeywords&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;c1&quot;&gt;// every five minutes&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&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;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;mergeMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dbQuery&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;subscribe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newFilterKeywords&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;filterKeywords&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;newFilterKeywords&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 leaves us holding the bag around both state and managing subscriptions.  In this example, we need to make sure that the subscription is properly disposed of, otherwise we might accidentally create tons of pollers and overwhelm the database with queries (this never happened, I don’t know what you’re talking about and don’t belive anything my former coworkers say about this).&lt;/p&gt;

&lt;p&gt;The obvious advantage of RxJS is modeling everything as streams but a lesser-known advantage is that RxJS provides many ways to store state inside the framework, ensuring that the library worries about subscriptions and filtering.  Combining two streams together in RxJS is known as ‘merging’ and there’s a variety of merge operators to utilize here.  Most merges don’t maintain an internal state and just send data on when they get it.  Here, we want to know the latest value from both streams on every event, so we turn to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;combineLatest&lt;/code&gt;.  The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;combineLatest&lt;/code&gt; constructor tracks multiple streams and on an event from any stream, emits the latest value of all streams as an array.&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;combineLatest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;crawlResults$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;latestKeywords$&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;We’re almost there.  The one remaining problem is that whenever &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestKeywords$&lt;/code&gt; updates, this might pass along the latest hit from the crawler as well.  There’s one operator that’ll save us: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;distinctUntilChanged&lt;/code&gt;, which is a stateful filter that only passes a value if it’s different from the previous value.  Throw in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; to extract the results from the keywords, and this looks like:&lt;/p&gt;

&lt;div class=&quot;language-typescript 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;combineLatest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;crawlResults$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;latestKeywords$&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;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyword&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;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;distinctUntilChanged&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;Tada!  A stateful merge filter, with the heavy lifting offloaded to the RxJS library.  If you want to learn more about RxJS, including building many functional examples, check out &lt;a href=&quot;https://pragprog.com/book/rkrxjs/build-reactive-websites-with-rxjs&quot;&gt;Building Reactive Websites with RxJS&lt;/a&gt;, now in beta.&lt;/p&gt;
</description>
        <pubDate>Mon, 17 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://rkoutnik.com/2018/09/17/rxjs-stateful-filter.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2018/09/17/rxjs-stateful-filter.html</guid>
        
        
      </item>
    
      <item>
        <title>Incentivize Teams, not People</title>
        <description>&lt;p&gt;Any programmer worth their salt is willing to help team members out when they’re in a pinch.  Software development is a team sport, after all.  Unfortunately, management can often completely miss the point and create perverse incentives that wreck a team’s cooperation and communication.  If you’re a software manager, here’s a quick self test:&lt;/p&gt;

&lt;p&gt;Put together a list of all of your incentives, from compensation increases &amp;amp; promotion to “Who gets the new project”.  Make sure to include things like a regular team lunch or a “Employee of the Month”.  Now, go through that list and ask yourself the following question for each item:&lt;/p&gt;

&lt;p&gt;“If Bob goes over to Alice and says ‘Do you have a minute?  I need help with something.’, does this incentive move Alice towards helping Bob?”&lt;/p&gt;

&lt;p&gt;Let’s go through some common management antipatterns and what impact they have on Alice’s answer.&lt;/p&gt;

&lt;p&gt;The worst of the worst are programs that link cash or other bonuses to individual performance goals.  Tying individual performance to comp means that the better financial decision for Alice is to make an excuse and focus on her own work metrics instead.  Bob’s unhappy because he’s still blocked.  Alice is also unhappy because she has to choose between focusing on her work or falling behind on her performance goals.  Do you really think more cash will increase morale enough offset this massive break in teamwork?&lt;/p&gt;

&lt;p&gt;On the other hand, some bonus programs reward engineers with bonuses that are dependent on &lt;em&gt;company&lt;/em&gt; performance (the biggest team there is!).  Alice earns more if the entire company does well, rather than focusing exclusively on Alice’s own objectives.  Now Alice’s extrinsic and intrinsic incentives are aligned.  She can help Bob, safe in the knowledge that the company wants them both to succeed.&lt;/p&gt;

&lt;p&gt;Some companies (like my employer, Netflix) go a step further and do away with bonuses entirely, providing top-of-market pay instead, coupled with explicit trust in the employee to do what’s best for the company in any given situation.  Netflix’s expense policy, “Act in Netflix’s best interests”, is the archetypical example.&lt;/p&gt;

&lt;p&gt;Promotions can be another sticking point.  If there’s an open req for a higher-level position that both Bob and Alice are hoping to get, they’re stuck in the same quandry.  &lt;a href=&quot;https://mtlynch.io/why-i-quit-google/&quot;&gt;Google is infamous for only looking at feature development&lt;/a&gt; when making promotion decisions and leaving everything (and everyone) else to the wayside.  Unsurprisingly, this means they’re launching &lt;em&gt;another&lt;/em&gt; chat app while letting Google Reader die.&lt;/p&gt;

&lt;p&gt;It may not be as direct as helping a coworker synchronously.  There are many other ways engineers work for the betterment of the team/org/company: writing documentation, providing product feedback, sitting in for UX testing, giving internal talks, and more.  One option is to sit down and create individual performance metrics for all of these activities.  The better option is to remove perverse incentives and let the team do what they do best: build great products.&lt;/p&gt;

&lt;p&gt;(Your interview process is filtering out the &lt;a href=&quot;http://www.brendangregg.com/blog/2017-11-13/brilliant-jerks.html&quot;&gt;brilliant jerks&lt;/a&gt;, right?)&lt;/p&gt;
</description>
        <pubDate>Sat, 17 Mar 2018 19:51:00 +0000</pubDate>
        <link>https://rkoutnik.com/2018/03/17/incentivize-teams-not-people.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2018/03/17/incentivize-teams-not-people.html</guid>
        
        
      </item>
    
      <item>
        <title>Hacking Calculords part 3: A math-free intro to neural networks</title>
        <description>&lt;p&gt;So far in the calculords series we’ve accomplished:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Part 1: &lt;a href=&quot;/2016/04/06/Hacking-Calculords.html&quot;&gt;Solving a level of Calculords in sub-sandwich time&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Part 2: &lt;a href=&quot;/2016/06/14/hacking-calculords-2-who-needs-fingers.html&quot;&gt;Building an API between Calculords and our code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite what your college might have taught you, there’s another layer beyond all the Big-O notation the ivory tower academics like to squawk on about: O(sandwich).  Specifically, if I run this code, do I have time to go make myself a sandwich before it finishes?  If so, it needs some optimization.  As fun as all of this was, there are two fatal flaws to our intermediate solution:&lt;/p&gt;

&lt;p&gt;Firstly, there weren’t enough buzzwords.  Anyone who’s made it to Junior level CS classes knows about garbage collection and dynamic programming.  We need some seriously hot terms on our resume in case scrawling “I work at Netflix” on a napkin doesn’t suffice at convincing future bosses of our awesome potential.  For this post, we’ll be delving into the second-hottest term out there: Neural Networks (I’d go with the hottest, T-E-N-S-O-R F-L-O-W, but that buzzword burns at just over 1,500°C and recruiters got tired of my resume melting holes in their desks).&lt;/p&gt;

&lt;p&gt;Secondly (and more importantly), our previous algorithm  still requires our fallible human fingers which are much better suited to eating that sandwich.  Each round, we need to type in all of the numbers that appear on the screen and then follow the precise instructions it spits back out.  One fat-finger and we’ve lost our 1.5x &lt;a href=&quot;http://calculords.wikia.com/wiki/Medals&quot;&gt;Perfectionist medal&lt;/a&gt;.  The horror!&lt;/p&gt;

&lt;h2 id=&quot;networking&quot;&gt;Networking&lt;/h2&gt;

&lt;p&gt;I had collected plenty of screen captures of a level in progress along with the data I’d inputted via the GUI from previous editions.  Despite my best efforts, there were some duplicates and plain ol’ bad data in the dataset.  Each level represented 6 datums for the cards and 9 for the integers, so I hoped this would be enough data to train my computer to play a video game for me.&lt;/p&gt;

&lt;p&gt;The simplest answer would be to take a screenshot and look at a few key pixels to tell if a section of a number was ‘on’ or ‘off’, much like a digital clock (remember those?).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/MLKcfLd.jpg?1&quot; alt=&quot;Picture of a generic digital clock&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We’ve gathered enough information to tell which pixels are significant just by looking at our sample data.  On the other hand “looking at pixels” doesn’t get to the front page of Hacker News and we’re &lt;em&gt;serious programmers&lt;/em&gt;.  Why do the sensible thing when we can ridiculously overcomplicate?&lt;/p&gt;

&lt;p&gt;At this point I need to take a quick break from the grandstanding and actually talk about what a neural network is.  There are two building blocks you need to know about: the neuron and the link.  If you’re at all familiar with graphs, this is a Weighted Directed Acyclic Graph (WDAG).  If you’re not familiar, a graph is a bunch of nodes connected by links.  ‘Directed’ means the connections only go one way, and ‘acyclic’ means that if you start at any given node and follow all the directed links, you’ll never get back to the node you started at (there are no cycles).  Weighted means that each connection has a different value.  Pictures help, so here’s one:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imgur.com/UkR40wn.png&quot; alt=&quot;Outline of a simple neural network&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Each circle is a node, the arrows connect the nodes, and each arrow has a value, or ‘weight’.  Circles and arrows are nice (at least in CS, they’re less swell when applied to &lt;a href=&quot;https://www.youtube.com/watch?v=m57gzA2JCcM&quot;&gt;8x10 color glossy pictures to be used as evidence against you&lt;/a&gt;) but where does the learning come in?  Imagine all of our lines are carrying a signal (with a strength somewhere between zero and one) to their destination neuron.  The neurons (our circles) have a tidy formula attached.  I won’t display any formulas here since I’m allergic to sigma functions (the ones with the big funky Σ) but I hope you’ll get the picture.  The neuron takes all of these signals, runs ‘em through our fancy formula and comes up with a number to output.  Sometimes you’ll hear mention of a ‘perceptron’, which works the same way as the neuron but only outputs zero or one.&lt;/p&gt;

&lt;p&gt;When we send in some training data (containing both a set of inputs as well as the expected output), the network runs through all of these calculations and comes up with &lt;em&gt;an&lt;/em&gt; answer (not necessarily the right one).  It then peeks at the right answer, and goes through a process called ‘backpropagation’.  Starting with the final column (the fancy data science types call this a ‘layer’) each neuron adjusts the weight of its inputs a smidge (even if the network got the right answer!).&lt;/p&gt;

&lt;p&gt;If the input value matched the correct answer (either high or low), the neuron gives the input a smidge more weight (and vice-versa for a non-match).  The precise amount of smidge is called the ‘learning rate’.  A big learning rate means faster learning but might overshoot the optimal balance.  A smaller rate will take longer to train but is more likely to find the ideal.  Picking a training rate is more of an art than a science (though “senior data artist” as a title won’t get you very far).&lt;/p&gt;

&lt;p&gt;The actual details are much more complicated, but c’mon, we’re software engineers, there’s a library for that.  Let’s dive into our examples:&lt;/p&gt;

&lt;p&gt;There’s two networks we need to build.  One is for the right-hand side of the play area, and only needs to recognize the digits from 0-10.  The images we will be working with are tiny and so we only need to architect a naive network.  The left-hand side involves double-digit numbers, so we need to be smarter about our network architecture if we don’t want to spend ages training.&lt;/p&gt;

&lt;h2 id=&quot;network-1-right-side&quot;&gt;Network #1 (right side)&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/X3x6PUN.png&quot; alt=&quot;Screen capture with right side of play area highlighted&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The construction of our naive network will be three parts, looking roughly something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/7T5vbE4.png&quot; alt=&quot;Diagram of the first network's layout&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;input-layer&quot;&gt;Input layer&lt;/h3&gt;

&lt;p&gt;Our input layer will include one neuron for each pixel in the input image (resulting be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;25 * 38 = 950&lt;/code&gt; neurons).  I’m lazy, so I ended up scaling down the image (from 50 x 75) to reduce the total size of this layer.  Training time is a function of how many neurons and connections there are (multiplied by how much training data you have).&lt;/p&gt;

&lt;p&gt;To further reduce the complexity of the input layer, I’ve converted the images to grayscale.  This means the network need only concern itself with how bright a pixel is instead of the colors.  In this particular problem, the background on the right could be red or blue - but that doesn’t change the number displayed.  Grayscale means our network doesn’t need to worry.&lt;/p&gt;

&lt;p&gt;Let’s review at the reductions made.  Remember, every data point means another neuron, and each input node will connect to every node in the middle layer.  Even small reductions mean big time savings.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/EuhHQGF.jpg&quot; alt=&quot;Comparison of before/after image downgrading&quot; /&gt;&lt;/p&gt;

&lt;table style=&quot;width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Image State&lt;/th&gt;
      &lt;th&gt;Data Points&lt;/th&gt;
      &lt;th&gt;Input Neurons&lt;/th&gt;
      &lt;th&gt;Connections&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;50x75 full color&lt;/td&gt;
      &lt;td&gt;50 x 75 x 4 (RGBA)&lt;/td&gt;
      &lt;td&gt;15,000&lt;/td&gt;
      &lt;td&gt;150,000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;25x38 full color&lt;/td&gt;
      &lt;td&gt;25 x 38 x 4&lt;/td&gt;
      &lt;td&gt;3,800&lt;/td&gt;
      &lt;td&gt;38,000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;25x38 grayscale&lt;/td&gt;
      &lt;td&gt;25 x 38 x 1&lt;/td&gt;
      &lt;td&gt;950&lt;/td&gt;
      &lt;td&gt;9,500&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;middle-layer&quot;&gt;Middle layer&lt;/h3&gt;

&lt;p&gt;This layer isn’t immediately exposed to our program, so we call it a ‘hidden layer’.  It’s this layer’s job to decide which of the perceptrons from the input layer are significant and reduce the weight given to the rest.&lt;/p&gt;

&lt;p&gt;I’ve put 100 neurons in this layer mostly because 100 is a nice round number and that seemed to work out.  Remember, this is a simple task so we don’t need to think too hard about what neurons go where.&lt;/p&gt;

&lt;p&gt;Like the input layer, every neuron in this layer connects to every neuron in the output layer.  This style of multilayered network where each neuron connects to all of the neurons in the next layer is called a ‘feed-forward’ network.&lt;/p&gt;

&lt;h3 id=&quot;output-layer&quot;&gt;Output layer&lt;/h3&gt;

&lt;p&gt;This layer is the one that’ll actually answer the question that’s been burning in our minds this whole time: is this a three?&lt;/p&gt;

&lt;p&gt;There are ten possible output values, so we have ten neurons in the output layer.  The strength of the signal these neurons emit is the percentage chance that particular neuron thinks the image represents that number.  This means that the summation of all of the signals differ greatly from the expected 100.  In fact, (much like children) two or more output nodes might decide that they very much have the right answer and it’s everyone else who’s wrong.&lt;/p&gt;

&lt;h3 id=&quot;getting-an-actual-answer&quot;&gt;Getting an actual answer&lt;/h3&gt;

&lt;p&gt;The simplest and most common way to resolve these disputes is to apply the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;softmax&lt;/code&gt; algorithm.  Softmax is an incredibly complicated system that works like so:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Take the largest number in the outputs.  Make it a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Make all the other numbers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…sorry, did I say incredibly complicated?  I must have meant the other thing.  Most networks used for classification tasks like this one use softmax at the end.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/SomeKittens/calculords-button-pusher/blob/master/screenChain/nn.js&quot;&gt;Here’s the code for this first neural network.&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;network-2-left-side&quot;&gt;Network #2 (Left side)&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/c1WL2i9.png&quot; alt=&quot;Screen capture highlighting left side of play area&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We have a lot more pixels to look at on the right-hand side coupled with a larger number of possible outputs.  A feed-forward network will have a LOT more nodes and connections than our previous task.  Given that training a network takes &lt;em&gt;ages&lt;/em&gt;, it’s in our best interest to architect the network to reduce the number of connections.  In this case, I split up the image into smaller overlapping sections and created a cluster of input neurons for each section:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/xKwzekM.png&quot; alt=&quot;Diagram showing image splitting&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This has the advantage of ‘compressing’ a section of the source image down to a few (in this case, three) nodes - much fewer connections and therefore faster training without much loss of granularity.  Each colored square in the above diagram represents a single input cluster here:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/bjskjWB.png&quot; alt=&quot;A diagram of the second network&quot; /&gt;&lt;/p&gt;

&lt;table style=&quot;width: 100%&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Network&lt;/th&gt;
      &lt;th&gt;Inputs&lt;/th&gt;
      &lt;th&gt;Neurons&lt;/th&gt;
      &lt;th&gt;Connections&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Feed-Forward&lt;/td&gt;
      &lt;td&gt;48 x 36&lt;/td&gt;
      &lt;td&gt;1,728 + 100 + 34 =  1,862&lt;/td&gt;
      &lt;td&gt;(1,728 * 100) + (100 * 34) = 176,200&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Input Clusters&lt;/td&gt;
      &lt;td&gt;192 x 25&lt;/td&gt;
      &lt;td&gt;4,800 + (3 * 25) + 34 = 4,909&lt;/td&gt;
      &lt;td&gt;(4,800 * 3) + (3 * 25 * 34) = 16,950&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;everything-else&quot;&gt;Everything else&lt;/h3&gt;

&lt;p&gt;Aside from this first-layer architectural change, this network works the same way as the first one.  There’s a middle hidden layer, an output layer, and softmax picks the best result out of the output neurons.&lt;/p&gt;

&lt;p&gt;You can find the code for this second network &lt;a href=&quot;https://github.com/SomeKittens/calculords-button-pusher/blob/master/screenChain/cardNN.js&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;back-to-calculords&quot;&gt;Back to Calculords&lt;/h2&gt;

&lt;p&gt;Phew, that was a lot of knowledge dumped in not-enough paragraphs.  Fortunately, we’re almost there!&lt;/p&gt;

&lt;p&gt;To recap, here’s the system:&lt;/p&gt;

&lt;p&gt;I push a button in some UI.  This triggers a screenshot of the device.  NodeJS chops up the screenshot and runs it through two neural networks to determine the current game state.&lt;/p&gt;

&lt;p&gt;Once the state is determined, it’s pushed through a Rust executable running a dynamic programming algorithm that will find the optimal solution for our current state.  Said solution will be automatically plugged back into the phone, deploying troops automatically.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/DYOSui3.gif&quot; alt=&quot;A computer plays Calculords for me&quot; /&gt;&lt;/p&gt;

&lt;p&gt;With this chain of tools, functions and hastily-typed blog post in place, I no longer have to suffer the indignity of &lt;em&gt;gasp&lt;/em&gt; playing a mobile game!  I’m free!&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Breaking: Calculords 2 development is well under way! Keep an eye here to see news, art, features, and timeframes. &lt;a href=&quot;https://t.co/NIOL5gjeUr&quot;&gt;pic.twitter.com/NIOL5gjeUr&lt;/a&gt;&lt;/p&gt;&amp;mdash; Calculords (@Calculords) &lt;a href=&quot;https://twitter.com/Calculords/status/683393228666605568&quot;&gt;January 2, 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;NOOOOOOOOOOO!!!!!!&lt;/p&gt;

&lt;p&gt;You can check out Calculords for yourself &lt;a href=&quot;http://www.calculords.com/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Sun, 21 Aug 2016 00:00:00 +0000</pubDate>
        <link>https://rkoutnik.com/2016/08/21/hacking-calculords-part-3-a-math-free-intro-to-neural-networks.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2016/08/21/hacking-calculords-part-3-a-math-free-intro-to-neural-networks.html</guid>
        
        
      </item>
    
      <item>
        <title>Advice on recruiting emails</title>
        <description>&lt;p&gt;Originally, I wasn’t going to respond but I’ve got a soft spot in my heart for startup founders.  If you don’t mind, here’s some unsolicited advice on recruiting:&lt;/p&gt;

&lt;p&gt;When I’m looking for a job, I have three big questions in mind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Will I have autonomy to do the best job I can?&lt;/li&gt;
  &lt;li&gt;Can I explore new areas instead of doing the same job over and over again?&lt;/li&gt;
  &lt;li&gt;Will the pay &amp;amp; total compensation be enough so I don’t feel cheated?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first question, autonomy, is the biggest.  Every startup claims that I’ll have “massive impact” etc, etc.  All of us know that’s table stakes.  My worry is that I’ll show up and be tasked with merely implementing someone else’s vision.  We know engineers don’t join startups to implement, they join to grow and be a part of the creation of something amazing.  You’d go a long way toward winning over potential recruits if you can convince them that they’ll be &lt;a href=&quot;https://rkoutnik.com/2016/04/21/implementers-solvers-and-finders.html&quot;&gt;Solvers &amp;amp; Finders, not Implementers&lt;/a&gt;.  Netflix knocks this out of the park - see the &lt;a href=&quot;http://www.slideshare.net/reed2001/culture-1798664/39-Seven_Aspects_of_our_Culture&quot;&gt;Freedom &amp;amp; Responsibility&lt;/a&gt; / &lt;a href=&quot;http://www.slideshare.net/reed2001/culture-1798664/78-Seven_Aspects_of_our_Culture&quot;&gt;Context, not Control&lt;/a&gt; sections of our culture deck.  I understand you’re absolutely strapped for time, so creating a giant culture deck probably isn’t the best use of a Thursday.  On the other hand, if recruiting top-quality talent is important, surely a sentence or two shouldn’t be a problem?&lt;/p&gt;

&lt;p&gt;Secondly, let me let you in on a little secret: I don’t enjoy pure UI engineering.  The last two jobs I’ve taken, I made sure that while I would mainly do UI (what I’m best at) I’d also have the opportunity to grow in other areas (stream processing, distributed systems, leadership).  I believe Mark referenced this by mentioning “your experience in developing user-focused, scalable solutions”.  More detail would be fantastic and help convince me to look further into your startup.&lt;/p&gt;

&lt;p&gt;Finally, compensation.  This is a tricky one to discuss as startups can’t compete with the big companies by definition.  Naive founders try to pitch equity as compensation but only naive engineers buy that (and yes, that was me once upon a time…).  I assume you don’t want to hire naive engineers.  You don’t need to be top-of-market (that would be foolish at your stage) but instead just convince me I won’t be ripped off and/or asked to work obscene hours.  This would be a good place to hammer home some of the perks from my first two points - there’s more to compensation than cash &amp;amp; options.&lt;/p&gt;

&lt;p&gt;One quick note: Terms like ‘market leader’, ‘disrupting’, etc are so overused as to have lost all meaning.  Overreliance on buzzwords is a big flag for “this person doesn’t know what’s actually special about them.”  You’re building something amazing - don’t obfuscate that with meaningless filler words.&lt;/p&gt;

&lt;p&gt;Good luck in your hunt!&lt;/p&gt;
</description>
        <pubDate>Mon, 15 Aug 2016 00:00:00 +0000</pubDate>
        <link>https://rkoutnik.com/2016/08/15/advice-on-recruiting-emails.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2016/08/15/advice-on-recruiting-emails.html</guid>
        
        
      </item>
    
      <item>
        <title>The git's guide to git: Commits &amp; their messages</title>
        <description>&lt;p&gt;The core unit of git is the commit. A commit is simple on the surface (some code changes and a message).  Such simplicity belies the complexity within.&lt;/p&gt;

&lt;h2 id=&quot;when-to-commit&quot;&gt;When to commit&lt;/h2&gt;

&lt;p&gt;I’ve heard many opinions on when one should commit from “commit early, commit often” to “one commit per release” (yikes).The only method I’ve found that consistently reduces developer headaches is to make one commit per change.This requires some discipline to break up small changes into their own commits and squashing multiple commits that all accomplish parts of the same change.  “Change” itself is subjective, my rule of thumb being “The smallest edit to the code that can be considered complete”. Half a refactor might be able to run &amp;amp; pass tests but it’s not ‘complete’.&lt;/p&gt;

&lt;p&gt;Making one commit per change supercharges tools like &lt;a href=&quot;/articles/The-gits-guide-to-git-Bisect.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git bisect&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://git-scm.com/docs/git-revert&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git revert&lt;/code&gt;&lt;/a&gt;. As tempting as it is to integrate several small changes in a single commit, you’ll be much happier with multiple commits if one of those changes need to be reverted later.&lt;/p&gt;

&lt;h2 id=&quot;commit-messages&quot;&gt;Commit messages&lt;/h2&gt;

&lt;p&gt;Technically speaking, commit messages aren’t that exciting.  There are two ways to write ‘em.  If you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit&lt;/code&gt;, git will helpfully open an editor to write the commit message. (Unhelpfully the editor is always Vim, git is credited with being the only reason developers know how to exit Vim [0]).  On the other hand, you can add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-m&lt;/code&gt; flag to add an inline commit message: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -m 'my commit'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, if you’re &lt;em&gt;not&lt;/em&gt; a mythical 10x programmer, you work on a team with other people. (if you are, &lt;a href=&quot;/2016/04/29/Wanted-Ninja-Rockstar-Code-Monkey-Hacker-Unicorn.html&quot;&gt;we could use a fellow like you&lt;/a&gt;). Even if you &lt;em&gt;are&lt;/em&gt; flying solo, you’re on a team comprised of now you, one-month-ago you, two-month-ago, etc. We all need some trail of breadcrumbs to follow whatever insane trail of logic February us was thinking.&lt;/p&gt;

&lt;p&gt;Which is why commit messages like this really tick me off:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;commit 32f4410abb2a901016c4a8b23c4b487e36be9916
Author: Randall Koutnik &amp;lt;souper_leet_h4x0r@rkoutnik.com&amp;gt;
Date:   Tue Jun 14 15:05:51 2016 -0700

    Fix error on alert page
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;What was this guy thinking?&lt;/em&gt; Seriously, what was he thinking?  I need to know the motivation for this commit - why, of all possible uses for his time, did this coder decide to make this one?&lt;/p&gt;

&lt;h3 id=&quot;context-is-king&quot;&gt;Context is king&lt;/h3&gt;

&lt;p&gt;When I was in college, I took Calc 2 and passed by a single point. I am not good with advanced math.  As I was cramming for the Calculus final, searching the textbook for any hint of explanation that would impart an understanding of antiderivatives, I came across the most terrifying sentence ever written:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The explanation for such a phenomenon is so trivial it is left as an exercise for the reader&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I hadn’t exercised in three days, so I went for a run.  This didn’t help my understanding of integration by parts at all.  The author of the textbook is well-read in calculus, as he literally wrote the book on it. He had a much greater context for calculus than I did and assumed I’d be able to pick up the finer points.&lt;/p&gt;

&lt;p&gt;The author of the commit message above knows what bug was fixed.  Their issue is in assuming the reader has the same context.&lt;/p&gt;

&lt;h3 id=&quot;the-three-questions&quot;&gt;The three questions&lt;/h3&gt;

&lt;p&gt;Commit messages need to answer three questions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What changed?&lt;/li&gt;
  &lt;li&gt;How was the change implemented?&lt;/li&gt;
  &lt;li&gt;Why was that change nessecary?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The commit above only answers “what” (and poorly at that). We’re still left wondering &lt;em&gt;which error?&lt;/em&gt;  Any code that’s existed for 90 seconds has multiple errors.  If I know that a fix when cloning alerts that had an ampersand in the name introduced a regression and am combing through the history trying to find said commit, this message is near-useless.&lt;/p&gt;

&lt;p&gt;This message also doesn’t provide a high level “how” of the fix. Was the answer better parsing?  A less-restrictive regex?  Skipping all the relevant unit tests? Answering “how” in the commit message saves the reader the effort of reading through the diff.&lt;/p&gt;

&lt;p&gt;Finally, and most importantly, &lt;em&gt;why&lt;/em&gt;?  Fixing errors is important, sure.  Why this error?  Most modern git systems allow linking to an issue tracker; apply links liberally.  Some, like GitHub, allow you to close an issue with a commit message containing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fixes #1234&lt;/code&gt;.  Two birds with one stone!&lt;/p&gt;

&lt;h3 id=&quot;a-better-commit&quot;&gt;A better commit&lt;/h3&gt;

&lt;p&gt;Let’s take a swing at fixing up the commit above.  Using our new heuristics for message quality, we need to add:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Why&lt;/em&gt; the commit happened (through some external links)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;How&lt;/em&gt; the change works&lt;/li&gt;
  &lt;li&gt;More details in the summary&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;commit 32f4410abb2a901016c4a8b23c4b487e36be9916
Author: Randall Koutnik &amp;lt;souper_leet_h4x0r@rkoutnik.com&amp;gt;
Date:   Tue Jun 14 15:05:51 2016 -0700

    Fix name parse bug when cloning alert with a '&amp;amp;' in the name

    Previously, the API would choke because we weren't escaping '&amp;amp;' in alert names on cloning.
    Now the clone service escapes the name before the API call.

    Fixes #1337
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We now have a neat little summary, an explanation of the actual fix and a connection to external details.  Now if (horrifyingly) some part of the system relied on unescaped data, we’d know exactly what commit to start with when the regression tickets come piling in…&lt;/p&gt;

&lt;p&gt;[0] Seriously, you can set the editor git uses either through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global core.editor &quot;your-editor-here&quot;&lt;/code&gt; or the environment variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GIT_EDITOR&lt;/code&gt;.&lt;/p&gt;
</description>
        <pubDate>Sat, 16 Jul 2016 00:00:00 +0000</pubDate>
        <link>https://rkoutnik.com/2016/07/16/git-s-guide-to-git-commit-messages.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2016/07/16/git-s-guide-to-git-commit-messages.html</guid>
        
        
      </item>
    
      <item>
        <title>Hacking Calculords part 2: Who needs fingers?</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://rkoutnik.com/2016/04/06/Hacking-Calculords.html&quot;&gt;When we last left off&lt;/a&gt;, we had a handy-dandy algorithm that used dynamic programming to find the optimal solution to a Calculords level in a sane amount of time.&lt;/p&gt;

&lt;p&gt;The biggest downside was that I still needed to manually transfer a bunch of numbers from the screen to the algorithm, and then painstakingly tap the results back into the phone, one by one.  Since there was a puny meatbag involved, there were a lot of errors and I couldn’t live without the 1.5x “Perfect!” bonus.&lt;/p&gt;

&lt;p&gt;Two paths lay before me, each glittering with possibility:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Write an interface to programmatically punch solutions into my phone&lt;/li&gt;
  &lt;li&gt;Do something useful with my life&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The answer was crystal clear.  What follows is the second entry in the journal of my journey to math and madness.&lt;/p&gt;

&lt;h2 id=&quot;adb&quot;&gt;adb&lt;/h2&gt;

&lt;p&gt;After an hour of talking at my computer, I concluded that there was no native voice-activated Android control system on OSX.  Dismayed, I turned to the next best thing: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb&lt;/code&gt; tool.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb&lt;/code&gt; lets a hacker interact with an Android device &lt;em&gt;without touching it at all&lt;/em&gt;.  I’m sure iOS devs are applauding right now at the thought of never needing to touch another dirty droid again.&lt;/p&gt;

&lt;p&gt;There are three things we need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb&lt;/code&gt; to do for us:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Take screenshots&lt;/li&gt;
  &lt;li&gt;Figure out the x/y coordinates of taps&lt;/li&gt;
  &lt;li&gt;Send taps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On macOS, install adb via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew install android-platform-tools&lt;/code&gt;; you’re on your own on other platforms, sorry.  This is less a tutorial and more preemptive documentation in case I ever need to plead insanity.  Once you’ve installed adb, enabled developer mode on your phone, and plugged everything in, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb devices&lt;/code&gt; to make sure it’s all hooked up:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ adb devices
List of devices attached
0123dd02f0babcde  device
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(don’t worry, that’s not my real serial number)&lt;/p&gt;

&lt;h3 id=&quot;screenshots&quot;&gt;Screenshots&lt;/h3&gt;

&lt;p&gt;Why, you may ask, do we need to take a screenshot of a device that’s &lt;em&gt;right in front of us?!?&lt;/em&gt;  Dear reader, you underestimate my ability to screw things up.  During manual input, I need to rapidly glance back and forth between phone and computer.  There is an abundance of things in between, such as a keyboard, pizza, and occasionally my cat.  Any one of these things could momentarily distract me—flipping bits in my brain—and I’d enter the wrong number, causing &lt;em&gt;minutes&lt;/em&gt; of lost ‘productivity’.  The obvious answer is to double-check my work but then we’d run into the infamous &lt;a href=&quot;https://en.wikipedia.org/wiki/Two_Generals%27_Problem&quot;&gt;Two Generals Problem&lt;/a&gt;, where two generals were having a nice lunch but the waiter got lost &amp;amp; the kitchen never received their order, so they decided to give up the whole war thing and become distributed systems experts.&lt;/p&gt;

&lt;p&gt;In any case, a screenshot allows us to show the phone’s screen as close to the inputs as possible, greatly reducing errors and neck strain:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/whXTNkH.png&quot; alt=&quot;Picture of the new UI&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We’re using  &lt;a href=&quot;https://www.npmjs.com/package/adbkit&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adbkit&lt;/code&gt;&lt;/a&gt; here to pull off the incredible feat of taking a screenshot:&lt;/p&gt;

&lt;div class=&quot;language-javascript 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;takeScreenshot&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;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;uuid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fileStream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createWriteStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`./public/screens/&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;s2&quot;&gt;.png`&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;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;screencap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SERIAL&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;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;screencap&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;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bluebird&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&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;c1&quot;&gt;// Create a new promise that resolves when we've finished writing to file&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Otherwise we get half-written nightmares&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;screencap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fileStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;screencap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;dl&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;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;resolve&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;p&quot;&gt;});&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hurrah!  Now we can procrastinate slightly faster and with fewer mistakes than ever before!&lt;/p&gt;

&lt;h3 id=&quot;input&quot;&gt;Input!&lt;/h3&gt;

&lt;p&gt;Now, we don’t need to look at the phone &lt;em&gt;before&lt;/em&gt; the algorithm runs.  In order to keep our necks un-sprained during the back nine, we need to coax &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb&lt;/code&gt; into sending input into the device for us.  Thankfully, 2/3ds of this is simple:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb shell input tap x y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We want to execute a shell command that sends a tap event to a set of coordinates.  Finding the right coordinates turned out to be a backbreaking journey.&lt;/p&gt;

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

&lt;p&gt;On the surface, things are simple.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb&lt;/code&gt; provides a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getevent&lt;/code&gt; function that echoes out all the details of events on the device, including the x/y coordinates of the event.  But this is software, so we should be suspicious of anything simple!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ adb shell getevent -l
add device 1: /dev/input/event5
  name:     &quot;msm8974-taiko-mtp-snd-card Headset Jack&quot;
add device 2: /dev/input/event4
  name:     &quot;msm8974-taiko-mtp-snd-card Button Jack&quot;
add device 3: /dev/input/event3
  name:     &quot;hs_detect&quot;
add device 4: /dev/input/event1
  name:     &quot;touch_dev&quot;
add device 5: /dev/input/event0
  name:     &quot;qpnp_pon&quot;
add device 6: /dev/input/event2
  name:     &quot;gpio-keys&quot;
/dev/input/event1: EV_ABS       ABS_MT_TRACKING_ID   00000056
/dev/input/event1: EV_ABS       ABS_MT_POSITION_X    000001af
/dev/input/event1: EV_ABS       ABS_MT_POSITION_Y    000003a0
/dev/input/event1: EV_ABS       ABS_MT_PRESSURE      00000035
/dev/input/event1: EV_ABS       ABS_MT_TOUCH_MAJOR   00000006
/dev/input/event1: EV_SYN       SYN_REPORT           00000000
/dev/input/event1: EV_ABS       ABS_MT_TRACKING_ID   ffffffff
/dev/input/event1: EV_SYN       SYN_REPORT           00000000
/dev/input/event1: EV_ABS       ABS_MT_TRACKING_ID   00000057
/dev/input/event1: EV_ABS       ABS_MT_POSITION_X    0000018d
/dev/input/event1: EV_ABS       ABS_MT_POSITION_Y    0000046d
/dev/input/event1: EV_ABS       ABS_MT_PRESSURE      00000036
/dev/input/event1: EV_SYN       SYN_REPORT           00000000
/dev/input/event1: EV_ABS       ABS_MT_TRACKING_ID   ffffffff
/dev/input/event1: EV_SYN       SYN_REPORT           00000000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Annoyingly the coordinates are in hex, though that’s trivial to convert.  However, these are the &lt;em&gt;wrong&lt;/em&gt; coordinates.  Converting them to decimal and sending a tap will trigger a tap in a entirely different location!  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb&lt;/code&gt; must be a politician or a UI developer as its position is relative.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getevent&lt;/code&gt; assumes that the device is &lt;em&gt;always&lt;/em&gt; in portrait mode and assigns 0/0 appropriately:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/D5YB393.png&quot; alt=&quot;x/y of getevent&quot; /&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input tap&lt;/code&gt; works with the current position (in this case, landscape):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/WQSWbIF.png&quot; alt=&quot;x/y of input tap&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This difference is not documented anywhere that I could find (you read it here first, folks!).  Once the tapping was set up, we can automagically enter in the best solution (‘best’ as in ‘deploys the most cards’, with no regard for order or overall strategy).&lt;/p&gt;

&lt;h3 id=&quot;strategy&quot;&gt;Strategy&lt;/h3&gt;

&lt;p&gt;Our AI places all of its units in the top lane.  As it turns out, Calculords isn’t calibrated to deal with someone deploying ALL of their troops every time.  Ninja Crime made the fatal mistake of assuming their fans weren’t &lt;em&gt;that&lt;/em&gt; dementedly obsessed with Calculords.  Our overwhelming firepower absolves the need for strategy.  We’ll deploy ~6 troops every turn (some power-up cards are in the deck, other cards deploy multiple units).  Every unit deployed moves the column ahead one square.  The standard pace is 4 squares/turn, so putting everyone in one lane speeds up our victory by 2.5x.&lt;/p&gt;

&lt;p&gt;Later enemies have abilities that can restrict what lane you place troops into.  I solved this by crying a lot and dropping down to manual control.  A more clever solution is left as an excercise for the reader.&lt;/p&gt;

&lt;h3 id=&quot;disaster-strikes&quot;&gt;Disaster strikes&lt;/h3&gt;

&lt;p&gt;With neck intact and all of my x’s dotted and y’s crossed, I thought I was in the clear.  Then a terrible, awful thing happened: I leveled up.&lt;/p&gt;

&lt;p&gt;Remember just how mind-boggling huge the number of calculations we were doing was with only eight integers?  Turns out there’s some ominous foreshadowing in the corner:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/pQNB2Vn.png&quot; alt=&quot;PICTURE SHOWING EIGHT INTEGERS WITH NINTH BLANK SPOT HIGHLIGHTED&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After a string of major victories on the field of battle, I was awarded a ninth and final integer to bring with me into the trenches.  This drove the running time of the solver algorithm from an upper bound of 90 seconds to an average time of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Out of Memory&lt;/code&gt;.  V8-driven JS isn’t very memory-efficient.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;🎵 Hello darkness my old friend&lt;br /&gt;I’ve come to crash with you again&lt;br /&gt;with the garbage softly creeping&lt;br /&gt;across the stack that I was sweeping🎵&lt;/p&gt;&amp;mdash; Randall Koutnik (@rkoutnik) &lt;a href=&quot;https://twitter.com/rkoutnik/status/739160837034627072&quot;&gt;June 4, 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/bsTNb71.png&quot; alt=&quot;Picture of JS memory crash&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I had been looking for an excuse to try Rust out (Slogan: “We’re on HN often, so we must be good!”).  Rust is the complete opposite of JavaScript - it’s incredibly strict about who has access to what value when.  It’s a systems level language, which means it doesn’t compile.  A lesser-known secret of the Rust community is that the compiler just picks a random compile-time error and throws it.  No one has ever successfully compiled Rust code.&lt;/p&gt;

&lt;p&gt;There have been plenty of articles discussing Rust, so I’ll just stick to one particular problem I encountered.  In the previous episode, we used dynamic programming (a single var containing all of the paths we’ve been to) in order to cut down on the overall number of calculations.  This was accomplished in JavaScript by having a variable in the parent function’s scope keep track, while a child function recursed:&lt;/p&gt;

&lt;div class=&quot;language-javascript 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;parent&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;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;placesWeHaveBeen&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;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// check placesWeHaveBeen&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;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 let us build out our wide tree of recursion while still keeping the number of calculations relatively low.  Rust, on the other hand was stubborn.  Rust allows nested functions, but the coder must make a choice between accessing variables in the parent scope (via a closure) XOR recursing.&lt;/p&gt;

&lt;p&gt;I’m sure &lt;a href=&quot;https://news.ycombinator.com/user?id=steveklabnik&quot;&gt;steveklabnik&lt;/a&gt; will appear in the HN comments with some wizardy trick to fix this but it was quite a problem for mortal me.  I ended up creating a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CalcEnv&lt;/code&gt; struct and passing that along to my recursing function (hurrah pointing):&lt;/p&gt;

&lt;div class=&quot;language-rust 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;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CalcEnv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cards&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&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;n&quot;&gt;solutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&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;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HashSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-rust 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;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;explore&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&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;n&quot;&gt;ints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CalcEnv&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;c&quot;&gt;// Various code-type things&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;explore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_ints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&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 allowed me to have a global dictionary of visited paths, albeit a slightly strange one.  This may be standard practice in the general Rust community– I’m just a newcomer.  One advantage of Rust is that converting this code to use multiple threads was fairly simple (though I still needed a global mutex, which meant that multithreading didn’t help much).&lt;/p&gt;

&lt;p&gt;Enough whining; here are the numbers (run on a MBP, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;time&lt;/code&gt; command).  Sometimes I lucked out and JS didn’t choke on a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n=9&lt;/code&gt; solution:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;&lt;/th&gt;
      &lt;th&gt;JS&lt;/th&gt;
      &lt;th&gt;Rust&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;10.537s&lt;/td&gt;
      &lt;td&gt;5.883s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;3m 13s&lt;/td&gt;
      &lt;td&gt;1m 32.30s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Phew - not only are we &lt;em&gt;not&lt;/em&gt; dying on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n=9&lt;/code&gt; but it’s running ~2x faster!  Memory consumption also drops by a massive amount, with Rust using about 12MB where JS chewed up over a gigabyte.&lt;/p&gt;

&lt;h3 id=&quot;now-what&quot;&gt;Now what?&lt;/h3&gt;

&lt;p&gt;When we started, we had a neat algorithm.  Now there’s a solid UI around it, programmatic interfacing with the device, and significant speed boosts from a lower-level language.&lt;/p&gt;

&lt;p&gt;On the other hand, I still have to type in the numbers.&lt;/p&gt;

&lt;p&gt;Next up is the thrilling conclusion wherein we’ll build a neural network to recognize digits to save us from all that tedious typing.&lt;/p&gt;

&lt;p&gt;I wish I were kidding….&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://rkoutnik.com/2016/08/21/hacking-calculords-part-3-a-math-free-intro-to-neural-networks.html&quot;&gt;Read Part 3 here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check out Calculords for yourself &lt;a href=&quot;http://www.calculords.com/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 14 Jun 2016 00:00:00 +0000</pubDate>
        <link>https://rkoutnik.com/2016/06/14/hacking-calculords-2-who-needs-fingers.html</link>
        <guid isPermaLink="true">https://rkoutnik.com/2016/06/14/hacking-calculords-2-who-needs-fingers.html</guid>
        
        
      </item>
    
  </channel>
</rss>
