<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Vladimir Klepov as a Coder</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://thoughtspile.github.io/"/>
  <updated>2018-09-23T11:37:20.000Z</updated>
  <id>https://thoughtspile.github.io/</id>
  
  <author>
    <name>Vladimir Klepov</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Another Week with Bad Software</title>
    <link href="https://thoughtspile.github.io/2018/09/23/bad-software-week/"/>
    <id>https://thoughtspile.github.io/2018/09/23/bad-software-week/</id>
    <published>2018-09-23T11:35:02.000Z</published>
    <updated>2018-09-23T11:37:20.000Z</updated>
    
    <content type="html"><![CDATA[<p>In the midst of my September job hop I headed to Kazan for the weekend. I don’t know exactly why — probably because I could. I had a hotel booked via booking.com, but once I arrived there the receptionist told me it was the first time he’s heard of my booking, and he told me that they had no more rooms, and he told me that I’d rather find another place to stay.</p><p>But why, I always see these things for what they are. Some sneaky caffeinated programmer kids at work with the booking system integrations, you should always double-check after us! After what came next, I started suspecting there’s some particularly defective developer marketing himself as a <em>“Chief Hotel Booking Management System (HBMS) Professional with 10+ years experience in the field”</em>.</p><p><img src="/images/kazan-bridge.jpg" alt=""></p><p>I booked the next hotel for the two nights, with a discount, and walked there. Guess what? The room I booked was occupied, but they had another one, but not for two night, just one. In the end it worked out all right because there was that woman using the responsive, fully interactive, enterprise-ready ERP system “sheet of paper and a pencil” that allows you to reschedule bookings at will, with no programmers involved.</p><p>The rest of my trip went well, probably because I had little interaction with software stuff. The pizza place charged me twice, because they thought the first payment didn’t pass, but they gave the money back. Human problem, wasn’t it? (Of course not completely, some usability failure out there, but let’s leave it for what it is, shall we?)</p><h2 id="The-Return"><a href="#The-Return" class="headerlink" title="The Return"></a>The Return</h2><p>I was riding the train from the airport, almost eager to get back to work writing things that mostly function. I was a bit worried they didn’t give me a call — was I supposed to just come to the office and figure out what to do next? Anyways, I made some calls and found out that the information about me starting my work got lost somewhere along the course of a month it’s been running around the infrastructure.</p><p>This got me a little worried: I haven’t spent a week in Moscow without work in over three years, and, besides, I was running low on money. I wasn’t angry with anyone in particular: who should I blame for the state of the industry? I’m just as guilty as anyone for letting it fall that low. it turned out not to be taht bad after all: the weather was good, and I got a chance to walk the empty city — everyone here in Moscow is too busy working hard to be out of office in the middle of the day.</p><p>My accidental vacation started along the fanfare of Nikita Prokopov’s <a href="http://tonsky.me/blog/disenchantment/" target="_blank" rel="noopener">software disenchantment</a>. It’s depressing but, and even more depressive for being true. Let me pick a quote for you:</p><blockquote><p>We cover shit with blankets just not to deal with it.</p></blockquote><p>I’ve been subscribed to this blog for several years, and never knew the man was Russian. I should have guessed — where else can a man that depressed and dissatisfied with the state-of-the-world come from? The part that caught my atteniton was the Russian apps on the screenshots. From there I got onto Nikita’s <a href="https://tonsky.livejournal.com/" target="_blank" rel="noopener">russian-language blog</a>.</p><h2 id="Why-must-it-be-like-this"><a href="#Why-must-it-be-like-this" class="headerlink" title="Why must it be like this?"></a>Why must it be like this?</h2><p>It’s a good the blog is in Russian — serves well to save the good people of the world from moscow-grade sadness. Somewhere in the comments on the fourth page I found a neat explanation for why the things in software are the way they are. I can’t find the particular comment any more, but I remember the gist and even spent some time elaborating on it.</p><p>Once a problem is solved by software at a minimum viable level, you don’t need programmers (we are crazy expensive) to actually make it work. The solution gets canned and distributed in a bundle that usually works, as long as you’re not getting too tricky:</p><ul><li>Edit a table of numbers? Excel!</li><li>Write a text? Word!</li><li>Send some data to another person? E-mail!</li><li>Make a website? Wordpress!</li><li>Edit an image? Photoshop!</li></ul><p>The programmers are there to stick them into the holes of the abstraction. If you’re generating excel tables programatically from a database, or want your website to synchronize with a price list from a Googledoc, you need some programmers to duct-tape the systems together in unexpected ways (I’m working hard to stay away from shit-based metaphors, but feel free to make one yourself). These systems have a long train of backwards compatibility, they are a massive overkill for the job, but hey, they work just well enough.</p><p>I’m enraged by the lack of attention to static website generators. The idea is beautiful: pipe some markdowns through a template, get a set of static HTMLs and resources that can be host anywhere for, like, free! Why do people make their websites in Wordpress — have a MySQL database at work pushing the limits of storing static data, and PHP, rendering the pages at every request. Oh dear, the system was supposed to write blogs — how did they ever manage to bend it into e-commerce, landing pages and ERP front-ends?</p><p>No, I do know the answer to that — just hit a freelance farm to find a bunch of schoolchildren who can make you something that looks like a website in a week, for $50. I wouldn’t consider disrupting a business with that low profit margin — and who would?</p><h2 id="And-also"><a href="#And-also" class="headerlink" title="And also"></a>And also</h2><p>On Thursday I was watching my TV when the electricity died. It spent the evening randomly switching it on and off, then got stuck loading forever. The philips tech support was very sympathetic. “There’s some very high tech in there — a whole embedded system! How in the world did you expect it to survive the electricity shutdown?” they said. And yeah, sure, what did I expect from a system that had a piece of software in it?</p><figure><br>  <iframe style="margin: 0 auto; display: block" width="560" height="315" src="https://www.youtube.com/embed/-eREiQhBDIk?rel=0&amp;start=230" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><br>  <div style="text-align: center; color: #666">Here’s what I (and Nikita, and even Uncle Bob lately) think of software</div><br></figure><p>Really, I should assume I write code at least marginally better-than-average and get into programming education. There’s a horrible shortage of material on learning actual programming (not “How to Use Technology X to Solve Problem Y”-style things) out there. I must to fight as well as I possibly can. You must, too (yes, you, the guy who actually read this all).</p><hr><p>You’ve just seen a weekly snapshot of my thoughts pile. While taking another look at this website’s design to see if the the navigation is obscure enough to prevent the users from noticing the other posts (it probably is; I don’t think i’m changing it just yet) I noticed something horrible.</p><p>The blog’s address has <em>thoughts pile</em> in it. How is that name appropriate for the smart, boring and technical stuff I’ve come to post? I need to give the place some wildness it deserves. <em>Klyukovka, ay, igray Balalaechka!</em> Writing messy speculative posts is far more entertaining!</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;In the midst of my September job hop I headed to Kazan for the weekend. I don’t know exactly why — probably because I could. I had a hote
      
    
    </summary>
    
    
      <category term="programming" scheme="https://thoughtspile.github.io/tags/programming/"/>
    
      <category term="life" scheme="https://thoughtspile.github.io/tags/life/"/>
    
      <category term="thoughtspile" scheme="https://thoughtspile.github.io/tags/thoughtspile/"/>
    
      <category term="depression" scheme="https://thoughtspile.github.io/tags/depression/"/>
    
  </entry>
  
  <entry>
    <title>Not Sucking at TypeScript: 3 Tips</title>
    <link href="https://thoughtspile.github.io/2018/09/22/typescript-unsuck-guide/"/>
    <id>https://thoughtspile.github.io/2018/09/22/typescript-unsuck-guide/</id>
    <published>2018-09-22T13:37:41.000Z</published>
    <updated>2018-09-22T13:57:43.000Z</updated>
    
    <content type="html"><![CDATA[<p>I have spent three years developing in TypeScript, but sometimes it is owerwhelming. I’m sitting there with all those little “fuck-fuck-fucks” in my head, thinking of how I’d great it would be to burn the annotations, change the extensions to <code>.js</code> and get out of this nighmare already. But hey, if used properly, TS makes you happy, not depressed! Here are my top 3 tips to ease the pain.</p><h2 id="Let-TS-do-its-type-inference"><a href="#Let-TS-do-its-type-inference" class="headerlink" title="Let TS do its type inference"></a>Let TS do its type inference</h2><p>Here’s a sample typescript fragment from one of my projects:</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">maxNumber</span>(<span class="params">arr: <span class="built_in">number</span>[]</span>): <span class="title">number</span> </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> max: <span class="built_in">number</span> = -<span class="literal">Infinity</span>;</span><br><span class="line">  arr.forEach(<span class="function">(<span class="params">x: <span class="built_in">number</span></span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (x &gt; max) &#123;</span><br><span class="line">      max = x;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>But TS compiler is really good at deducing types, so you don’t to be that explicit! TS deduces types from:</p><ul><li>initial values: <code>const x = 10</code> is enough, no need for <code>const x: number = 10;</code>. This also works on default values, as in <code>(x = false) =&gt; !x</code>;</li><li>array method types (any generic specifications, really): if <code>arr</code> is <code>number[]</code>, than x in  <code>arr.forEach(x =&gt; ...)</code> is obviously a <code>number</code>;</li><li>return values: in our example, TS knows pretty well that <code>max</code> is a <code>number</code>, so the function returns a <code>number</code>.</li></ul><p>So, our examle only needs one type annotation:</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">maxNumber</span>(<span class="params">arr: <span class="built_in">number</span>[]</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> max = -<span class="literal">Infinity</span>;</span><br><span class="line">  arr.forEach(<span class="function">(<span class="params">x</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (x &gt; max) &#123;</span><br><span class="line">      max = x;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>As a bonus, once we the annotations do not duplicate, we can easily change types without having to fix half a file. In our example, we changing <code>arr</code> to <code>string[]</code> immediately shows that we must also change the initial value of <code>max</code> to a string, <code>&#39;&#39;</code>.</p><p>As a rule of thumb, we only need explicit type annotations for:</p><ul><li>Function parameters: <code>(x: number, y: number) =&gt; x + y;</code>. As we’ve seen, default values will also do: <code>(x = 0, y = 0) =&gt; x + y;</code>.</li><li>Empty containers: <code>private users: IUser[] = [];</code>. TS does not see an item, and can’t know its type.</li><li>Values coming from outside the codebase. This one’s trickier, but think af an API call: <code>get&lt;IUser[]&gt;(&#39;/users&#39;)</code>.</li><li>(Yes, there are other cases, you’ll know it when you see one, don’t get mad at me).</li></ul><p><img src="/images/ts-just-enough.png" alt=""></p><p>Generally, annotate as few types as you can, then check the IDE hints to see if TS got it right. If not, help him.</p><h2 id="Sometimes-just-let-types-go"><a href="#Sometimes-just-let-types-go" class="headerlink" title="Sometimes, just let types go"></a>Sometimes, just let types go</h2><p>I’m absolutely guilty of this one: I’ve spent a day once typing a tricky low-level canvas util. Always remember that TS is supposed to help you, not stand in your way.</p><p>If you find yourself describing an especialy tricky type — a generic generic, or a polymorphic variadic function — stop and think if you really need it. Maybe the logic is just too obscure, and the fancy typings are just a symptom. Maybe you only use that function in one place, and it already works, so what’s the use?</p><p>With TS, you always have an easy way out — there’s no shame in dropping an <code>any</code> if it saves you a day! An explicit <code>any</code> is better than implicit beacuse if you’re feeling static on a Friday afternoon, you can grep your codebase for <code>/: any/</code> and see if you can fix a couple.</p><h2 id="Prevent-compilation-error-buildup-with-global-overrides"><a href="#Prevent-compilation-error-buildup-with-global-overrides" class="headerlink" title="Prevent compilation error buildup with global overrides"></a>Prevent compilation error buildup with global overrides</h2><p><img src="/images/ts-errors.png" alt=""></p><p>Accidentally you slip and ignore a TS error. The code still compiles, no harm done! But once your compilation log is several 10+ of bloody redness, it’s lost as a source of information about global project correctness. The generic advice is “look if it’s a real error, then either fix or re-type it”, but yes, I do have something specific in mind. Global type overrides are your friends!</p><p>Sure your browser targets support <code>&lt;Array&gt;.find</code>, or have a polyfill ready? Override the global <code>Array</code> type (courtesy of <a href="https://stackoverflow.com/questions/31455805/find-object-in-array-using-typescript" target="_blank" rel="noopener">user75525 at SO</a>)!<br><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> Array&lt;T&gt; &#123;</span><br><span class="line">  find(predicate: <span class="function">(<span class="params">search: T</span>) =&gt;</span> <span class="built_in">boolean</span>): T;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>Working on a legacy project with lodash loaded globally via a CDN? Throw it in:<br><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> lodash <span class="keyword">from</span> <span class="string">'lodash'</span>;</span><br><span class="line"><span class="keyword">declare</span> global &#123;</span><br><span class="line">  <span class="keyword">const</span> _: <span class="keyword">typeof</span> lodash;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>Using an obscure jQuery plugin? Global type overrides got you covered:<br><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">interface</span> JQuery &#123;</span><br><span class="line">  webuiPopover: <span class="function">(<span class="params">o: <span class="built_in">any</span></span>) =&gt;</span> JQuery;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><h2 id="Love-the-types-you’re-with"><a href="#Love-the-types-you’re-with" class="headerlink" title="Love the types you’re with"></a>Love the types you’re with</h2><p>Hope this tips will help you be less depressed and more productive when working with TypeScript.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I have spent three years developing in TypeScript, but sometimes it is owerwhelming. I’m sitting there with all those little “fuck-fuck-f
      
    
    </summary>
    
    
      <category term="javascript" scheme="https://thoughtspile.github.io/tags/javascript/"/>
    
      <category term="programming" scheme="https://thoughtspile.github.io/tags/programming/"/>
    
      <category term="typescript" scheme="https://thoughtspile.github.io/tags/typescript/"/>
    
  </entry>
  
  <entry>
    <title>Simpifying AngularJS controllers with ES5 get / set</title>
    <link href="https://thoughtspile.github.io/2018/09/20/angularjs-service-property-getter/"/>
    <id>https://thoughtspile.github.io/2018/09/20/angularjs-service-property-getter/</id>
    <published>2018-09-20T14:04:06.000Z</published>
    <updated>2018-09-20T18:04:08.000Z</updated>
    
    <content type="html"><![CDATA[<p>I’ve been developing an AngularJS application for the past year — and <em>voila!</em> here I am, alive and well. I’m not some crazy old fuck who thinks AngularJS is a promising new technology. Nor have I been waiting to publish this post for 3 years. It’s just how things turned up for me. Since there’s no shortage of AngularJS apps in the wild, I’ve decided to share some tips for taming Angular (the Terrible one) and staying sane (yes you can).</p><figure><br>  <img src="/images/angularjs-is-bad.jpeg"><br>  <div style="color: #666; text-align: center;">Oh AngularJS, what a reputation you’ve earned yourself</div><br></figure><h2 id="The-context-—-where-am-I-Help"><a href="#The-context-—-where-am-I-Help" class="headerlink" title="The context — where am I? (Help)"></a>The context — where am I? (Help)</h2><p>Some context first. I spent two years developing React front-ends. When offered a job on an AngularJS app, I was scared at first — we’ve all spent years making fun of it. The team lead was shaking a full Vue rewrite around not to scare the candidates off. The idea of playing around with Vue felt good (I’m a playful coder, don’t judge me), but Joel Spolsky’s <a href="https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/" target="_blank" rel="noopener">spooky story</a> of Netscape’s full rewrite had been growing on me for years. And well, there were <em>features</em> to be made, no time for the geek fun.</p><p>Now I’m gone from the project (no relation to the tech stack whatsoever), and the app is still moslty AngularJS. It’s in a good shape, and has all the modern things: webpack, babel, a sprinkle of React here and there. I feel I’ve made a good job by focusing on the business stuff.</p><h2 id="The-Problem-—-what’s-wrong"><a href="#The-Problem-—-what’s-wrong" class="headerlink" title="The Problem — what’s wrong?"></a>The Problem — what’s wrong?</h2><p>So, what was it I was gonna tell you kids about? We have a service that holds the list of users. Here it is, with all the ES6 exquisiteness:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserService</span> </span>&#123;</span><br><span class="line">  load() &#123;</span><br><span class="line">    <span class="keyword">return</span> get(<span class="string">'/users'</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Now, the component. All basic, too, just shows a list of users:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserListController</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(userService) &#123;</span><br><span class="line">    <span class="keyword">this</span>.userService = userService;</span><br><span class="line">    <span class="keyword">this</span>.userService.load().then(<span class="function"><span class="params">users</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="keyword">this</span>.users = users;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">angular.component(<span class="string">'userList'</span>, &#123;</span><br><span class="line">  template: <span class="string">`&lt;user-card ng-repeat="user in $ctrl.users" user="user"&gt;&lt;/user-card&gt;`</span>,</span><br><span class="line">  controller: UserListController</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>But we can also add a user. Once the thing is done, we should update the list — it’s surely changed. But — oh no! — we have no way of doing it, because the data is stuck in <code>UserListController</code>.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserService</span> </span>&#123;</span><br><span class="line">  load() &#123;</span><br><span class="line">    <span class="keyword">return</span> get(<span class="string">'/users'</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  addUser(user) &#123;</span><br><span class="line">    <span class="keyword">return</span> post(<span class="string">'./users'</span>, user).then(<span class="comment">/* oops */</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="The-classic-solution"><a href="#The-classic-solution" class="headerlink" title="The classic solution"></a>The classic solution</h2><p>The classic, ES3-level <a href="https://www.justinobney.com/keeping-angular-service-list-data-in-sync-among-multiple-controllers/" target="_blank" rel="noopener">solution put forward by Justin Obney</a> is to make <code>users</code> the property of <code>UserService</code> and never reassign it, only mutate (mute? mutilate?). The controller references the service property, and the angular view watch works, since <code>users</code> are shared by reference. Here’s the code:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserService</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>() &#123;</span><br><span class="line">    <span class="keyword">this</span>.users = [];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  load() &#123;</span><br><span class="line">    <span class="keyword">return</span> get(<span class="string">'/users'</span>).then(<span class="function"><span class="params">users</span> =&gt;</span> &#123;</span><br><span class="line">      angular.copy(users, <span class="keyword">this</span>.users);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  addUser(user) &#123;</span><br><span class="line">    <span class="keyword">return</span> post(<span class="string">'./users'</span>, user).then(<span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">this</span>.load());</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserListController</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(userService) &#123;</span><br><span class="line">    <span class="keyword">this</span>.userService = userService;</span><br><span class="line">    <span class="keyword">this</span>.users = <span class="keyword">this</span>.userService.users;</span><br><span class="line">    userService.load();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>There are three problems with this solution:</p><ol><li>It’s fragile: if we accidentally reassign <code>users</code> either in the controller or the service, the whole scheme breaks down.</li><li>Instead of using normal javascript, you dance around the reference. The result of a well-behaved library function that does not mutate the data must be merged back into the original object.</li><li>The suggested way of caring for the reference, <code>angular.copy</code>, is angular-specific and makes a deep copy.</li></ol><p>We can work around the first issue using TypeScript’s <code>readonly</code> properties, but the reference dance persists. Using TS2+ over AngularJS is a bit bipolar, too (exacly what I used on the project, but that’s beside the point).</p><p>Luckily, we can do much better — let me show you how.</p><h2 id="The-get-set-solution"><a href="#The-get-set-solution" class="headerlink" title="The get / set solution"></a>The get / set solution</h2><p>My solution relies on ES5 getters. Compatibility analysis, if I please? ES5 is nothing hot, it’s been around long enough to be considered the web standard. People who use IE9 are probably used to the web looking and working strange. Considering a modern framework — Vue or React? They require IE9+ anyways. So yes, we can use ES5 safely.</p><p>We do whatever we want to the service property, and declare a getter for it on the controller:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserService</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>() &#123;</span><br><span class="line">    <span class="keyword">this</span>.users = [];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  load() &#123;</span><br><span class="line">    <span class="keyword">return</span> get(<span class="string">'/users'</span>).then(<span class="function"><span class="params">users</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="keyword">this</span>.users = users;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  addUser(user) &#123;</span><br><span class="line">    <span class="keyword">return</span> post(<span class="string">'./users'</span>, user).then(<span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">this</span>.load());</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserListController</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(userService) &#123;</span><br><span class="line">    <span class="keyword">this</span>.userService = userService;</span><br><span class="line">    userService.load();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  get users() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">this</span>.userService.users;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Digest works normally. Mutate the <code>users</code> array in the service and the views update. Reassign in the service — the views still update. Mutate the array in a controller — the views update (a bug, not a feature? Maybe, but that’s how it goes). We can’t accidentally reassign the controller property because it only has a getter. And we have zero angular-specific code. The trick is backwards-compatible with the old one, so we needn’t rewrite the service all at once. Nice!</p><h2 id="What-good-have-we-done"><a href="#What-good-have-we-done" class="headerlink" title="What good have we done?"></a>What good have we done?</h2><p>Is this the holy grail? Certainly not. It requires some boilerplate, a 4-line getter per controller. We’re still stuck with the shaky shared ownersip: every controller can change the object. But this is an improvement over the old way.</p><p>For completeness, here are three other solutions off the top of my head:</p><ol><li>Bind to service from the template: <code>&lt;user-card ng-repeat=&quot;user in $ctrl.userService.users&quot;&gt;&lt;/user-card&gt;</code>. Bad, because it breaks abstraction layering — the view should not touch the service.</li><li>Make the service an event bus, do <code>this.trigger(&#39;users.update&#39;, users);</code> on every users change. Vanilla implementation is fragile (never forget to call <code>trigger</code> on update), but this might work with some structure around (though at this point we might as well stick mobx into the service).</li><li><p><code>$scope.$watch(() =&gt; this.userService.users, users =&gt; this.users = users)</code>. The effect is the same as in my solution, but at the cost of an extra digest iteration. Fall back to this one for ES3 complicance.</p><p>Never say never to AngularJS — who knows how it’s gonna turn out. Drop a comment if the topic interests you! I still have a couple of AngularJS tricks down my sleeve to keep you safe. ES6 modules? String templates? CSS modules? Yes you can.</p></li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I’ve been developing an AngularJS application for the past year — and &lt;em&gt;voila!&lt;/em&gt; here I am, alive and well. I’m not some crazy old f
      
    
    </summary>
    
    
      <category term="javascript" scheme="https://thoughtspile.github.io/tags/javascript/"/>
    
      <category term="programming" scheme="https://thoughtspile.github.io/tags/programming/"/>
    
      <category term="frontend" scheme="https://thoughtspile.github.io/tags/frontend/"/>
    
      <category term="angularjs" scheme="https://thoughtspile.github.io/tags/angularjs/"/>
    
  </entry>
  
  <entry>
    <title>Programming is Like Writing</title>
    <link href="https://thoughtspile.github.io/2018/09/19/Programming-is-like-writing/"/>
    <id>https://thoughtspile.github.io/2018/09/19/Programming-is-like-writing/</id>
    <published>2018-09-19T12:04:27.000Z</published>
    <updated>2018-09-19T12:49:24.000Z</updated>
    
    <content type="html"><![CDATA[<p>I’ve been playing around with this idea for a while. The more I got into writing (Strunk-White and William Zinsser’s “On Writing Well” are most suggested), the more similarities to software development I found. Now I’m ready to put it forward: <em>writing code is still writing,</em> or <em>writing code is writing,</em> or maybe even “you’re <strong>writing</strong> code”.</p><p>After some online research this analogy does not seem as fresh. Jeff Atwood in <a href="https://blog.codinghorror.com/coding-its-just-writing/" target="_blank" rel="noopener">Coding: It’s Just Writing</a> notes the similarities between William Strunk’s tips on writing and programming best practices, and then there’s Bert Wagner <a href="https://hackernoon.com/writing-good-code-is-like-writing-a-novel-33973645be01" target="_blank" rel="noopener">talking</a> about the psychological similarities between coding and writing. On the other hand, the topic does not seem completely dead either, so watch me take another stab on it!</p><h2 id="You-produce-text-not-really"><a href="#You-produce-text-not-really" class="headerlink" title="You produce text (not really)"></a>You produce text (not really)</h2><p>On the surface, the end result of both writing and coding is text (as in “a sequence of words with some meaning”). However, this view breaks down once you think about it.</p><p>People in the software industry know that the value they provide is in solving <em>business problems</em> through code, not in writing code per se. Yet I don’t feel “shoving shitcode on top of shitcode to make things work” is the way to go. Let’s ban the whole business / technical argument for a minute.</p><figure><br>  <img style="border: 1px solid #eee;" src="/images/hexo-source.png"><br>  <div style="color: #666; text-align: center;">This is not why people like open source</div><br></figure><p>The users do not care for the code — they only see the GUI (or an API). What code you wrote in there is irreleveant as long as it works. When your users start caring about the code, it’s either because they want to learn from it, or because you screwed up and they have to dive in and debug. Not the primary use cases, huh?</p><p>But writers do indeed write texts. Or do they? A piece of writing is only valuable once you put it into your head and think about it. Very much like running a program, isn’t it? A good book is good because of the feelings and ideas it gives you, not because of the arrangement of words. Still not convinced? Think about play- and screenwriting: there is no <em>text</em> in a movie, yet the writing itself sure as hell is there.</p><p>Now, who carese about the word arrangements? Literature students do: they learn the ways to use words for the desired effect. When the text is so bad you can’t make sense of it (some lawyer mumbo-jumbo), you read it over and over again — isn’t it “text debugging”? Bingo on both!</p><h2 id="You’re-transmitting-intention-through-text"><a href="#You’re-transmitting-intention-through-text" class="headerlink" title="You’re transmitting intention through text"></a>You’re transmitting intention through text</h2><p>And text is not even the best medium for what we the writers (see what I did there?) are trying to acheive. But we don’t know any better, so we settled on it somehow. We just want to communicate the ideas in our heads: algorithms, storylines, all is one.</p><p><img src="/images/tintin-grasshopper.png" alt=""></p><p>The attempts to run away from the text? Check! Visual programming and comic books, respectively. However, people do not take these too seriously. Don’t grumble, give these some time and they will outshine the poor old text.</p><h2 id="People-think-complex-and-long-is-cool-it-is-not"><a href="#People-think-complex-and-long-is-cool-it-is-not" class="headerlink" title="People think complex and long is cool (it is not)"></a>People think complex and long is cool (it is not)</h2><p>What makes a writer good? It must be all those fancy baroque wordings! I heard James Joyce was good, and you can barely make sense of his books. The more grotesque plot twists, the merrier. But didn’t the greatest writers always talk about working hard to keep their works simple?</p><p>Now, what makes a programmer good? It must be all the fancy optimization hacks! How cool, this dude uses Singletons, Message Queues and Service Workers! No one can understand this code — what a work of genius! Sounds familiar? If you program, you know it’s bullshit. The best code for the job is the simplest code for the job — it’s easy to follow and does not strangle the performance with all the unnecessary layers of abstraction.</p><h2 id="Teamwork-is-limited-it-is-still-there"><a href="#Teamwork-is-limited-it-is-still-there" class="headerlink" title="Teamwork is limited (it is still there)"></a>Teamwork is limited (it is still there)</h2><p>Ten writers working on a book won’t write it ten times better or faster than one. Similarly, if you give one task to ten programmers with no management, they would drown in merge conflicts before delivering.</p><p><img style="border: 1px solid #eee;" src="/images/maxwell-perkins.jpg"></p><p>However, teamwork does exist in both industries, and is strikingly similar. Our code reviews = writers’ proofreading and editing. I remember Hemmingway’s quote about how cool his editor was, but I can’t seem to find that one now that there’s some <em>proofreading</em> software called <em>Hemmingway</em> — hope it edits sober. And you know how the code collapses into anarchy once there’s no one to stop you and watch with a clear eye.</p><h2 id="The-conclusion-I-am-so-serious"><a href="#The-conclusion-I-am-so-serious" class="headerlink" title="The conclusion (I am so serious)"></a>The conclusion (I am so serious)</h2><p>And I feel that as exploring other areas — art, cooking, construction, retail, what not — I will find even more structure to all of these. So make sure to come by when I publish more posts on “Programming is like Making Pasta”, “Hackathons are Like Doodling” and “Working in Outsource is Like Being an Illegal Plumber”.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I’ve been playing around with this idea for a while. The more I got into writing (Strunk-White and William Zinsser’s “On Writing Well” ar
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Quick Tip: docx is a zip Archive</title>
    <link href="https://thoughtspile.github.io/2018/07/14/docx-is-a-zip-archive/"/>
    <id>https://thoughtspile.github.io/2018/07/14/docx-is-a-zip-archive/</id>
    <published>2018-07-14T11:33:41.000Z</published>
    <updated>2018-07-14T12:06:23.000Z</updated>
    
    <content type="html"><![CDATA[<p>Microsof Office’s <code>docx</code> files are actually zip archives with a bunch of XMLs and all the attached media. Super useful, everyone should know it!</p><p>When I tell my colleagues, friends, or students about it, they don’t take me seriously the first time. So, here we go again. If you have a docx (or xlsx, or pptx) file, you can unzip it with <code>unzip proj.docx -d proj</code> or any other unarchiver and get a folder with all the stuff that makes up the document:</p><p><img src="/images/unzipped-docx.png" alt=""></p><p>From here, you can:</p><ul><li>quickly grab all the media from  <code>word/media</code></li><li>work with the document (<code>word/document</code>) via an XML parser (or grep / sed, but it’s a secret)</li></ul><p>And do all the other marvellous stuff — no Office or even GUI needed. Now go and spread the light of this newfound knowledge and never complain about docx again!</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Microsof Office’s &lt;code&gt;docx&lt;/code&gt; files are actually zip archives with a bunch of XMLs and all the attached media. Super useful, everyo
      
    
    </summary>
    
    
      <category term="microsoft, zip, &#39;quick tip&#39;" scheme="https://thoughtspile.github.io/tags/microsoft-zip-quick-tip/"/>
    
  </entry>
  
  <entry>
    <title>Advanced Promise Coordination: Rate Limiting</title>
    <link href="https://thoughtspile.github.io/2018/07/07/rate-limit-promises/"/>
    <id>https://thoughtspile.github.io/2018/07/07/rate-limit-promises/</id>
    <published>2018-07-07T07:11:13.000Z</published>
    <updated>2018-07-07T07:56:33.000Z</updated>
    
    <content type="html"><![CDATA[<p>In the <a href="/2018/06/20/serialize-promises/">previous post</a> we learnt to serialize<br>and concurrecy-limit promise-based operations in js. This time we dive further<br>and handle rate limiting.</p><h2 id="What-Exactly-to-Rate-Limit"><a href="#What-Exactly-to-Rate-Limit" class="headerlink" title="What Exactly to Rate Limit"></a>What Exactly to Rate Limit</h2><p>Let’s get terminological matters out of the way first. Promises represent operations<br>that last a certain amount of time, while rate limiting is applied to discrete events.<br>Over its life, a promise starts and terminates (with a success or a failure, not<br>important now). It makes most sense to rate limit promise creations (starts).<br>Rate limiting promise resolutions can be done by appending a start-rate-limited<br>promise onto the end of the running promise. We could also limit the gap<br>between operations, but I have no idea how that would be useful.</p><h2 id="Rate-vs-concurrency-limiting"><a href="#Rate-vs-concurrency-limiting" class="headerlink" title="Rate vs concurrency limiting"></a>Rate vs concurrency limiting</h2><p>While both rate and concurrency limits are trying to prevent a client from<br>overloading the server by making too many calls too fast, they do not replace<br>one another, and are implemented differently.</p><p>Suppose an API is rate-limited to 1 request per second. Even 1-concurrent requests<br>break the rate limit if they complete in under 1s. On the other hand, if the<br>requests take 3 seconds to complete, we can only have 3 of them running at the same time:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"> ...</span><br><span class="line">  ...</span><br></pre></td></tr></table></figure><p>We could derive a bunch of formulae to connect the concurrency, rate and<br>running time of operations, but that’s completely beside the point. The thing to<br>remember here is that without strict guarantees on operation duration you can<br>not replace concurrency limit with rate limit or vice versa.</p><h2 id="Rate-limiting-individual-operations"><a href="#Rate-limiting-individual-operations" class="headerlink" title="Rate limiting individual operations"></a>Rate limiting individual operations</h2><p>The simplest form of rate limiting is “1 operation per N seconds”. This one is<br>straightforward, but first we need a building block — the promise counterpart<br>of <code>setTimeout</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> resolveAfter = <span class="function"><span class="params">ms</span> =&gt;</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="params">ok</span> =&gt;</span> setTimeout(ok, ms));</span><br></pre></td></tr></table></figure><p><code>resolveAfter</code> is self-explanatory: it returns a promise that resolves after<br>the specified time has elapsed. Now, for the actual rate limiter:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">rateLimit1</span>(<span class="params">fn, msPerOp</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> wait = <span class="built_in">Promise</span>.resolve();</span><br><span class="line">  <span class="keyword">return</span> <span class="function">(<span class="params">...a</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// We use the queue tail in wait to start both the</span></span><br><span class="line">    <span class="comment">// next operation and the next delay</span></span><br><span class="line">    <span class="keyword">const</span> res = wait.then(<span class="function"><span class="params">()</span> =&gt;</span> fn(...a));</span><br><span class="line">    wait = wait.then(<span class="function"><span class="params">()</span> =&gt;</span> resolveAfter(msPerOp));</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Now we can, as usual, wrap the promise and call with no worries, the operations<br>are magically delayed:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> slowFetch = rateLimit1(fetch, <span class="number">1000</span>);</span><br><span class="line"><span class="built_in">Promise</span>.all(urls.map(<span class="function"><span class="params">u</span> =&gt;</span> slowFetch(u)))</span><br><span class="line">  .then(<span class="function"><span class="params">raw</span> =&gt;</span> <span class="built_in">Promise</span>.all(raw.map(<span class="function"><span class="params">p</span> =&gt;</span> p.json())))</span><br><span class="line">  .then(<span class="function"><span class="params">pages</span> =&gt;</span> <span class="built_in">console</span>.log(pages));</span><br></pre></td></tr></table></figure><p>The 1-rate-limiter can also be elegantly implemented on top of serializer<br>with the pitfall of unnecessarily delaying the first operation:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">rateLimit1</span>(<span class="params">fn, msPerOp</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> wait = serializePromises(<span class="function"><span class="params">()</span> =&gt;</span> resolveAfter(msPerOp));</span><br><span class="line">  <span class="keyword">return</span> <span class="function">(<span class="params">...a</span>) =&gt;</span> wait().then(<span class="function"><span class="params">()</span> =&gt;</span> fn(...a));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Rate-limiting-multiple-operations"><a href="#Rate-limiting-multiple-operations" class="headerlink" title="Rate limiting multiple operations"></a>Rate limiting multiple operations</h2><p>Many APIs feature soft rate limits instead: they allow <code>M request per N seconds</code>.<br>That is not equivalent to <code>1 request per N/M seconds</code>! Converting the multiple<br>rate limit into individual one does fulfil the rate limit, but is overly harsh<br>and non-optimal. Let’s see this through examples.</p><h3 id="Difference-from-individual-rate-limit-by-example"><a href="#Difference-from-individual-rate-limit-by-example" class="headerlink" title="Difference from individual rate limit, by example"></a>Difference from individual rate limit, by example</h3><p>Suppose you’re flying a plane, and the airline allows 10 kg of luggage per<br>passenger. If you’re travelling with a girl, and have one 16-kg bag with both<br>your things. At the check-in desk you’re asked to take out half the stuff in<br>your bag to make two 8-kg items. While formally correct, it feels idiotic —<br>you still add the exact same weight to the plane! But now, why would you enforce<br>such a stupid restriction on your own operations if you can do better?</p><p>Closer to the topic, let’s try 2-req-per-2-sec rate limit for operations<br>lasting 2 seconds. If you immediately fire 2 requests, you’re done in 2 seconds:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">----| 2 seconds, all done!</span><br><span class="line">----|</span><br></pre></td></tr></table></figure><p>Converting this into 1-req-per-1-sec delays the second request by 1s, and<br>now the same 2 requests take 3 seconds! You just lost a second for no reason.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">----  | 3 seconds</span><br><span class="line">  ----|</span><br></pre></td></tr></table></figure><h3 id="Understanding"><a href="#Understanding" class="headerlink" title="Understanding"></a>Understanding</h3><p>To understand what we should do, let’s have a closer look at the 1-rate-limit.<br>We essentially make a queue of promises that never resolve closer than <code>delay</code><br>apart. We use the resolutions to start the next operations, and don’t care<br>about its termination at all:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">*--*--     *--*--</span><br></pre></td></tr></table></figure><p>This view extends to N-rate-limit: create N independent queues and put these<br>into a circular queue (yes, a queue of queues makes a good <em>in Soviet Russia</em><br>joke):</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">*--*-- *--*--</span><br><span class="line"> *-- *--*--  *--</span><br><span class="line"> *--  *-- *--    *--</span><br></pre></td></tr></table></figure><p>The individual queues are unchanged, and never fire more than 1 operation per N<br>seconds. Thus, M queues can fire at most M operations during the window.</p><h3 id="Implementing"><a href="#Implementing" class="headerlink" title="Implementing"></a>Implementing</h3><p>With this plan in mind, we can generalize the implementation:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">rateLimit</span>(<span class="params">fn, windowMs, reqInWindow = <span class="number">1</span></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// A battery of 1-rate-limiters</span></span><br><span class="line">  <span class="keyword">const</span> queue = _.range(reqInWindow).map(<span class="function"><span class="params">()</span> =&gt;</span> rateLimit1(fn, windowMs));</span><br><span class="line">  <span class="comment">// Circular queue cursor</span></span><br><span class="line">  <span class="keyword">let</span> i = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">return</span> <span class="function">(<span class="params">...a</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// to enqueue, we move the cursor...</span></span><br><span class="line">    i = (i + <span class="number">1</span>) % reqInWindow;</span><br><span class="line">    <span class="comment">// and return the rate-limited operation.</span></span><br><span class="line">    <span class="keyword">return</span> queue[i](...a);</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Preventing-queue-overflow"><a href="#Preventing-queue-overflow" class="headerlink" title="Preventing queue overflow"></a>Preventing queue overflow</h2><p>Just as before, we run into problems if the operations are consistently inserted<br>into the queue faster than the rate limit. The solution is the same: once the<br>queue exceeds the specified number of items, we immediately reject the incoming<br>operations.</p><h2 id="Combining-with-concurrency-limiting"><a href="#Combining-with-concurrency-limiting" class="headerlink" title="Combining with concurrency limiting"></a>Combining with concurrency limiting</h2><p>Now that we know how to limit both the rate and the number of simultaneously<br>running operations, and since neither is a substitute for another, we want a<br>way to combine the two limits. But can we build the joint rate/concurrency<br>limiter by composing the primitive limiters? Turns out we can, but should carefully<br>choose the order.</p><p><code>rateLimit(concurrencyLimit(fetch, N), ms)</code>, limits the rate at which the<br>operations enter the concurrency-limit queue. Serialized (1-concurrent) promises<br>rate-limited to 1 second break this combination. Suppose the first operation runs for<br>2 seconds, and during that time we throw 2 fast operations, O_2 and O_3 (say,<br>10 ms each) into the serializer. Instead of waiting for 1 second, the O_3 starts<br>right after O_2 completes, or 10ms after it starts, breaking the rate limit.</p><p><code>concurrencyLimit(rateLimit(fetch, ms), N)</code> limits the number of operations in<br>the rate-limit queue. Since the rate limiter only sees N operations at a time,<br>it has no chance to fire more than N, which is exactly what we want.<br>Hence, <strong>Chaining Rule 1: limit concurrency before rate.</strong></p><h2 id="Use-cases"><a href="#Use-cases" class="headerlink" title="Use cases"></a>Use cases</h2><p>The classic and most appropriate rate-limiting use case is for API requests.<br>But now that you know the pattern, you will see it in your own tasks and,<br>hopefully, use it ;-)</p><p>Promise-based rate limiting is a great way to quickly hack together a safe API<br>wrapper without depending on the underlying HTTP / TCP / WebSocket client.</p><p>Frankly, other use cases I can come up with off the top of my head (render<br>throttling and preventing too many e-mail notifications) are better served by<br>batching. Maybe, you’ll have better luck.</p><h2 id="Summary"><a href="#Summary" class="headerlink" title="Summary"></a>Summary</h2><p>We’ve learnt to rate-limit promise-based APIs, both for the simple<br>“1-action-per-N-seconds” and the more general M-actions case. Together with the<br>previously discussed concurrency limiter, these patterns allow us to build robust<br>service gateways with node.js, safely call external APIs and do all the other<br>things you come up with.</p><p>Planning note: I’ve decided to throw away the excessively tricky part on load<br>balancing and go with super fun and useful posts on <em>batching</em> and <em>handling failure</em>.<br>I have RSS now, so be sure to stay tuned!</p><p><strong>Advanced Promise Coordination Series</strong></p><ul><li><a href="/2018/06/20/serialize-promises/">Serialization and Concurrency Limiting</a></li><li><a href="/2018/07/07/rate-limit-promises/">Rate Limiting</a></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;In the &lt;a href=&quot;/2018/06/20/serialize-promises/&quot;&gt;previous post&lt;/a&gt; we learnt to serialize&lt;br&gt;and concurrecy-limit promise-based operation
      
    
    </summary>
    
    
      <category term="javascript" scheme="https://thoughtspile.github.io/tags/javascript/"/>
    
      <category term="programming" scheme="https://thoughtspile.github.io/tags/programming/"/>
    
      <category term="promises" scheme="https://thoughtspile.github.io/tags/promises/"/>
    
      <category term="high availability" scheme="https://thoughtspile.github.io/tags/high-availability/"/>
    
  </entry>
  
  <entry>
    <title>Advanced Promises Coordination: Serialization and Concurrency Limiting</title>
    <link href="https://thoughtspile.github.io/2018/06/20/serialize-promises/"/>
    <id>https://thoughtspile.github.io/2018/06/20/serialize-promises/</id>
    <published>2018-06-20T09:42:08.000Z</published>
    <updated>2018-07-07T07:52:25.000Z</updated>
    
    <content type="html"><![CDATA[<p>I’m sure you can chain promises with <code>doBefore().then(() =&gt; doAfter())</code> and even<br>run multiple promises in parallel using <code>Promise.any</code>. However, chaining an<br>unknown count of homogenous promises is trickier. Let me teach you to serialze<br>promises like a pro!</p><p>Suppose we want a list of all the cafes in a mid-sized european country.However,<br>the API only lets you query the cafes by city. No problem — we have a list of<br>all the cities, and will send a request for each one, then assemble the results.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> cities = [</span><br><span class="line">  <span class="string">"Abertamy"</span>,</span><br><span class="line">  <span class="string">"Adamov (Blansko District)"</span>,</span><br><span class="line">  <span class="string">"Aš"</span>,</span><br><span class="line">  <span class="string">"Bakov nad Jizerou"</span>,</span><br><span class="line">  <span class="string">"Bavorov"</span>,</span><br><span class="line">  <span class="string">"Bechyně"</span>,</span><br><span class="line">  <span class="string">"Bečov nad Teplou"</span>,</span><br><span class="line">  <span class="string">"Bělá nad Radbuzou"</span>,</span><br><span class="line">  <span class="string">"Bělá pod Bezdězem"</span>,</span><br><span class="line">  <span class="comment">// ... and 200 more</span></span><br><span class="line">];</span><br><span class="line"><span class="keyword">const</span> loadCafes = <span class="function"><span class="params">city</span> =&gt;</span> fetch(<span class="string">`api.fivecircle.com/city/<span class="subst">$&#123;city&#125;</span>`</span>);</span><br></pre></td></tr></table></figure><h2 id="How-Not-to-Chain-Promises"><a href="#How-Not-to-Chain-Promises" class="headerlink" title="How Not to Chain Promises"></a>How Not to Chain Promises</h2><p>The first naive attempts are no good:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// All gone in a glimpse of eye:</span></span><br><span class="line"><span class="built_in">Promise</span>.all(areas.map(loadCafes)).then(<span class="function"><span class="params">cafes</span> =&gt;</span> db.save(_.flatten(cafes)));</span><br><span class="line"><span class="comment">// Still not good</span></span><br><span class="line">areas.forEach(<span class="function"><span class="params">area</span> =&gt;</span> &#123;</span><br><span class="line">  loadCafes(area).then(storeData);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// More of the same</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> area <span class="keyword">in</span> areas) &#123;</span><br><span class="line">  loadCafes(area).then(storeData);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Since promises start executing once created, each of these options fires all<br>the requests at once. With sane rate limiting restrictions, it will fail.<br>A less elaborate server could even crash.</p><p>We could, of course, use <code>await</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> cafes = [];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> area <span class="keyword">of</span> areas) &#123;</span><br><span class="line">  cafes = cafes.concat(<span class="keyword">await</span> loadCafes(area));</span><br><span class="line">&#125;</span><br><span class="line">storeData(cafes);</span><br></pre></td></tr></table></figure><p>But I’m not a fan of this syntax — the code is now arguably C-like. I also<br>find error handling in promises cleaner. And now we have more preprocessing to do<br>for the code to work, which is nothing to be proud of. So let’s go on and write this<br>in pure promises instead.</p><h2 id="Explicit-Serialization"><a href="#Explicit-Serialization" class="headerlink" title="Explicit Serialization"></a>Explicit Serialization</h2><p>The best-known trick from this bunch is explicitly chaining an array of promises with<br><code>&lt;Array&gt;.reduce</code>. It works best for fire-and-forget promises, like redux actions:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> actions.reduce(</span><br><span class="line">  (pre, action) =&gt; before.then(<span class="function"><span class="params">()</span> =&gt;</span> action()),</span><br><span class="line">  <span class="built_in">Promise</span>.resolve());</span><br></pre></td></tr></table></figure><p>However, assembling return values is a bit awkward:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">areas.reduce(<span class="function">(<span class="params">before, area</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> before.then(<span class="function"><span class="params">acc</span> =&gt;</span> loadCafes(area).then(<span class="function"><span class="params">cafes</span> =&gt;</span> acc.concat(cafes)));</span><br><span class="line">&#125;, <span class="built_in">Promise</span>.resolve([])).then(<span class="function"><span class="params">cafes</span> =&gt;</span> db.save(cafes));</span><br></pre></td></tr></table></figure><p>Overall, this is good enough when you have an array of data you want to run the<br>actions on beforehand. But what if you don’t?</p><h2 id="Implicit-Serialization"><a href="#Implicit-Serialization" class="headerlink" title="Implicit Serialization"></a>Implicit Serialization</h2><p>We can actually write a wrapper for arbitrary promise-returning<br>functions that makes any call wait for the previous ones to finish. This wrapper<br>is completely transparent, leaving the function’s interface intact — good for<br>composability. Here it is:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">serializePromises</span>(<span class="params">immediate</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// This works as our promise queue</span></span><br><span class="line">  <span class="keyword">let</span> last = <span class="built_in">Promise</span>.resolve();</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params">...a</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// Catch is necessary here — otherwise a rejection in a promise will</span></span><br><span class="line">    <span class="comment">// break the serializer forever</span></span><br><span class="line">    last = last.catch(<span class="function"><span class="params">()</span> =&gt;</span> &#123;&#125;).then(<span class="function"><span class="params">()</span> =&gt;</span> immediate(...a));</span><br><span class="line">    <span class="keyword">return</span> last;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Now we can just wrap our function and never have to worry about flooding the API again:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> loadCafesSafe = serializePromises(loadCafes);</span><br><span class="line"><span class="built_in">Promise</span>.all(areas.map(<span class="function"><span class="params">a</span> =&gt;</span> loadCafesSafe(a)));</span><br></pre></td></tr></table></figure><p>It’s so easy it doesn’t warrant a library — just five lines of code. And we can<br>take this idea further with…</p><h2 id="Concurrency-Limiting"><a href="#Concurrency-Limiting" class="headerlink" title="Concurrency Limiting"></a>Concurrency Limiting</h2><p>Serialization effectively forces our promises to run in one thread. To make them<br>go faster, we can generalize the serializer to allow not one, but at most N<br>promises to run simultaneously:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">limitConcurrency</span>(<span class="params">immediate, maxConcurrent</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// Each element holds its index, or a promise resolving with the index</span></span><br><span class="line">  <span class="keyword">const</span> workers = _.range(maxConcurrent);</span><br><span class="line">  <span class="comment">// Without this serialization, Promise.race would resolve with the same</span></span><br><span class="line">  <span class="comment">// worker whenever a concurrency-limited function was synchronously called</span></span><br><span class="line">  <span class="comment">// multiple times.</span></span><br><span class="line">  <span class="keyword">const</span> findWorker = serializePromises(<span class="function"><span class="params">()</span> =&gt;</span> <span class="built_in">Promise</span>.race(workers));</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params">...a</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// race resolves with the first free worker</span></span><br><span class="line">    <span class="keyword">return</span> findWorker().then(<span class="function"><span class="params">i</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// and here we start the action and update the worker correspondingly:</span></span><br><span class="line">      <span class="keyword">const</span> promise = immediate(...a);</span><br><span class="line">      workers[i] = promise.then(<span class="function"><span class="params">()</span> =&gt;</span> i, () =&gt; i);</span><br><span class="line">      <span class="keyword">return</span> promise;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>The idea is the same, but we replaced the single <code>last</code> promise with an array of<br>N workers and added some bookkeeping. This code packs promises into threads as<br>tightly as possible, with no idle time.</p><p>Also note that <code>serializePromises</code> is the same as <code>a =&gt; limitConcurrency(a, 1)</code>.</p><p>If you want to impose joint limiting on several arbitrary functions, you can tweak the<br>code — I leave this to you as an exercise ;-)</p><h2 id="Propagating-Rate-Errors"><a href="#Propagating-Rate-Errors" class="headerlink" title="Propagating Rate Errors"></a>Propagating Rate Errors</h2><p>Now that our code manages a promise queue, we can see a potential problem in it.<br>The system can smooth activity spikes without propagating these upstream.<br>However, if the request rate is higher than what the upstream can handle for an<br>extended period of time, our queue can overfill and blow up the memory limit.</p><p>The problem still existed before we added the limiter, but would occurred<br>upstream instead. No wrapper can magically improve service throughput.</p><p>To handle these errors without crashing our process, we can put a hard limit on<br>queue size. Here’s how it can be done for the generic <code>limitConcurrency</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">limitConcurrency</span>(<span class="params">immediate, maxConcurrent, maxQueue</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// this is our queue counter</span></span><br><span class="line">  <span class="keyword">let</span> queued = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">const</span> workers = _.range(maxConcurrent);</span><br><span class="line">  <span class="keyword">const</span> findWorker = serializePromises(<span class="function"><span class="params">()</span> =&gt;</span> <span class="built_in">Promise</span>.race(workers));</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params">...a</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (queued &gt;= maxQueue) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="built_in">Promise</span>.reject(<span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">'Max queue size reached'</span>));</span><br><span class="line">    &#125;</span><br><span class="line">    queued += <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">return</span> findWorker().then(<span class="function"><span class="params">i</span> =&gt;</span> &#123;</span><br><span class="line">      queued -= <span class="number">1</span>;</span><br><span class="line">      <span class="keyword">const</span> promise = immediate(...a);</span><br><span class="line">      workers[i] = promise.then(<span class="function"><span class="params">()</span> =&gt;</span> i, () =&gt; i));</span><br><span class="line">      <span class="keyword">return</span> promise;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Now, instead of uncontrollably enqueueing, the coordinator rejects when there’s<br>already too much work ahead. The consumers can handle these errors and retry later.</p><h2 id="Use-Cases"><a href="#Use-Cases" class="headerlink" title="Use Cases"></a>Use Cases</h2><p>So far we’ve been discussing an example with API requests, and you might argue<br>that concurrency limiting functionality should be provided bt the HTTP client<br>library. That’s true, but the power of our promise-based strategy is its generality.<br>Here are some unorthodox use cases:</p><h3 id="“Sloppy-Transactions”-with-Serialization"><a href="#“Sloppy-Transactions”-with-Serialization" class="headerlink" title="“Sloppy Transactions” with Serialization"></a>“Sloppy Transactions” with Serialization</h3><p>Suppose an action involves reading an external data source, computing on the<br>response and issuing an update. If the source changes between the read and the<br>update, you’ve corrupted your data beyond repair. You can instead wrap the action<br>with our “promise serializer”. Of course, this assumes that the relevant data is only<br>accessed by your wrapper, and only by a single process. You can even build a<br>simple file-based database.</p><h3 id="Prevent-Notification-Flood-with-Concurrency-Limiting"><a href="#Prevent-Notification-Flood-with-Concurrency-Limiting" class="headerlink" title="Prevent Notification Flood with Concurrency Limiting"></a>Prevent Notification Flood with Concurrency Limiting</h3><p>A front-end idea. You probably have a notification area somewhere on<br>the screen. However, if a large batch of notifications just arrived, the users are<br>likely to miss some of those. But now you can treat the currently visible<br>notifications as the running threads and apply <code>limitConcurrecny</code>!</p><p>A similar use case for modal windows uses serialized promises — you can’t<br>show multiple modals at the same time, but now you can enqueue the next one<br>instead.</p><h3 id="Web-Worker-Thread-Pool"><a href="#Web-Worker-Thread-Pool" class="headerlink" title="Web Worker Thread Pool"></a>Web Worker Thread Pool</h3><p>Finally, time for some cutting-edge tech. If your web app heavily uses web<br>workers for background processing, you can wrap web worker access with a<br>promise-based API, then use our wrapper to limit the number of simultaneously<br>active workers. With several kinds of specialized workers, you might choose to<br>use a multi-factory flavour of our <code>limitConcurrecny</code> instead. I’ll delve<br>deeper into this this case with an upcoming article on load balancing.</p><h2 id="Summary"><a href="#Summary" class="headerlink" title="Summary"></a>Summary</h2><p>We’ve learnt how to force promises to run consecutively and even to limit the<br>number of pending promises to a specified number. This technique can be used<br>for safer back-end access, and its generality allows to use it for any<br>promise-based API.</p><p>I’m not too good at writing: the topics kept expanding in my head, and I have<br>had a hard time finishing this article. I have two other interesting<br>promise coordination patterns to handle in future articles of this series:</p><ul><li>Rate Limiting</li><li>Load Balancing</li></ul><p>Wish me luck writing these! If you have some tips or want to argue, drop me an<br>e-mail.</p><p><strong>Advanced Promise Coordination Series</strong></p><ul><li><a href="/2018/06/20/serialize-promises/">Serialization and Concurrency Limiting</a></li><li><a href="/2018/07/07/rate-limit-promises/">Rate Limiting</a></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I’m sure you can chain promises with &lt;code&gt;doBefore().then(() =&amp;gt; doAfter())&lt;/code&gt; and even&lt;br&gt;run multiple promises in parallel using
      
    
    </summary>
    
    
      <category term="javascript" scheme="https://thoughtspile.github.io/tags/javascript/"/>
    
      <category term="programming" scheme="https://thoughtspile.github.io/tags/programming/"/>
    
      <category term="promises" scheme="https://thoughtspile.github.io/tags/promises/"/>
    
      <category term="concurrency" scheme="https://thoughtspile.github.io/tags/concurrency/"/>
    
  </entry>
  
</feed>
