{
  "version": "https://jsonfeed.org/version/1",
  "title": "speculative nonfiction on Softly developing about software development",
  "icon": "https://avatars.micro.blog/avatars/2026/14/62453.jpg",
  "home_page_url": "https://softlydeveloping.micro.blog/",
  "feed_url": "https://softlydeveloping.micro.blog/feed.json",
  "items": [
      {
        "id": "http://softlydeveloping.micro.blog/2023/12/22/my-sparse-margin-note-couplet.html",
        "title": "My sparse margin note couplet from Jon Bentley's Programming Pearls, also bit of a book review, and a whole ass",
        "content_html": "<img src=\"https://internetross.space/uploads/2023/batman-year-one-im-fine.png\" title=\"batman-year-one-im-fine.png\" alt=\"comic frame of Batman on top of a man who says 'I'm Fine'\" border=\"0\" width=\"598\" height=\"278\">\n<img src=\"https://internetross.space/uploads/2023/programming-pearls.png\" alt=\"keyboard laying on top of an oyster shell and a pearl necklace\" title=\"programming-pearls.png\" border=\"0\" width=\"599\" height=\"567\">\n<pre tabindex=\"0\"><code>In 2015 I bought this book.    \n7, or 8 years ago.    \nYear one into my software career.   \nThis book is canon.   \nI've had little use for its studies of algorithms. # thus far, see below     \nI don't think Bentley would be offended.    \nFirst sentence: &quot;Computer programming has many faces.&quot;    \n</code></pre><p>I&rsquo;m sure I glanced at its pages before entering the corporate interview gauntlet to get in the vigilante mood. To shake out the shoulders, find some relaxment, whilst staring down a twenty two minute treadmill run or pile of laundry Sunday evening. You must to armor up for the algos in the kingdom of men.</p>\n<p>While Bentley&rsquo;s pearls are the type of polished wisdom earned through real life experience we get on the job, this book never became the vade mecum for my quotidian affairs. Is it for others? What comes after Part I was too metallic for an early-career front-end Rails dev.</p>\n<p>Yet, the book can be pragmatic for all ages &ndash; see <em>3.2 Form-Letter Programming!</em>. The  fantastic headings are pedagogically caring. It is sensually satiated with geeked thoroughness. The cases are actually well-situated within the real-world: Bentley spoils you with further readings and sidebars, journalistic first-hand-accounts that remind you of how the metal has been worked over by a person&rsquo;s hands.</p>\n<p>It reminds you that software is not lonely, which is important.</p>\n<p>But beware: there&rsquo;s a modest amount of myth-making for his contemporaries and mentors. And yet, they are the most honest plagiarisms. Yes/and: he&rsquo;s humbler than many. (Perhaps it is worth another pass now that I have more years in the rear view).</p>\n<p>I am a visual learner and thinker: logical word-problems were always a pain. In recent years I tend to reach for Bhargava&rsquo;s <em>Grokking Algorithms</em> for a refresher on binary search or walking trees. It has cute pictures. It&rsquo;s stacked next to other faves like <em>Land of Lisp</em> and <em>Why&rsquo;s (Poignant) Guide to Ruby</em>.</p>\n<p>Hmmm (thinking emoji, I will not look you in the eye as I cock my head buried in thoughts). After all, the solstice konmari of my bookshelf &ndash; which I thought would elicit a reflection on some forgotten paper taking up space &ndash; has become the discovery of lost treasure. And yet, I&rsquo;m still tickled by the scant amount of notes taken. I can&rsquo;t read without a pen. Perhaps we&rsquo;re time-traveling, then.</p>\n<pre tabindex=\"0\"><code>It's year one. \nYoung Rails dev. \nHe makes only two liner notes in a book considered staple grocery. \nI don't remember if I even read the whole thing. \nI bet I got through Part 1's wider lens, then started to gloss over.\n</code></pre><p>One note is an exaggerated check mark next to this <em>principle</em> listed on p29 (Second Edition, published 2000):</p>\n<p>&gt; Rework repeated code into arrays. A long stretch of similar code is often best expressed by the simplest of data structures, the array.</p>\n<p>With &ldquo;the array&rdquo; also underlined from the outer left edge of the &ldquo;t&rdquo; to the outer right edge of the last &ldquo;a.&rdquo;</p>\n<p>This one has stuck. Arrays, especially <em><a href=\"https://en.wikipedia.org/wiki/Associative_array#Ordered_dictionary\">maps</a></em>, can be more durable when staring down change. Before long any thoughtful software developer will realize that the components of a software system will become ordered and/or multiple.</p>\n<p>There is no lonely software.</p>\n<p>Data, whether as scalar, &ldquo;bags&rdquo; of properties, even subroutines and processes, even the manual lever pulling human tasks must be sequenced, serial, bound, reversed, indexed, sorted. The maintenance cost of housing data in ordered collections is generally low.</p>\n<pre tabindex=\"0\"><code>[&lt;anything&gt;, &lt;anything&gt;] \n</code></pre><p>Whole ass languages, like Clojure, were designed to favor ordered, associative arrays. As I learned after finding Hickey&rsquo;s seminal talk <em>Simple Made Easy</em>. Richly simple and luxurious as Hockney&rsquo;s bathers.</p>\n<img src=\"https://internetross.space/uploads/2023/hockney-sunbather.jpg\" alt=\"hockney's sunbather painting\" title=\"hockney-sunbather.jpg\" border=\"0\" width=\"600\" height=\"598\">\n<p>A second mark: a vertical line next to the opener for section <em>12.2 One Solution</em>. This was (yet another moment in my lifetime) I learned that we never have to go it alone when staring down the void of what we&rsquo;re building next:</p>\n<p>&gt; As soon as we settled on the problem to be solved, I ran to my nearest copy of Knuth&rsquo;s <em>Seminumerical Algorithms</em> (having copies of Knuth&rsquo;s three volumes both at home and at work has been well worth the investment).</p>\n<p>This has also stuck, reified after seasons.</anything></anything></p>\n",
        "date_published": "2023-12-22T19:53:23-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/12/22/my-sparse-margin-note-couplet.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/11/20/but-night-software-is-not.html",
        
        "content_html": "<p>&gt; But night software is not like that. It’s not written for the day job. It’s not written to see the light of day at all. It’s not written to be looked at and scrutinized by anybody. It’s intimate and personal, it’s messy and buggy. To take a look is to transgress.</p>\n<p>Boundary cross. Sex.</p>\n<p>From a small heap software that helps make software. By way of <a href=\"https://merveilles.town/@neauoire/111416145594833059%20\">Devine Lu Linvega</a></p>\n",
        "date_published": "2023-11-20T22:18:04-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/11/20/but-night-software-is-not.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/11/20/dei-grieving-and-ai-skepticism.html",
        "title": "DEI Grieving and AI Skepticism",
        "content_html": "<p>IYKYK DEI in tech is all but dead. If you&rsquo;re an outsider, it&rsquo;s important to understand that employee-led efforts to make workplaces less racist &ndash; which began in earnest at the onset of the Obama years &ndash; have been steadily blotted out since Trump. The Tech aristocracy has decided to abandon DEI budgets along with other workplace perks. As @betsythemuffin notes (in the thread I&rsquo;ll be referencing below):</p>\n<p>&gt; DEI is <em>seen</em> by a sizable chunk of the funder class as an allowable luxury to keep the peons happy.</p>\n<p>It has been tragically hard to swallow this defeat. @betsythemuffin again:</p>\n<p>&gt;Regret that we didn&rsquo;t do more to build material power when we had the chance.</p>\n<p>And yet, as the movement has regrouped and recentered to reposition the struggle, some have begun to take note of a problematic adaptation in the techy left&rsquo;s rhetoric. @danilo started a thread on Mastodon that points out a new-born form of absolutist skepticism for emerging <em>technologies</em> &ndash; notably AI (of course). Regardless of why the left slips into what @glyph calls a problem of &ldquo;semasiology&rdquo; around the term &ldquo;AI&rdquo;, point is, the hurt seems to be cutting so deep that the movement has retreated into an unproductive preservationism.</p>\n<p>&gt; The abject and understandably heartbreaking defeat of DEI-type progress in tech has moved most leftist critique of the space into a technological conservatism built on denialist, magical thinking.</p>\n<p>&gt; You can’t successfully advocate for a dead end when the other side is investing in roads that lead to helpful places.</p>\n<p>&gt; You can’t win against technologies people find useful by pretending they aren’t useful.</p>\n<p>Check out the rest of the <a href=\"https://hachyderm.io/@danilo/111439397005424457\">conversation</a>. There are smart people in here thinking through this &ldquo;AI&rdquo; moment. The underlying question seems to be how we can continue the fight without completely disavowing what might be practical revolutions borne out by this albeit early phase of &ldquo;AI&rdquo; that is &ldquo;finally bearing serious fruit.&rdquo;</p>\n<p>If you&rsquo;re wondering on what side of the line I fall, my major beef with the LLMs is their wanton extractive consumption of human labor  <em>without citation</em> or, god forbid, <em>recompense</em>. Of course, a time honored tradition of slave traders and capitalists. Here is Marc Andreesen with a recent plea written to the US copyright office, hopeful we can just all ignore this blatant theft for the common good of the funder class. This is <a href=\"https://www.businessinsider.com/marc-andreessen-horowitz-ai-copyright-2023-11\">class warfare</a>:</p>\n<p>&gt; Imposing the cost of actual or potential copyright liability on the creators of AI models will either kill or significantly hamper their development.</p>\n<p>I hold that citation is feminist since it combats the authoritative mansplain that obscures collaboration, hardens selfhood, and hoards ideas. Ergo I consider the de-linkified, referent vacuum of effluvium produced by ChatGPT et al as patriarchal in its presentation of &ldquo;knowledge&rdquo; and preoccupation with mastery. I&rsquo;m scare quoting because philosophically I&rsquo;m confused about what this content even <em>is</em>, so unhinged. Although I recognize that the interplay of this text with the reader and their investigative context does produce meaning.</p>\n<p>UPDATE (minutes after the writing the above): heh, Danilo actually expounds generously about the left&rsquo;s false critique of AI in a <a href=\"https://redeem-tomorrow.com/the-average-ai-criticism-has-gotten-lazy-and-thats-dangerous\">long-form piece</a> on his blog.</p>\n",
        "date_published": "2023-11-20T21:32:12-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/11/20/dei-grieving-and-ai-skepticism.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/11/10/lament-for-tafteria-sailing-the.html",
        "title": "Lament for Tafteria: sailing the Apollo's docs",
        "content_html": "<img src=\"https://internetross.space/uploads/2023/the-hospital-ship-martin-bax.png\" alt=\"The hospital ship martin bax\" title=\"the-hospital-ship-martin-bax.png\" border=\"0\" width=\"386\" height=\"600\">\n<p>Documentation, naming things. Hard. Let&rsquo;s see this hardness compound at the intersection of these two phenomena in the real world.</p>\n<p>I&rsquo;m casually scanning the Apollo docs, reading up on subscriptions because my wife is writing graphql client code at work. (I had vague memories of how we worked with distributed event streaming at my last job. NestJS + Kafka. We had consolidated apis into a graphql layer, but worked with Kafka event streams through Nest with the <code>kafka-js</code> lib as a bridge. Point is, I wanted a light refreshment of how this stuff works.).</p>\n<p>It&rsquo;s a frustrating moment to jump between these two pieces of the documentation. (This is supposed to be a <em>mature framework</em> (sobbing, <em>why can&rsquo;t we have nice things</em>)). From <a href=\"https://www.apollographql.com/docs/react/data/subscriptions/#2-initialize-a-graphqlwslink\">2. Initialize a GraphQLWsLink</a> to <a href=\"https://www.apollographql.com/docs/apollo-server/data/subscriptions/#enabling-subscriptions\">Enabling subscriptions</a>.</p>\n<p>The former section, which walks us through client setup, provides a callout with a detour into the server docs for grabbing the connection <em>url</em> we need for configuring and instantiating our web socket linkage.</p>\n<p>&gt; Replace the value of the url option with your GraphQL server&rsquo;s subscription-specific WebSocket endpoint. If you&rsquo;re using Apollo Server, see Setting a subscription endpoint.</p>\n<p>If we are using Apollo&rsquo;s server, then we must pass a <code>url</code> property when creating and instantiating the  <code>GraphQLWsLink</code> object .</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-ts\" data-lang=\"ts\"><span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">wsLink</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#66d9ef\">new</span> <span style=\"color:#a6e22e\">GraphQLWsLink</span>(<span style=\"color:#a6e22e\">createClient</span>({\n  <span style=\"color:#a6e22e\">url</span><span style=\"color:#f92672\">:</span> <span style=\"color:#e6db74\">&#39;ws://localhost:4000/subscriptions&#39;</span>,\n}));\n</code></pre></div><p>HOWEVER, once we hyperlink to the server docs one simply cannot find &ndash; throughout the entire web document &ndash; a mention of &ldquo;endpoint.&rdquo; We&rsquo;re dropped into a section called &ldquo;Enabliing subscriptions&rdquo; &ndash; instruction for setting up the server side bits.</p>\n<p>Let down. Expectations missed. Problematic asymmetry, lack of consistency!</p>\n<p>Repletely kerfuffled, my synapses delivering a reminiscence of Tom Benner&rsquo;s big bird bound <em>Naming Things</em>, and his chapter on Consistency. (This so happens to be one of my favorite dogmas of Better Naming™️.) Well, the Apollo docs demonstrate a similar symptom of bad <em>naming</em>, just like the kinds of bad examples we oft find in code. Join me in considering disparate, hyperlinked documents as analogs to components of a software program that exchange messages. Readers of these texts suffer the bad naming with familiar  symptoms: frustration. Capitalists lose the most with anemic productivity.</p>\n<p>If the hyperlink is a documentation document-as-component api/interface, us readers should be allowed to charismatically move back and forth without being flung out from our flow state like starships intercepted in warp. Perhaps the doc could send me to a subsection of &ldquo;Enabling Subscriptions&rdquo; titled/anchored with &ldquo;Server endpoint&rdquo; (or the like). My instinct is that there&rsquo;s a deeper scoop here.</p>\n<p>Of course, there&rsquo;s an imperfect system to blame. When Trevor Scheer <a href=\"https://github.com/apollographql/apollo-server/commit/f04cb2f1f251f1bc9d82ad395fd520d951c4c0c4\">removed all mention</a> of &ldquo;endpoint&rdquo; in the docs update preparing users for Apollo Server version 3 back in 2021 &ndash; Apollo Server would no longer include inherent support for websocket protocols &ndash; how closely did he collaborate with Stephen Barlow who <a href=\"https://github.com/apollographql/apollo-client/commit/fbd4c253883504553ca41a080bf9d85c7dc6ed21\">initially committed</a> the instructions referencing endpoints a year or so before. Do the people matter? (They do.) And from under whatever constraints they perform these literary efforts. We can wonder, imagine, daydream about the socio-technical system that produces docs for clients and servers, and how the basic capabilities of the web link them together. The bounded contexts. The challenges of producing universal languages, ubiquitous terms across what likely are two disparate teams.</p>\n<p>There are some leaky abstractions, but it&rsquo;s not a total system failure.</p>\n<p>I&rsquo;m reading Bax.</p>\n<p>Dispatches, bulletins, papers, pinned up, spewed about The Hospital Ship.</p>\n<p>Page 15: <em>A chronic shortage of pins to fix up the reports, so that in consequence they blrew away and anyone in the stern of the ship could reach out a hand and collect bulletins from the air as they drifted by in an endless paper-chase over the stern of the boat and on into the sea.\n</em></p>\n<p>Page 98: <em>Did the programmers hope to attract some reply? The <code>Hopeful</code> did not know what replay to make so they transmitted their call signal only, but there was no response.</em></p>\n<p>Euan wants to blame Tafteria, too bad.</p>\n",
        "date_published": "2023-11-10T13:26:04-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/11/10/lament-for-tafteria-sailing-the.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/10/31/clojure-was-small-typescript-is.html",
        "title": "Clojure was small, TypeScript is big (thinking w/ Dan Vanderkam)",
        "content_html": "<img src=\"https://internetross.space/uploads/2023/midnight-endless-summer.jpg\" alt=\"Midnight endless summer\" title=\"midnight-endless-summer.jpg\" border=\"0\" width=\"600\" height=\"600\">\n<p>The dangers of <em>premature optimization</em> are well understood among software engineers who&rsquo;ve been frustrated by the secondary effects of code that end up compounding maintenance cost. (Does this principle play out in other milieu?).</p>\n<p>Nonetheless, there are times when optimizations are demonstrably beneficial but are difficult to implement because of system-wide or social dynamics that can&rsquo;t or won&rsquo;t accept the optimizations. Here I&rsquo;m thinking with Dan Vanderkam&rsquo;s post from back in September: <a href=\"https://effectivetypescript.com/2023/09/27/closure-compiler/\">The Saga of the Closure Compiler, and Why TypeScript Won</a>.</p>\n<p>Skipping gingerly back through through recent web and computing history, Dan discusses the now obvious demise of Google&rsquo;s Closure compiler, which at the time enjoyed merits of technical achievements in optimization. During it&rsquo;s development in the early aughts, the hardware of the time demanded Closure&rsquo;s designers focus on minification. Dan argues that contemporary typed projects, like Typescript, won&rsquo;t succeed beyond the range of Closure&rsquo;s niche usage on advancements in performance. Typescript must be built with consideration ever-increasingly diversifying ecosystem of tool chains and environments within which it can and will be run. Such as right alongside plain ole dynamically-typed JS in mixed types/non-typed codebases.  Despite the heroic campaigns of developers to slap types on everything &ndash;  see the <code>DefinitelyTyped</code> repo &ndash; the JavaScript multi-verse offers no real guarantees that imports will be typed or not. TypeScripts declared horizon of</p>\n<p>&gt; Be a cross-platform development tool</p>\n<p>must be joined by</p>\n<p>&gt; Emit clean, idiomatic, recognizable JavaScript code</p>\n<p>and further qualified by the <em>non-goal</em> of</p>\n<p>&gt; Aggressively optimize the runtime performance of programs. Instead, emit idiomatic JavaScript code that plays well with the performance characteristics of runtime platforms.</p>\n<p>I wonder how many TypeScript developers have looked at the <a href=\"https://github.com/microsoft/TypeScript/wiki/TypeScript-Design-Goals#non-goals\">TypeScript Design Goals</a>? Not to call out/in, just curious.</p>\n<p>I wonder, the Midnight&rsquo;s 2016 <em>Endless Summer</em>. Saxophone crying out from the other room.</p>\n",
        "date_published": "2023-10-31T11:42:32-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/10/31/clojure-was-small-typescript-is.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/10/30/language-ergonomic-studies-possession-ruby.html",
        "title": "Language ergonomic studies: Possession: Ruby, JavaScript, D/s, Mycology",
        "content_html": "<img src=\"https://internetross.space/uploads/2023/flair-anniston.png\">\n<p>There exist happy little clouds of coincidence when studying new languages. And not just across the computer ones, mind you!</p>\n<p>Ruby and Indonesian share a frugal brevity and disinterest in flairs of punctuation when managing possession.</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-txt\" data-lang=\"txt\">Itu bukuku.\n</code></pre></div><p>vs</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-txt\" data-lang=\"txt\">That&#39;s my book.\n</code></pre></div><p>And&hellip;</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-ruby\" data-lang=\"ruby\">me <span style=\"color:#f92672\">=</span> <span style=\"color:#66d9ef\">Person</span><span style=\"color:#f92672\">.</span>find(my_user_id)\nmy_books <span style=\"color:#f92672\">=</span> me<span style=\"color:#f92672\">.</span>books\n</code></pre></div><p>vs</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-js\" data-lang=\"js\"><span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">me</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#66d9ef\">await</span> <span style=\"color:#a6e22e\">prisma</span>.<span style=\"color:#a6e22e\">user</span>.<span style=\"color:#a6e22e\">findUnique</span>({ \n\t<span style=\"color:#a6e22e\">where</span><span style=\"color:#f92672\">:</span> { \n\t\t<span style=\"color:#a6e22e\">id</span><span style=\"color:#f92672\">:</span> <span style=\"color:#ae81ff\">99</span>, \n\t}, \n\t<span style=\"color:#a6e22e\">include</span><span style=\"color:#f92672\">:</span> { \n\t\t<span style=\"color:#a6e22e\">books</span><span style=\"color:#f92672\">:</span> <span style=\"color:#66d9ef\">true</span> \n\t} \n});\n<span style=\"color:#a6e22e\">myBooks</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">me</span>.<span style=\"color:#a6e22e\">books</span>;\n</code></pre></div><p>Well, Rails AR query syntax vs Prisma (NodeJS). (Also, did I do a useful interpretation of linguistic <em>possession</em> in a soft coding expression??)</p>\n<p>This isn&rsquo;t YAOFJS (Yet Another Opprobrium for JS). I don&rsquo;t have a quarrel with English, either. Although I find it often fairly dull when it&rsquo;s not rescued by the reticulations of regional and immigrant (forced or free) anastomosis of the tongue and mouth (and whatever other maneuvers contribut to nudging the Queen&rsquo;s own verbage (I&rsquo;ve forgotten if there is anything before a body without organs, how is it done???)) that take root in everyday speech.</p>\n<p>Only a mere 30 pages (of 250) into <em>Make the Golf Course a Public Sex Forest</em> and you run headlong into Raechel Anne Jolie&rsquo;s musings on D/s, mushrooms, and mouths. There&rsquo;s probably something here to dwell on with respect to power, colonialism, oral sex, entangelment, Dulcinea Pitagora&rsquo;s &ldquo;subspace&rdquo; in BDSM play (ohhh, wonderful that this term wasn&rsquo;t entirely pre-figured by Roddenberry&rsquo;s universe expanse), etc&hellip;</p>\n<p>Cue Butler&rsquo;s <em>Xenogenesis</em>, ringing in my ears.</p>\n",
        "date_published": "2023-10-30T12:40:21-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/10/30/language-ergonomic-studies-possession-ruby.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/10/25/rspec-vs-js-let-vs.html",
        "title": "Rspec vs js, let vs let",
        "content_html": "<p>Have you noticed that comprehension arrives more quickly when reading comparison pieces that juxtapose the syntaxes, rules, and shibboleths of two programming languages. Steve Hicks' article <em>What JavaScript Tests Could Learn From RSpec</em> is one such example.</p>\n<p>My preference when writing tests is to keep re-assigning and re-using variables to a minimum. Localize them as close to the assertions as possible. Beware of cross-contamination. Pollination. Sexual interops.</p>\n<p>Recreating a lazy-evaluated <code>let</code>-style block in JS, Hicks performs some clever scoping  gymnastics which makes me nervous. The declarations of <code>calculator</code>, <code>first</code>, and <code>second</code> feel visually and temporally far-flung from usage.</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-js\" data-lang=\"js\"><span style=\"color:#a6e22e\">describe</span>(<span style=\"color:#e6db74\">&#34;Calculator&#34;</span>, () <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n  <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">calculator</span>\n  <span style=\"color:#a6e22e\">beforeEach</span>(() <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; { <span style=\"color:#a6e22e\">calculator</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#66d9ef\">new</span> <span style=\"color:#a6e22e\">Calculator</span>() })\n\n  <span style=\"color:#a6e22e\">describe</span>(<span style=\"color:#e6db74\">&#34;.multiply&#34;</span>, () <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n    <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">first</span>, <span style=\"color:#a6e22e\">second</span>\n    <span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">getResult</span>() {\n      <span style=\"color:#66d9ef\">return</span> <span style=\"color:#a6e22e\">calculator</span>.<span style=\"color:#a6e22e\">multiply</span>(<span style=\"color:#a6e22e\">first</span>, <span style=\"color:#a6e22e\">second</span>)\n    }\n\n    <span style=\"color:#a6e22e\">describe</span>(<span style=\"color:#e6db74\">&#34;when the first value is negative&#34;</span>, () <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n      <span style=\"color:#a6e22e\">beforeEach</span>(() <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; { <span style=\"color:#a6e22e\">first</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#f92672\">-</span><span style=\"color:#ae81ff\">1</span> })\n\n      <span style=\"color:#a6e22e\">describe</span>(<span style=\"color:#e6db74\">&#34;when the second value is negative&#34;</span>, () <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n        <span style=\"color:#a6e22e\">beforeEach</span>(() <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; { <span style=\"color:#a6e22e\">second</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#f92672\">-</span><span style=\"color:#ae81ff\">3</span> })\n\n        <span style=\"color:#a6e22e\">it</span>(<span style=\"color:#e6db74\">&#34;returns a positive number&#34;</span>, () <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n          <span style=\"color:#a6e22e\">expect</span>(<span style=\"color:#a6e22e\">getResult</span>()).<span style=\"color:#a6e22e\">toEqual</span>(<span style=\"color:#ae81ff\">3</span>)\n        })\n      })\n\n      <span style=\"color:#a6e22e\">describe</span>(<span style=\"color:#e6db74\">&#34;when the second value is positive&#34;</span>, () <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n        <span style=\"color:#a6e22e\">beforeEach</span>(() <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; { <span style=\"color:#a6e22e\">second</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#ae81ff\">3</span> })\n\n        <span style=\"color:#a6e22e\">it</span>(<span style=\"color:#e6db74\">&#34;returns a negative number&#34;</span>, () <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n          <span style=\"color:#a6e22e\">expect</span>(<span style=\"color:#a6e22e\">getResult</span>()).<span style=\"color:#a6e22e\">toEqual</span>(<span style=\"color:#f92672\">-</span><span style=\"color:#ae81ff\">3</span>)\n        })\n      })\n    })\n  })\n})\n</code></pre></div><p>This doesn&rsquo;t really bother me though:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-js\" data-lang=\"js\"><span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">sharedVar</span>;\n\n<span style=\"color:#a6e22e\">before</span>(() <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n  <span style=\"color:#a6e22e\">sharedVar</span> <span style=\"color:#f92672\">=</span> ...\n})\n\n<span style=\"color:#a6e22e\">describe</span>(() <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n  <span style=\"color:#a6e22e\">it</span>(() <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n    <span style=\"color:#a6e22e\">sharedVar</span> <span style=\"color:#f92672\">=</span> ...\n  })\n})\n</code></pre></div><p>Is rspec <code>let</code> better than JS <code>let</code>?</p>\n<p>Even rspec maintainers caution us, Hicks notes. Convenience always carries a caveat in programming. This is a substantial pillar of the &ldquo;readability&rdquo; discussion: durability of convenience.</p>\n<p>&gt; Note: let can enhance readability when used sparingly (1,2, or maybe 3 declarations) in any given example group, but that can quickly degrade with overuse. YMMV.</p>\n<p>Cool find: <a href=\"https://github.com/enova/givens\">givens</a>. Shoutout to the translators, the transcribers, the interpreters.</p>\n",
        "date_published": "2023-10-25T11:57:43-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/10/25/rspec-vs-js-let-vs.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/07/04/with-annemarie-willis-professor-of.html",
        "title": "With Anne-Marie Willis, professor of design theory at the German University in Cairo.",
        "content_html": "<p>Another world is possible. But what of worlding? How to world?</p>\n<p>When a Farley&rsquo;s barista is a strong current; wow the level of shine escaping her mouth. And I loved it. The slightest tickle of maple syrup was a great recommendation!</p>\n<p>Per usual I sent myself something to read and didn&rsquo;t cite the source so I&rsquo;ve been having that weird kind of drifty, but tethered, Pong ball experience. Was it mentioned by someone in a Paper in Systems discussion? Maybe a content of the fediverse&rsquo;s systems thinkers briefly held in place by my thumb.</p>\n<p>As I like to say (with often different verses), I do software development because it&rsquo;s a phenomenological wonder of people, text, code, time travel, non-determinism &ndash; and always pluckily avoids fitting neatly into capitalist fetish.</p>\n<p>Like, software <em>projects</em> (already &ldquo;bad&rdquo; (incomplete, inaccurate) lexicon) of any substantial scope are only delivered on time accidentally.</p>\n<p>Frederica Frabetti supports this axiomatic <em>chiste</em> of software, noting in her book <em>Software Theory</em>:</p>\n<p>&gt; &ldquo;The central problem of software development is thus the impossibility of following a sure path in which a system is completely and exhaustively specified <em>before</em> it can be realized.&rdquo;</p>\n<p>and</p>\n<p>&gt; &ldquo;Stability is something that <em>happens</em> to the system, rather than being scheduled and worked towards.&rdquo;</p>\n<p>Look how software was virtually helpless to build complex systems that are designed to become <em>eventually consistent</em>.</p>\n<p>For me, software is philosophical-ing. An ontological milieu. Therefore Willis' essay is soooo good for those of us who are philosophical-ing, but not academically trained &ndash; and who can drift into this kind of theoretical reasoning easily, especially in an essay like <em>Ontological Designing</em> which onboards us you into hardcore theory with a ton of grace. Willis doesn&rsquo;t need to spend her initial breaths on defining &ldquo;ontological&rdquo; and and Heidegger&rsquo;s &ldquo;being&rdquo;, and (re)introducing us to the failure of the <em>Western</em> metaphysical tradition. But she is generous; and that&rsquo;s likely the point. A broader appeal.</p>\n<p>Which, in turn, helps the mind Pong around during an essay about pervasive push and pull.</p>\n<p>I&rsquo;m reading this essay about how we effect social change but also thinking through the systems reasoning and how it vibrates into software ontology. Well, there are references to IT infrastructure and other &ldquo;equipment&rdquo; of our present epoch &ndash; though they do not supersede other kinds of equipment. For Willis, our contemporary technologies can function both as examples of any designed material, as well as juxtapose with the immaterial (organizational structures, administrative systems, etc&hellip;) to demonstrate how they are equivalent as objects/outcomes of the ontological design circularity/looping, bi-directional reach &ndash; Heidegger&rsquo;s grabbing Cartesian dualism by the shoulders and shaking them.\n(&ldquo;Ontological designing refuses such one dimensional understandings of (human) being-in-the-world, which are worn-out fragments of enlightenment thinking and Christian morality sloppily stitched together.&quot;) As Willis notes, Heidegger themself reaches for the simple household jug to work with in his pursuit of how <em>things, thing</em>.</p>\n<p>&gt; &ldquo;The jug gathers and unites these.&rdquo;</p>\n<p>These being: water, wine, sky, earth. Gathered/outpoured.</p>\n<p>But she talks about tech in a way that tickles, for sure. Especially it&rsquo;s excess as it frenetically infinite loops rather than unlocks potential:\n&gt; Rather than inducing us into a world of multiple creative possibilities (as software advertisers would have it), [computers] design us as users into their horizons of possibility &ndash; which by the very nature of horizons (in Gadamer&rsquo;s sense) always have a limit. In fact, the proliferation of options within even a basic operating system or software application becomes a tyranny of choice, a maze of seemingly endless possibilities, a dazzling instrumentation for its own sake, all means with no end in sight.&rdquo;</p>\n<p>Maybe free software never will be truly free.</p>\n<img src=\"https://internetross.space/uploads/2023/farley-mug.webp\" width=\"600\" height=\"600\" alt=\"\">\n",
        "date_published": "2023-07-04T15:03:38-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/07/04/with-annemarie-willis-professor-of.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/06/08/naur-goodies-years-after-jesus.html",
        "title": "Naur, goodies, 1985 years after Jesus Christ",
        "content_html": "<p>There are so many goodies in Naur, 1985. Filter, some():</p>\n<ul>\n<li>Declares there&rsquo;s no right way to write software</li>\n<li>(Further) rebukes the scientific method</li>\n<li>Calls out lack of empirical study of software methods</li>\n<li>The programmer as &ldquo;manager&rdquo; of computer activity</li>\n</ul>\n<p>Thank you ceejbot for <a href=\"https://blog.ceejbot.com/posts/programming-as-theory-building/\">further distillations</a>.</p>\n",
        "date_published": "2023-06-08T09:29:54-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/06/08/naur-goodies-years-after-jesus.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/06/08/naur-the-optimist-years-after.html",
        "title": "Naur, the optimist, 1985 years after Jesus Christ",
        "content_html": "<p>The year is 1985. Certain kinds of optimism abound in programming circles. From Peter Naur&rsquo;s Programming as Theory Building:</p>\n<blockquote>\"It may be noted that the need for revival of an entirely dead program probably will rarely arise, since it is hardly conceivable that the revival would be assigned to new programmers without at least some knowledge of the theory had by the original team.\" </blockquote> \n<p>The infamous &ldquo;shit mouse&rdquo; bug that I pushed to production in 2018 &ndash; which subsequently became an iconic team joke with its own concomitant laptop sticker swag &ndash; was the direct result of software abandoned in the wake of absconding team members. Picking up dust-laden software seems like a common occurrence these days, no?</p>\n<p>In their <em>reading-with</em> of Naur, Ceejbot <a href=\"https://blog.ceejbot.com/posts/programming-as-theory-building/\">offers</a> a valuable remediation technique for deleterious  knowledge vacancies. It&rsquo;s one that I personally strive for in everyday software practice: gross amounts of maintainer documentation.</p>\n<p>&gt; Don’t waste time documenting what can be seen through simple reading. Document why that function exists and what purpose it serves in the software. When might I call it? Does it have side effects? Is there anything important about the inputs and outputs that I might not be able to deduce by reading the source of the function? All of those things are clues about the thinking of the original author of the function that can help their successor figure out what that author’s theory of the program was.</p>\n<p>and</p>\n<p>&gt; &hellip;the program exists to solve a problem, some “affair of the world” that Naur refers to. What was that problem? Is there a concise statement of that problem anywhere? What approach did you take to solving that problem statement? What tradeoffs did you make and why? What values did you hold as you made those tradeoffs? Why did you organize the source code in that particular way? What belongs where?</p>\n",
        "date_published": "2023-06-08T08:56:20-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/06/08/naur-the-optimist-years-after.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/06/06/power-moves.html",
        "title": "Power Moves",
        "content_html": "<p>During her novel workshop on estate planning, Sarah Deluca of Move Money Shift Power poses the question:</p>\n<p><em>Is holding onto control after your death something you want?</em></p>\n<p>If part of our life&rsquo;s work is to strengthen connection, relinquish power, share power, redistribute, does a Trust actually violate the moves we&rsquo;ve been making at the speed of small &ldquo;t&rdquo; trust? Individualistic posthumous scheming is not the invention of communities, but of corrupted powerfuls. It would seem.</p>\n<p>A few days later I found myself in the next Paper in Systems discussion led by Dawn Ahukanna and Shauna Gordon-McKeon. On the table was Shauna&rsquo;s essay <em>Interpretive Labor: Bridging the Gap Between Map and Territory</em>. Wherein you&rsquo;ll find a rich investigation &ndash; and then interrogation &ndash; of the lopsided power distribution between those that labor to imagine, construct models, maps, and those that sit with the effects of the implementation &ndash; who interpret, navigate, bridge the chasm between theory and material outcomes.</p>\n<p>I was called in. Software engineers do wield an outsized power from behind the desk. Although the tower isn&rsquo;t deathly bleached, because 1) we do some interpretive labor at the seam between business requirements and software building (system design, theory of, code/text writing), and 2) failures reverberate back to us pretty hard (midnight pages) &ndash; at least more acutely than through the beauracratic layers. (Do the capitalists get to feel much of anything?) Nonetheless, we probably aren&rsquo;t the ones screaming during the scream test. What do we do with this power?</p>\n<figure>\n<img src=\"https://internetross.space/uploads/2023/3f903ee582.png\" width=\"402\" height=\"600\" alt=\"Jorge Luis Borges self portait\">\n    <figcaption>Jorge Luis Borges - Self Portrait</figcaption>\n</figure>\n",
        "date_published": "2023-06-06T06:00:51-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/06/06/power-moves.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2023/04/29/can-you-jam-with-the.html",
        "title": "Can you jam with the console cowboys in cyberspace?",
        "content_html": "<p>No. You can&rsquo;t. Not yet.</p>\n<p>It&rsquo;s quite possible that my work in computers today is a last ditch to actualize a childhood fantasy of solving neighborhood crimes with my friends in Brooklyn with the help of a friendly ghost that communicates via word processor. You type, then we type, Ghostwriter.</p>\n<p>The way she caresses the monitor in this scene: longingly, tenderly, expectant. The arrogant gush of buzzwords. Unalloyed after school cool.</p>\n<img src=\"https://internetross.space/uploads/2023/3b291aa203.jpg\" width=\"374\" height=\"374\" alt=\"\">\n",
        "date_published": "2023-04-29T09:44:02-07:00",
        "url": "https://softlydeveloping.micro.blog/2023/04/29/can-you-jam-with-the.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2022/01/08/redis-poem-set-things-set.html",
        
        "content_html": "<h1 id=\"redis-poem\">Redis Poem</h1>\n<p>set things <br>\nset them to expire <br>\nset them to be exclusive <br>\nset them to expire, be exclusive</p>\n<p>(inspired by a chat with mike b)</p>\n",
        "date_published": "2022-01-08T00:22:45-07:00",
        "url": "https://softlydeveloping.micro.blog/2022/01/08/redis-poem-set-things-set.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2021/01/24/wellknown-ways-that-javascript-coerces.html",
        "title": "Well-known ways that JavaScript coerces objects to strings",
        "content_html": "<p>One typical practice of your everyday software developer building commercial computer programs is to add logs alongside code at important relay nexuses &ndash; where the code does valuable things. Logs are typically composed of data and a message that meaningfully describe a moment in the system&rsquo;s operation during it&rsquo;s lifetime. There are a handful of reasons to surface information this way: producing audit trails for legal compliance, gathering product insights, performance profiling, or collecting debug traces for quality monitoring. Generally logs are a benign additive to your running programs, although they are notoriously risky as vectors where private user data may be &ldquo;leaked&rdquo; &ndash; serialized unencrypted. Perhaps a lesser-known trickiness of composing and handling logs, one that I find compelling enough to write about here, is the unpredictability of what happens when you try to serialize more complex data structures when writing in a  dynamically typed language like JavaScript. Because logs are namely messages that need to be formatted for transport across system boundaries, out from your system to other systems, the act of stuffing objects, arrays, maps, sets, etc&hellip; into a message string is fraught. Let&rsquo;s consider this in some depth.</p>\n<p>Logs capture a Good-Enough Facsimile<sup>™️</sup> of the current state of the world for later analysis<sup>1</sup>. This likely means grabbing the subject of the current operation that might appear like  <code>context.currentUser</code> as well as other supporting actors like the session context and properties of the objects being acted upon by the current user &ndash; then bundling these properties as an object. Sometimes the object being acted upon is the current user&rsquo;s own data. Then we have a funky transmigration of Subject/Object.</p>\n<p>Why don&rsquo;t we clasp hands and skip through a hallucination together into a fantasy e-commerce example where we can explore logging and value coercion of a canonical <em>Order</em> class. Let&rsquo;s start with the following modest invention which terraforms a theoretical backend piece of a prescription drug dispenser. And let&rsquo;s imagine that, from time to time, orders that come into this shop become <em>stuck</em> during the fulfillment process. Insurance claims may be rejected, the doctor or pharmacist discovers a conflict between the patient&rsquo;s health attributes and the meds. In such a scenario, this code attempts a fully-automated retry of the unstuck order, and in due course, at important nexuses, passes relevant contextual data to log handlers. From there other bots or real-life persons can take over.</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-js\" data-lang=\"js\"><span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">oldestStuckOrder</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#66d9ef\">await</span> <span style=\"color:#a6e22e\">query</span>(<span style=\"color:#a6e22e\">orders</span>, { <span style=\"color:#a6e22e\">filter</span><span style=\"color:#f92672\">:</span> <span style=\"color:#e6db74\">&#39;oldest_stuck&#39;</span> });\n<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">logData</span> <span style=\"color:#f92672\">=</span> {\n\t<span style=\"color:#a6e22e\">order</span><span style=\"color:#f92672\">:</span> <span style=\"color:#a6e22e\">oldestStuckOrder</span>,\n\t<span style=\"color:#a6e22e\">userInfo</span><span style=\"color:#f92672\">:</span> { ... },\n\t<span style=\"color:#a6e22e\">sessionInfo</span><span style=\"color:#f92672\">:</span> { ... },\n};\n<span style=\"color:#a6e22e\">logger</span>.<span style=\"color:#a6e22e\">info</span>(<span style=\"color:#e6db74\">`Start resolving stuck order: </span><span style=\"color:#e6db74\">${</span><span style=\"color:#a6e22e\">logData</span><span style=\"color:#e6db74\">}</span><span style=\"color:#e6db74\">`</span>);\n<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">reason</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">determineStuckReason</span>(<span style=\"color:#a6e22e\">oldestStuckOrder</span>);\n\n<span style=\"color:#66d9ef\">if</span> (<span style=\"color:#a6e22e\">reason</span>) {\n\t<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">result</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">resolveStuckOrder</span>(<span style=\"color:#a6e22e\">oldestStuckOrder</span>, <span style=\"color:#a6e22e\">reason</span>);\n\t<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">logDataWithResult</span> <span style=\"color:#f92672\">=</span> {\n\t\t...<span style=\"color:#a6e22e\">logData</span>,\n\t\t<span style=\"color:#a6e22e\">reason</span>,\n\t\t<span style=\"color:#a6e22e\">result</span>,\n\t};\n\t<span style=\"color:#a6e22e\">logger</span>.<span style=\"color:#a6e22e\">info</span>(<span style=\"color:#e6db74\">`Finished resolving stuck order: </span><span style=\"color:#e6db74\">${</span><span style=\"color:#a6e22e\">logDataWithResult</span><span style=\"color:#e6db74\">}</span><span style=\"color:#e6db74\">`</span>);\n} <span style=\"color:#66d9ef\">else</span> {\n\t<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">logDataWithReason</span> <span style=\"color:#f92672\">=</span> {\n\t\t...<span style=\"color:#a6e22e\">logData</span>,\n\t\t<span style=\"color:#a6e22e\">reason</span>,\n\t}\n\t<span style=\"color:#a6e22e\">logger</span>.<span style=\"color:#a6e22e\">error</span>(<span style=\"color:#e6db74\">`Unable to resolve stuck order: </span><span style=\"color:#e6db74\">${</span><span style=\"color:#a6e22e\">logDataWithReason</span><span style=\"color:#e6db74\">}</span><span style=\"color:#e6db74\">`</span>);\n}\n</code></pre></div><p>There are three points in this code where I&rsquo;m sending an aforementioned warned-about complex object into a logger service which only accepts a single string argument. In this scenario, the devs want the logger API as simple and straightforward as can be: unary and stringy. I hope this code reads naturally, that it&rsquo;s similar to something you&rsquo;ve seen before. And&hellip;hopefully your gears are turning already and you are starting to see with me 𓁿; and you are beginning to feel awkward 🙇🏻‍♂️ about what representation for <code>oldestStuckOrder</code> or <code>logDataWithReason</code> that this gussied-up <code>console</code> function will likely display. Won&rsquo;t interpolating complex objects inside a template string implicitly coerce the object into the obstinately churlish <code>[object Object]</code>?</p>\n<p>JavaScript is funky-beautiful because it is dynamically typed. It grants you the freedom to smush\nvalues of mismatched types into the <em>same  computational</em> context and your program won&rsquo;t\ncrash, resulting in stuckness on stuckness. JavaScript has loose assumptions loosely held.</p>\n<p>We often take this for granted when we write JavaScript. We also often exploit\nit for good. Conscious or not, you are probably already familiar with the types of common\ncomputational contexts where the language affords this failsafe. Here&rsquo;s a general breakdown:</p>\n<ul>\n<li>expressions using arithmetic operators</li>\n<li>comparison operators</li>\n<li>text expressions (<code>if</code> statements, the second clause of a <code>for</code> loop handler, the first clause of a ternary operator)</li>\n<li>interpolated strings.</li>\n</ul>\n<p>That last one is case in point. We can send an object into a string context &ndash; <code>Finished resolving stuck order: ${logDataWithResult}</code> &ndash; and get something workable out the other end:</p>\n<pre tabindex=\"0\"><code>const logDataWithResult = {\n\tprop: 'prop',\n\tanotherProp: 'anotherProp',\n};\nconsole.log(`Finished resolving stuck order: ${logDataWithResult}`);\n// =&amp;gt; Finished resolving stuck order: [object Object]\n</code></pre><p>And there it is. Workable (quite generously). The famed proterozoic, bracketed\nnotation of familiar churlish conceit and &ldquo;bad parts&rdquo; motifs. Obviously this not\nthe best guess we hope the engine to make when executing our logging function &ndash;\nwe have lost all that rich order and user data! Our compliance trail is\nmeaningless. But we shouldn&rsquo;t despair quite yet. I&rsquo;m happy to share that\nJavaScript exposes many an API for developers to control the return value of\ndynamic type conversions. If JavaScript is anything, it&rsquo;s a fairly &ldquo;open&rdquo; language.\nNot necessarily open for expansion to the extent of, say, Clojure&rsquo;s macros. But\nall things being mutable objects (with a few untouchable properties) and a\nhandful of scalar values, you have a good deal of freedom. For coercing objects\nto string, the most famous method is probably <code>toString()</code>. In fact, JavaScript\ndogfoods its own <code>toString()</code> for object -&gt; string conversion automatically in\nall those common contexts we listed above. Whenever</p>\n<p>&gt; the object is to be represented as a text value or when an object is referred to in a manner in which a string is expected\n&gt; &ndash; MDN <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString/contributors.txt\">contributors</a></p>\n<p>Like between backticks.</p>\n<p>Now, if a fellow developer in our dream of a drug shop codebase has not already\ncome along and monkey-patched the <code>Order</code> object&rsquo;s <code>toString()</code> method, the\ndefault conversion algorithm rules defined for <code>Object.prototype.toString()</code>\nfrom the ECMAScript® 2021 spec section 19.1.3.6 will kick in. The algorithm is\nactually pretty easy to understand; though here&rsquo;s to hoping your browser of\nchoice actually follows these rules. I invite you for a glance:</p>\n<p><a href=\"https://tc39.es/ecma262/#sec-object.prototype.tostring\"><img src=\"https://internetross.space/uploads/2021/66e3d2ae1b.png\" height=\"384\" alt=\"\"></a></p>\n<p>Can you see where <code>[object Object]</code> comes from? If the unfamiliar dialect is a bit intimidating for your casual Sunday morning read, here&rsquo;s what the above algorithm would like if we implemented it in JavaScript<sup>4</sup>:</p>\n<pre tabindex=\"0\"><code>import { SecretInternals } from 'secret-internals';\n\nconst internalSlotsToTagMap = {\n  ParameterMap: &quot;Arguments&quot;,\n  Call: &quot;Function&quot;,\n  ErrorData: &quot;Error&quot;,\n  BooleanData: &quot;Boolean&quot;,\n  NumberData: &quot;Number&quot;,\n  StringData: &quot;String&quot;,\n  DateValue: &quot;Date&quot;,\n  RegExpMatcher: &quot;RegExp&quot;,\n}\n\nfunction toString(value) {\n  if (value === undefined) return '[object Undefined]';\n  if (value === null) return `[object Null]`;\n\n  let builtinTag;\n  const innerValue = innerValue = SecretInternals.Object.box(value);\n  const isArray = isArray(innerValue);\n\n  if (isArray) {\n    builtinTag = 'Array';\n  } else {\n    for (const [key, value] of Object.entries(internalSlotsToTagMap)) {\n      if (SecretInternals.Object.hasInternalSlot(innerValue, key)) {\n        builtinTag = value;\n      }\n    }\n  }\n\n  if (!builtinTag) {\n    builtinTag = 'Object';\n  }\n\n  const tag = SecretInternals.Object.get(innerValue, '@@toStringTag');\n\n  if (tag !== string) {\n    tag = builtinTag\n  }\n\n  return `[object ${tag}]`;\n}\n</code></pre><p>For <em>actual</em> objects, not object-like things (Arrays), the algorithm falls through to step 14 where a temporary referent called <code>builtInTag</code> receives the value <code>Object</code>. This <em>built in tag</em> is later used as the second part of the converted argument value.</p>\n<blockquote>I had a JavaScript joke but it’s [object Object] — Greg Meyer (@grmeyer)</blockquote>\n<p>Despite the sarcastic jabs from the peanut gallery, what else would we expect\nthe language to do. JavaScript&rsquo;s unintentional emissions were designed for a\nplatform that projects them through UIs for consumption by masses of retinas of\nhuman people &ndash; it&rsquo;s Good Enough. The language keeps your program running with a\ntype guess and leaves the contents of your value alone. It doesn&rsquo;t take drastic\nmeasures and radically\nunpack and/or serialize your contents to JSON (what compute or privacy costs might\nlurk!); or try to set the <em>built in tag</em> to the left-hand side of the\nlast variable assignment statement: what a drastic move, the language doesn&rsquo;t\nwork this way: variable names are not synonymous with types! Variable assignment\nis void of any tautological binding! JavaScript just lets you take matters into\nyour own hands.</p>\n<p>Until very recently I wasn&rsquo;t aware of any techniques beyond an Object&rsquo;s built-in <code>toString()</code> property to futz around with type conversions. But apparently there are a few modern well-known Symbols<sup>5</sup> that have entered the language to help. I&rsquo;ve compiled an example with four different APIs I could track down. Any of these would play nicely for logging libraries, though the last only works in node, and there are nuances to each that you must consider for your use case.</p>\n<pre tabindex=\"0\"><code>// 1. Override toString() (js, node)\nclass Chicken {\n  toString() {\n    return '🐓';\n  }\n}\n\nvar chicken = new Chicken();\nconsole.log(`${chicken}`); // 🐓\n\n// 2. Symbol.toStringTag (js, node)\nclass Chicken {\n  get [Symbol.toStringTag]() {\n    return '🐓';\n  }\n}\n\nlet chicken = new Chicken();\nconsole.log(`${chicken}`); // [object 🐓]\n\n// 3. Symbol.toPrimitive (js, node)\nclass Chicken {\n  [Symbol.toPrimitive](hint) {\n    switch (hint) {\n      case 'number':\n      case 'string':\n      case 'default':\n        return '🐓';\n      default:\n        return null;\n    }\n  }\n}\n\nlet chicken = new Chicken();\nconsole.log(`${chicken}`); // 🐓\n\n// 4. util.inspect.custom (node)\nconst inspect = Symbol.for('nodejs.util.inspect.custom');\nconst util = require('util');\n\nclass Chicken {\n  [inspect]() {\n    return '🐓';\n  }\n}\n\nconst chicken = new Chicken();\nconsole.log(chicken); // 🐓\nconsole.log(`${chicken}`); // [object Object]\nutil.inspect(chicken) // 🐓\n</code></pre><p>I haven&rsquo;t formally surveyed this, but I can report anecdotally that of my current team of ~25 engineers who work on a universal JavaScript application, overriding <code>toString()</code> is the most commonly preferred strategy. My sneaking suspicion is that many JavaScript developers are not aware of the more contemporary <code>Symbol</code> methods/properties, even though these methods have been available in major browsers/node for ~4-5 years. Or maybe it&rsquo;s simply a matter of many backend devs coming to backend JS from other languages and server environs. From what I understand, node has just started to finally emerge in the past few years as fit-enough for prod. JavaScript is vast territory, quickly expanding, in multiple runtimes &ndash; it takes years.</p>\n<p>As for <code>nodejs.util.inspect.custom</code>, I haven&rsquo;t been around  node land long enough to know if its usage is idiomatic.</p>\n<p>Still, preference for <code>toString()</code> may not simply be an issue of keeping up with the JS Joneses. As shown above, the outcomes of these different strategies are not identical. What&rsquo;s more, to layer on the complexity, these options aren&rsquo;t wholly independent. In fact, JavaScript combines these strategies together under the hood. Did you notice what was going on in step 15 of the conversion algorithm above? The spec requires that  <code>Object.prototype.toString</code> looks up the <code>@@toStringTag</code> symbol property on the object &ndash; these symbol members are in the DNA sequence now. When we take control back, understanding the spec is quite key: we can avoid mistakes like combining these two options since overriding <code>toString()</code> always take precedence. For example:</p>\n<pre tabindex=\"0\"><code>class Chicken {\n  get [Symbol.toStringTag]() {\n    return 'Base 🐓';\n  }\n\n  toString() {\n    return 'This is a 🐓';\n  }\n}\n\nclass JungleChicken extends Chicken {\n  get [Symbol.toStringTag]() {\n    return 'Jungle 🐓';\n  }\n}\n\nconst chicky = new Chicken();\nconst jungleChicky = new JungleChicken();\n\nconsole.log(`${chicky}`);\nconsole.log(`${jungleChicky}`);\n// =&amp;gt; This is a 🐓\n// =&amp;gt; This is a 🐓\n</code></pre><p>However, say I were interested in simply <em>tagging</em> the string representation of my object to protect exposing its value contents, and still present a semantically rich identifier to consumers. This would help us express a desire to maintain the default bracket output &ndash; <code>[Object..]</code> &ndash; with the prepended &ldquo;object&rdquo; type to maintain some consistency with how objects are stringified in our code. In that case, leveraging the well-known <code>Symbol.toStringTag</code> property would be the way to go. For example, the following logger from our e-commerce imaginary might obscure private user data like this:</p>\n<pre tabindex=\"0\"><code>// .../jsonapi/resources/user.js\nclass User {\n\tget [Symbol.toStringTag]() {\n\t\treturn `User ${this.id}`;\n\t}\n}\n\n// Somewhere else...\nlogger.error(`Unable to resolve stuck order: ${logDataWithReason}`);\n// Unable to resolve stuck order:\n// {\n//  \torder: {...},\n//\t\tuserInfo: [object User:123456],\n//\t\tsessionInfo: {...},\n// };\n</code></pre><p>Your next option, empowering even more fined-grained control, is adding a <code>Symbol.toPrimitive</code> method to your object. <code>Symbol.toPrimitive</code> is a main line into the runtime&rsquo;s coercion processing. After playing around a bit in a browser and a node repl, I&rsquo;ve noticed that this Symbol will precede over a provided <code>toString()</code> override.</p>\n<pre tabindex=\"0\"><code>class Chicken {\n  toString() {\n    return 'This is a 🐓';\n  }\n\n  get [Symbol.toStringTag]() {\n    return '🐓';\n  }\n\n  [Symbol.toPrimitive](hint) {\n    switch (hint) {\n      case 'number':\n      case 'string':\n      case 'default':\n        return 'This is a 🐓 primitive';\n      default:\n        return null;\n    }\n  }\n}\n\nconst chicky = new Chicken();\nconsole.log(`${chicky}`)\n// =&amp;gt; This is a 🐓 primitive\n</code></pre><p>By using <code>Symbol.toPrimitive</code>, you&rsquo;re basically instructing the runtime to <em>LOOK HERE</em> for all its object coercion preferences. What&rsquo;s more, beyond <code>Symbol.toStringTag</code>&rsquo;s mere label augmentation, you get a powerful indirection<sup>2</sup> to handle all primitive type coercion scenarios<sup>1</sup>. You&rsquo;re also overriding internal language behavior which &ndash; I was surprised to learn &ndash; effectively resolves how to order the calls for <code>Object.prototype.toString()</code> and <code>Object.prototpye.valueOf()</code>. Flip to section 7.1.1 of the spec to see how the <code>ToPrimitive</code> abstraction is designed to call a further nested <code>OrdinaryToPrimitive</code> abstraction for decision-making:</p>\n<p><a href=\"https://tc39.es/ecma262/#sec-ordinarytoprimitive\"><img src=\"https://internetross.space/uploads/2021/0d11e430d2.png\" height=\"316\" alt=\"\"></a></p>\n<p>Translated for comfort:</p>\n<pre tabindex=\"0\"><code>import { SecretInternals } from 'secret-internals';\n\nfunction ordinaryToPrimitive(object, hint) {\n  if (SecreteInternals.isObject(object)) {\n    throw TypeError;\n  }\n\n  if (hint !== 'string' || hint !== 'number') {\n    throw TypeError;\n  }\n\n  let methodNames = [];\n\n  if (hint === 'string') {\n    methodNames = ['toString', 'valueOf'];\n  }\n\n  if (hint === 'number') {\n    methodNames = ['valueOf', 'toString'];\n  }\n\n  for (methodName of methodNames) {\n    if (SecreteInternals.isCallable(methodName)) {\n      const result = SecreteInternals.call(object, methodName);\n\n      if (SecreteInternals.isNotObject(result)) {\n        return result;\n      }\n    }\n  }\n\n  throw TypeError;\n}\n</code></pre><p>I think I like the idea of using these <a href=\"https://tc39.es/ecma262/#table-well-known-symbols\"><em>well-known</em> symbols</a> for custom object -&gt; string representations, if for the collision protection alone.<sup>3</sup> What would it be like to reach for the powerhouse of <code>Symbol.toPrimitive</code> to hijack the runtime from eventually calling through to <code>Object.prototype.toString()</code>. Furtive, conspiratorial whispers to the interpreter 🤫. Even a partially implemented reducer will do, as I demonstrate above in my chicken example above: the switch statement can gracefully sidestep other type hint cases and only target the string hint case. But is grabbing for <code>Symbol.toPrimitive</code> overkill?  <code>toString()</code> is tried and true and a pristine greenfield function block without arrogant &ldquo;hints&rdquo; and a naive switch statement without <em>pattern matching</em> 🙄 (are we <a href=\"https://github.com/tc39/proposal-pattern-matching\">there</a> yet?). Could there be non-trivial DX cost of confusing other developers if the other primitive case statements are fall throughs?</p>\n<hr>\n<p><sup>1: Whenever I think about how software tries to capture its own understanding of the world it creates, I&rsquo;m brought back to systems thinkers like jessitron:</p>\n  <blockquote><a href=\"https://jessitron.com/2019/05/18/distance-outside-of-maps/\">\"We don’t expect the world to have perfect consistency. Yet we wish it did, so we create facsimiles of certainty in our software.</a></blockquote>\n  <blockquote><a href=\"https://jessitron.com/2020/01/24/capturing-the-world-in-software/\">It’s impossible to model the entire world. Completeness and consistency are in conflict, sadly. Still, if we limit “complete” to a business domain, and to the boundaries of our company, this is possible. Theoretically.</a></blockquote>\n</sup>\n<p><sup>2: By &ldquo;indirection&rdquo; I really mean to invoke Zachary Tellman&rsquo;s exegesis of semantic drifts in software industry lexicons from his book <em>Elements of Clojure</em>. His work is a really nice refinement:</p>\n  <blockquote>Indirection provides separation between <em>what</em> and <em>how</em>. It exists wherever \"how does this work?\" is best answered, \"it depends.\" This separation is useful when the underlying implementation is complicated or subject to change. It gives us the freedom to change incidental details in our software while maintaining its essential qualities. It also defines the layers of our software; indirection invites the reader to stop and explore no further. It tells us when we're allowed to be incurious.</blockquote>He goes on to discuss that conditionals are one of two primary devices to achieve successful indirections (the other being <em>references</em>). Conditionals are effective because they contain ordered, \"closed\" decision-making mechanisms that avoid conflicts; in contrast to tables with indivduated keys.\n  <blockquote>Conditionals solve conflicts by making an explicit, fixed decision. Where conflicts are possible, we use conditionals <em>because</em> they are closed. </blockquote>\n</sup>\n<p><sup>3: That&rsquo;s the primary purpose of these Symbols. For a deeper  <a href=\"c\">Support util.inspect.custom as a public symbol #20821</a> on GitHub. </sup></p>\n<p><sup>4: Try not to think too hard about the implications of a JS interpreter written in JS. But, ya know, Atwood&rsquo;s law; you will, not surprisingly, find JS interpreters for JS out there, many built on Acorn, which, is itself, a parser written in JS. Man alive!</sup></p>\n<p><sup>5: I&rsquo;m bemused and betwixed by this use of &ldquo;well-known.&rdquo; Does anyone know the origin of this qualifier?</sup></p>\n",
        "date_published": "2021-01-24T15:57:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2021/01/24/wellknown-ways-that-javascript-coerces.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/11/08/language-ergonomic-studies-summing-ranges.html",
        "title": "Language ergonomic studies: Summing ranges and most frequent terms",
        "content_html": "<p>Pennies per day (by day count) in Clojure:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-clojure\" data-lang=\"clojure\">(<span style=\"color:#66d9ef\">defn </span>pennyPerDay [numDays]\n  (reduce + (range <span style=\"color:#ae81ff\">1</span> (+ numDays <span style=\"color:#ae81ff\">1</span>)))\n)\n\n(<span style=\"color:#a6e22e\">pennyPerDay</span> <span style=\"color:#ae81ff\">30</span>)\n</code></pre></div><p>Pennies per day (by day count) in JS:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">pennyPerDay</span>(<span style=\"color:#a6e22e\">numDays</span>) {\n  <span style=\"color:#66d9ef\">return</span> Array(<span style=\"color:#f92672\">++</span><span style=\"color:#a6e22e\">numDays</span>)\n    .<span style=\"color:#a6e22e\">fill</span>(<span style=\"color:#ae81ff\">0</span>)\n    .<span style=\"color:#a6e22e\">reduce</span>((<span style=\"color:#a6e22e\">sum</span>, <span style=\"color:#a6e22e\">_</span>, <span style=\"color:#a6e22e\">i</span>) <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">sum</span> <span style=\"color:#f92672\">+</span> <span style=\"color:#a6e22e\">i</span>, <span style=\"color:#ae81ff\">0</span>);\n}\n\n<span style=\"color:#a6e22e\">pennyPerDay</span>(<span style=\"color:#ae81ff\">30</span>);\n</code></pre></div><p>Most frequent terms in JS:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">termList</span> <span style=\"color:#f92672\">=</span> [<span style=\"color:#e6db74\">&#39;term1&#39;</span>, <span style=\"color:#e6db74\">&#39;term2&#39;</span>, <span style=\"color:#e6db74\">&#39;term3&#39;</span>, <span style=\"color:#e6db74\">&#39;term3&#39;</span>];\n<span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">mostFrequentTerms</span>(<span style=\"color:#a6e22e\">arr</span>) {\n  <span style=\"color:#66d9ef\">return</span> <span style=\"color:#a6e22e\">arr</span>.<span style=\"color:#a6e22e\">reduce</span>((<span style=\"color:#a6e22e\">result</span>, <span style=\"color:#a6e22e\">curr</span>) <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; {\n    <span style=\"color:#a6e22e\">result</span>[<span style=\"color:#a6e22e\">curr</span>] <span style=\"color:#f92672\">=</span> <span style=\"color:#f92672\">++</span><span style=\"color:#a6e22e\">result</span>[<span style=\"color:#a6e22e\">curr</span>] <span style=\"color:#f92672\">||</span> <span style=\"color:#ae81ff\">1</span>\n    <span style=\"color:#66d9ef\">return</span> <span style=\"color:#a6e22e\">result</span>;\n  }, {})\n}\n  \n<span style=\"color:#a6e22e\">mostFrequentTerms</span>(<span style=\"color:#a6e22e\">termList</span>);\n</code></pre></div><p>Most frequent terms in a list with Clojure:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-clojure\" data-lang=\"clojure\">(<span style=\"color:#66d9ef\">def </span>term-list [<span style=\"color:#e6db74\">:term1</span> <span style=\"color:#e6db74\">:term2</span> <span style=\"color:#e6db74\">:term3</span> <span style=\"color:#e6db74\">:term3</span>])\n(<span style=\"color:#66d9ef\">defn </span>most-freq-terms <span style=\"color:#e6db74\">\\[</span>terms<span style=\"color:#e6db74\">\\]</span>\n  (<span style=\"color:#a6e22e\">-</span><span style=\"color:#f92672\">&amp;</span>gt<span style=\"color:#75715e\">;&amp;gt; terms</span>\n       frequencies\n       (sort-by val)\n       reverse))\n(<span style=\"color:#a6e22e\">most-freq-terms</span> term-list)\n</code></pre></div>",
        "date_published": "2020-11-08T21:01:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/11/08/language-ergonomic-studies-summing-ranges.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/09/30/zoom-doomed.html",
        "title": "Zoom Doomed",
        "content_html": "<p>Not a day goes by when I don&rsquo;t witness the over signifying of &ldquo;meeting&rdquo;. &ldquo;Meeting&rdquo; invokes a collective sigh for laborers since a better way seems a fairy tale. As a consequence, possibilities for elevated communication are damaged. But a meeting is so much more:</p>\n<p>&gt; Calling the coordinated exchange of messages or moderated access to shared material (like a blackboard) a <em>conference</em> or <em>meeting</em> seems to neglect a factor that is rather important in meetings. Often the explicit exchange of messages is relatively unimportant compared with the development of social relations in the group of participants that happens simply by the fact that they are close to each other as humans for a while.\n&gt;\n&gt; <footer><small><cite>Perspectives and Metaphors for Human-Computer Interaction</cite>, Susanne Maaß  and Horst Oberquelle</small></footer></p>\n<p>Thus, we may be Zoom doomed. Perhaps. We need to hire facilitators and train our people in facilitation. It&rsquo;s a technical skill that most technologists lack, profoundly.</p>\n",
        "date_published": "2020-09-30T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/09/30/zoom-doomed.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/09/09/not-so-byzantine-algorithm-studies.html",
        "title": "Not so byzantine algorithm studies: Using math to deliver your medication",
        "content_html": "<p>Like many commercial software developers, math plays a more sporadic role in my day-to-day work. That said, I certainly wouldn&rsquo;t blithely demote <em>knowing math</em> below other techs like programming languages, web frameworks, and principles of software design/architecture; which already sets up a false dichotomy, anyway.</p>\n<p>Math presents a beautiful core proposition to software developers. Through its powers of abstracting and reducing real-world dynamics into expressable, repeatable, sequential logic &ndash; which we can be lifted easily into our favorite coding grammars &ndash; math can be the companion dynamo we need for achieving levels of faithful verisimilitude for real world complexities (Keep It Savvy Stupid).</p>\n<p>Italicizing <em>knowing math</em> is totally an intentional problematization to mess with the idea that <em>knowing math</em> is narrowly scoped to demonstrating technical prowess of calculation or proofing. I think software engineers can, and should, consider a relationship with math as knowing <em>enough</em> math; like, an ontological relationship with math&rsquo;s formalism and general principles. <em>Math The Good Parts</em>, so to speak. Otherwise the bravado of equating math and problem solving or math as &ldquo;hard&rdquo; (dick) science of some kind is doomed to engender an axiomatic blur that will gate keep devs who are not deemed fit for lack of educational background or interest in fiddling with greek letters. Keep these gates wide open, por favor!</p>\n<p>(I also think the focus on calculation in my early schooling, alienated from everyday material uses, made me quite <em>Meursault</em> for it &ndash; perhaps why I don&rsquo;t feel the need to champion for being mathy. It took entering commercial software life much later in life to see how the dynamo helps us make stuff and therefore able to consider embracing math (and being embraced by math) again.)</p>\n<p>Our praxis: we can coopt <em>knowing math</em> to ramify similar to our desire for Senior Engineers™ to be T-shaped with their knowledge of the stack in order that they can press more heavily on architecture and design. For example, we can desire for React developers to:</p>\n<ul>\n<li>Understand just enough graph theory to <em>see</em> component architectures as graphs;</li>\n<li>Understand the implications of data pipelining and message passing in a graph (bonus points for being a student of Christopher Alexanders' semilattices)</li>\n<li>Or understand just enough category theory to understand the heritage and benefits of composability of first-class functions &ndash; is JS even fun without a bit of FP? What else?</li>\n</ul>\n<p>This is all just to say that some business problems map really well to higher-order maths and devs should be prepared for it, at least through the design phase. Again, once we sit down to write code, we can easily offload the fastidious implementation details; those few lines of copy|paste from the math deep state.</p>\n<p>For example, take a common e-commerce retail problem like Distributed Order Management (DOM). Modern omnichannel selling combined with cloud computing open a broad field of possibilities to achieve low-cost order fulfillment. Affine cost structures &ndash; resulting from variable/variadic shipping dynamics &ndash; will increase complexity as an ecommerce company scales. We&rsquo;re talking about quite a bit of real-world complexity to model and adapt to.</p>\n<p>What, then, when we&rsquo;re tasked to create an algorithm to satisfice a version of this problem where you have these rough requirements:</p>\n<ol>\n<li>Orders must be completely fulfilled</li>\n<li>There will be variant shipping costs per supplier</li>\n<li>Orders can be <em>fully splittable</em> by a supplier</li>\n</ol>\n<p>This kind of thing will break your brain once you start to grasp for a rational boundary to contain the argument ramifications: supplier availability, supplier inventory availability, etc&hellip;</p>\n<p>I was presented with a challenge like this recently and it took me a couple hours just to understand what this problem domain was; like, find my way to DOM through off-by-one google searches; a true StumbleUpon revival. Because I didn&rsquo;t know the math well-enough yet. Google is pretty fast though, and within minutes I practically broke out in a sweat after discovering multiple long-winded computer science papers written on the topic filled with intimidating mathy notations. Then more OMGs and <em>mon dieu</em>s as I careened sharply into Cantor&rsquo;s theorem and Set Theory. Wait, am I doing math? <em>Oh mersault!</em></p>\n<p>More and more it seemed a fantasy that I&rsquo;d be capable of solving Amazon within a reasonable amount of time because this gestalt was increasing aggressively. Nonetheless, after some deep breaths and patience recoup and having worked with enough devs without math experience, I began to inculcate to this world and realize any solve was going to be an approximation of some sort and probably wouldn&rsquo;t require me to crack open a text book; there was no silver bullet or excavation of secret proofs. Rather, this whole class of optimization maximations applied to fulfillment problems is a rigorous academic field, but when it meets the metal it softens and warms for <a href=\"https://en.wikipedia.org/wiki/Principle_of_good_enough\">Good Enough™️</a> programming. Each potential brute force linear assignment or dynamic programming algorithm was discarded. My inputs couldn&rsquo;t be structured into a decision table or cost matrix amenable to path finding, traversal, or Cartesian production. Which meant I could rule out potentials like Kuhn&rsquo;s Hungarian algorithm. In fact, the scope was something more akin to a <em>set cover</em> or networking problem &ndash; still a brave new world, but less and less unbounded the more I scoured the web. Ulimately, my task was gonna be something toward imagining <em>all</em> probabilities between order items and suppliers, and then reducing these matches against cost constraints. &ldquo;All probabilities&rdquo; was a strong clue.</p>\n<p>So, a bit surprisingly for someone not used to needing math everyday &ndash; and certainly not trying to fuck with this:</p>\n<figure>\n<img src=\"https://internetross.space/uploads/2020/89e27c7784.png\" alt=\"Fully splittable\" title=\"fully_splittable.png\" border=\"0\" width=\"600\" height=\"199\">\n<figcaption><center><small>Eq. (5a) ensures every order is fulfilled, and (5b) limits service provided by a store.</small></center></figcaption>\n</figure>\n<p>I soon found myself drifting at a comfortable altitude through Probability and Combinatorics with the help of other cow path pavers &ndash; we are community-taught developers, after all! &ndash; crafting a studied, yet heuristic, approach from where I could thread my inputs through techs like combinations and permutations to make some educated guesses.</p>\n<p>The general step-rules of algorithm gradually accreted into something resembling following:</p>\n<ol>\n<li>Generate all possible combinations of order items\n<ul>\n<li>Order items are unique, therefore we are working with a Set. We can therefore use a mathematical definition of a Powerset and create a function which outputs a set of all subsets of any set <em>S</em>:</li>\n</ul>\n<pre class=\"language-javascript\"><code>powerset([A, B, C]) === [[A], [B], [A, B], [C], [A, C], [B, C], [A, B, C]];</code></pre>\n</li>\n<li>Generate all possible combinations of combinations order items that are less than or equal to the number of suppliers\n<ul>\n<li>Effectively take the result of the Step 1 as the input Set for another powerset that only returns combinations of order item splits that can be fulfilled by available suppliers. For two suppliers:</li>\n</ul>\n<pre class=\"language-javascript\"><code>powersetBySize(powerset([A, B, C]), 2) ===\n  [\n    [[\"A\"]],\n    [[\"B\"]],\n    [[\"A\"], [\"B\"]],\n    [[\"A\", \"B\"]],\n    [[\"A\"], [\"A\", \"B\"]],\n    [[\"B\"], [\"A\", \"B\"]],\n    [[\"C\"]],\n    [[\"A\"], [\"C\"]],\n    [[\"B\"], [\"C\"]],\n    [[\"A\", \"B\"], [\"C\"]],\n    [[\"A\", \"C\"]],\n    [[\"A\"], [\"A\", \"C\"]],\n    [[\"B\"], [\"A\", \"C\"]],\n    [\n      [\"A\", \"B\"],\n      [\"A\", \"C\"],\n    ],\n    [[\"C\"], [\"A\", \"C\"]],\n    [[\"B\", \"C\"]],\n    [[\"A\"], [\"B\", \"C\"]],\n    [[\"B\"], [\"B\", \"C\"]],\n    [\n      [\"A\", \"B\"],\n      [\"B\", \"C\"],\n    ],\n    [[\"C\"], [\"B\", \"C\"]],\n    [\n      [\"A\", \"C\"],\n      [\"B\", \"C\"],\n    ],\n    [[\"A\", \"B\", \"C\"]],\n    [[\"A\"], [\"A\", \"B\", \"C\"]],\n    [[\"B\"], [\"A\", \"B\", \"C\"]],\n    [\n      [\"A\", \"B\"],\n      [\"A\", \"B\", \"C\"],\n    ],\n    [[\"C\"], [\"A\", \"B\", \"C\"]],\n    [\n      [\"A\", \"C\"],\n      [\"A\", \"B\", \"C\"],\n    ],\n    [\n      [\"B\", \"C\"],\n      [\"A\", \"B\", \"C\"],\n    ],\n  ];\n</code></pre>\n</li>\n<li>Generate all permutations of suppliers</li>\n<li>Generate all viable <em>routes</em> by matching between the sized combinations of order items (result of Step 2) to supplier permutations (result of Step 3)\n<ul>\n<li>Basically a fancy zipping computation</li>\n</ul>\n</li>\n<li>Filter viable routes against both superficial and business constraints like like duplicated suppliers and supplier availability and/or inventory</li>\n<li>Compute the lowest cost route!</li>\n</ol>\n<p>Now there&rsquo;s a well-suited mathy modeling!</p>\n<p><strong>Some other thoughts</strong></p>\n<p>Combinatoric applications for this algorithm are quite expensive: you can see how the cardinality flourishes pretty fast above, and my example is for a modest 3 order items and 2 suppliers. If those numbers increase by any measure CPU will be tremendously exercised. (I believe the runtimes of these functions may be polynomial?) I can see why optimization becomes an attractively ripe apple for academicians. Quickly glossing, I can imagine optimizing the looping functions to break before completion when satsificing within a range of acceptance criteria; or structuring the data as Iterators and/or piping through transducers to minimize space complexity with lazy or eager techniques.</p>\n<p>By the way, JS has pretty underwhelming options for combinatorics. I found one <a href=\"https://github.com/dankogai/js-combinatorics\">library</a> that I found a bit awkward to use and ended up ditching in favor of a few standalone implementations of <code>powerset</code> and <code>permutations</code> so I could ensure the code would comply with how I was trying to express the above heuristic. Unsurprisingly, Python&rsquo;s <code>itertools</code> has combinatoric functions built in and even provides recipes for common tooling you can build on primitives like <code>permutations()</code> and <code>combinations()</code>. For example, <code>powerset()</code>.</p>\n<pre class=\"language-python\"><code>def powerset(iterable):\n    \"powerset([1,2,3]) --&gt; () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)\"\n    s = list(iterable)\n    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))\n</code></pre>\n<p>Or simply import the blessed <code>more-itertools</code> library. Of course, this is expected for Python which is heavily developed for the data science world.</p>\n",
        "date_published": "2020-09-09T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/09/09/not-so-byzantine-algorithm-studies.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/09/07/the-loss-of-logical-purity.html",
        "title": "The loss of logical purity primacy",
        "content_html": "<figure>\n<img src=\"https://internetross.space/uploads/2020/a8f0ecd5f0.jpg\" alt=\"MV5BN2NhZTg0MDgtMTc5ZC00MGQxLThhNzEtYmE5ZjRiMzI5ZTcyXkEyXkFqcGdeQXVyMjUyNDk2ODc V1\" title=\"MV5BN2NhZTg0MDgtMTc5ZC00MGQxLThhNzEtYmE5ZjRiMzI5ZTcyXkEyXkFqcGdeQXVyMjUyNDk2ODc@._V1_.jpg\" border=\"0\" width=\"599\" height=\"337\">\n<figcaption><center><small>Femi Ogunbanjo &amp; Hanne Klintoe, 1999, <em>The Loss of Sexual Innocence</em></small></center></figcaption>\n</figure>\n<p>Back in February, my entire notion of <em>expertise</em> and how experts make decisions became cracked after listening to episode 169 of the <em>Greater than Code</em> podcast. While the podcast is rolling I&rsquo;m discovering my socialized construction of <em>expert</em> &ndash; like we pump and grow some kind of muscled query power of an expanding brain-database over time. And that combined with a trained analytical rigor gained through extensive tutelage, study, and practice.</p>\n<p>I&rsquo;m struck by how neo-classical cyberpunk-capitalist fantasy that notion sounds: a techno-positivist outcome of brain as database; the privileging of expertise as accumulation. The time-value of memory perhaps.</p>\n<p>It&rsquo;s kind of wild: wondering about what sort of instinct decision-making really <em>is</em> in concrete terms. Thankfully we have the &gt;Code crew to help us navigate Decision Theory from the safety of our own home. The podcast panelists offer a different notion attributed to Gary Klein&rsquo;s work <em>Sources of Power: How People Make Decisions</em>. Rein&rsquo;s paraphrasing of this more probable notion for quick decision under time pressure situations in our business environs:</p>\n<p>&gt; Expertise is an act of rapid mental simulation without formal analysis based on previous experience. It&rsquo;s more akin to &ldquo;instinct&rdquo; than a cartesian scientific methodology.</p>\n<p>Gary Klein calls this model &ldquo;recognition primed decision&rdquo; or <em>RPD</em>. The key is that over time and through experience we continue to enhance our instincts around familiar problems, and replace outdated versions that don&rsquo;t make sense in our newer model of the world. No need to increase disk/head space! Then, when facing a quick-decision moment, we can make a strong guesses. Informed guesses, not overly formal; certainly not grooved to dreams of electric sheep or Moore&rsquo;s law or, by necessity, scholastic architectures of cognition. But not totally informaled, either; we are making smart connections.</p>\n<p>I find RPD comforting as a way to rethink my role as an expert despite fewer than a decade of years practicing my trade: a sophomoric &ldquo;mid-level&rdquo; software engineer. While RPD reveals the distinctions between less experienced and more experienced people &ndash; notably the former&rsquo;s exceeding alacrity to arrive at a first course of action &ndash; RPD is about evolving your pattern matching, identifying the least risky choice, mentally modeling/imagining outcomes (see <a href=\"https://en.wikipedia.org/wiki/Recognition_primed_decision#Variations\">Variations</a>)</p>\n<p>Embracing an RPD notion of expertise can ramify more permissions for less skilled SWEs to face spontaneously emerging decision-making moments in the workplace with less imposter syndrome and tougher felicity. Fellow career middlers, if you have an idea, basically just trust your power of . RPD also beseeches us to expel myths like (quickly riffing): <em>Principal and Staff technologists have reached their eminent station by putting in the time to refine their powers of inspection, analysis, interpretation, evaluation; they&rsquo;ve amassed all the good frameworks, methodologies, and systems into their memory bank; and decisions they make are conclusive (foreclosing, narrowly, the scope of possibility) because of this special toolkit which is wielded though an infallible reason.</em></p>\n<p>Reason and logic might factor into RPD mental simulation, but there&rsquo;s a primacy of imagination and <em>knowing deep down</em>. Strength of will even?</p>\n<p>I am enough. My powers to decide can be totally excellent.</p>\n<p>Of course, that doesn&rsquo;t mean my first guess won&rsquo;t be totally wrong. But hopefully I&rsquo;m not asked to fix something urgent that far exceeds my bounded rationality of this domain; which might ramify harm on real people if the mark is missed, goddess forbid and forgive.</p>\n<p>I did some additional reflection with the &gt;Code community in their Slack on why I was feeling relieved by Klein&rsquo;s ideas (Jessica Kerr hearted this so I&rsquo;m feeling proud to share!):</p>\n<p>&gt; Thanks. This really struck me because I think I have internalized some idea that experts have these academically rigorous approaches to problems where they draw on frameworks and data and tools blah blah to come to conclusions.</p>\n<p>Then Rein chimes in:</p>\n<p>&gt; Yeah, the analytic decision-making mode is what we are taught, but it&rsquo;s not what people actually use, especially in high-pressure situations.</p>\n<p>The me again:</p>\n<p>&gt; Oh right that was the other piece. [Making decisions under] high pressure. Which in corporate culture feels like all the time a lot.</p>\n<p>Then some other folks tried to pivot the conversation to talk about how web tech is not really that high &ldquo;pressure&rdquo; because bad decisions don&rsquo;t kill people or necessarily tank the business immediately. So I continue:</p>\n<p>&gt; I understand where y’all went with that idea of “high pressure.” But even without the kinds of excess you describe — which I’m grateful not to feel at my (fairly spread out) 1000 person company — I still feel like I’m caught up in a heavy stream; not in a surprising or terribly uncomfortable way; but like a tireless machine of ambient conversation between me and my work and my coworkers that is always humming. So maybe “high pressure” in the sense of constant. Day to day I feel coerced into what feels like quick/on-the-spot decision-making, and always on guard for such; and that’s definitely challenging for me.</p>\n<p>&gt; Like, I’m a developer, and I have to make a ton of small decisions all day long when coding. Even medium-sized decisions. (Like the other day deciding whether to coordinate on a revision of a standard component with a team in Spain with similar needs, vs plowing ahead myself because I knew that process may take weeks and I needed output in days). And often these decisions have to happen within a matter of minutes because of the above normal buzz. I think I remember there was another episode where folks talked about how developers make more decisions than CEOs on any given day?</p>\n<p>&gt; I was finding comfort in this idea from Gary Klein because I can consider whatever my instinct draws on in that moment to be a practice of expertise. I can feel like an expert; and without any added insecurity for a lack of analytical rigor, if I had to explain my decision. I usually have confidence in my decisions, but I didn’t have a framing of it as expertness. A framing I was likely lacking, as Rein said, because I’ve been taught a dichotomy between analytical thinking and instinct, where there actually isn’t one; at least as I understand the idea without having read the book yet. But as someone relatively new in the industry — just around 6 years building web — being able to come into expertise or see it forming in my behavior is really nice.</p>\n<p>Earlier today, delving through <em>Software Development and Reality Construction</em>, I was delighted to discover another rebuke to my previous ideas of expertise as analytical reason qua database. It smacked of Klein and I wonder if Reinhard Keil-Slawik is influenced by Klein &ndash; or conversely &ndash; or perhaps they swarm with each other in that world of systems thinking, cybernetics, constructivism, etc&hellip;</p>\n<p>From Keil-Slawik&rsquo;s essay <em>Artifacts in Software Design</em>:</p>\n<img src=\"https://internetross.space/uploads/2020/09857ecfae.png\" alt=\"Reinhard keil slawik insight\" title=\"reinhard-keil-slawik-insight.png\" border=\"0\" width=\"599\" height=\"202\">\n<p>Keil-Slawik argues that expertise &ndash; ie &ldquo;insight&rdquo; &ndash; is an enrichening of &ldquo;understanding.&rdquo; Understanding being a cognitive structure derived from the encounter with our envionrment which mashes up phenomena (physical, etc&hellip;) and circumstance. It&rsquo;s not random access from a <em>brain-as-database</em> that has been populated with arrangements of stuff from &ldquo;out there&rdquo; - outside ourself/mind &ndash; (previous cognitive structures); as if insight is <em>just</em> a result of recall or trial; that smacks of an easy slippage slide into decision paralysis.</p>\n<p>Rather it&rsquo;s:</p>\n<img src=\"https://internetross.space/uploads/2020/025a295bb7.png\" alt=\"Reinhard keil slawik insight 2\" title=\"reinhard-keil-slawik-insight-2.png\" border=\"0\" width=\"598\" height=\"113\">\n<p>This notion seems to gel well with RPD. I wonder if Klein would welcome this cognitive science to explain how we <em>do</em> decisions.</p>\n<p>I&rsquo;m tempted to accept this explanation pro-tem since the thought of unbounded accumulation of stuff in the brain, and lookup at exponential runtime, doesn&rsquo;t satisfactorily explain the reliable guesses of experts under time pressure. This idea finds kinship with Nora Bateson&rsquo;s characterization of sensemaking as Warm Data collection:</p>\n<p>&ldquo;For some reason, you know what it would feel like to put your tongue on the rug — you almost know what it would taste like. You have been gathering the contrasts, comparisons, and differences that give you that sensing since you were born, maybe even through the sense making of prior generations. You have no files for those data.&rdquo; <a href=\"https://norabateson.medium.com/the-squishy-mud-of-warm-data-where-senses-find-senses-6888da67b941\">🚀</a></p>\n<p>Keil-Slawik and kin are proposing the idea of human expertise as an individual construction of meaning, as well as a co-constitutive emergence of our own body/mind wisdom and the &ldquo;external memory&rdquo; of symbols and tools we work with. The latter is an important point because it reinserts the importance of mneumonics as Turing machines, algebra, languages, frameworks, etc&hellip;. This affords us the benefit of a tradeoff: speed of resolution over perfectness. The example Keil-Slawik gives is of the ape who, if taught once to put sticks together to reach a banana, will subsequently devise similar means of combining objects to get the banana &ldquo;without any hesitation&hellip;and any similar situation.&rdquo;</p>\n",
        "date_published": "2020-09-07T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/09/07/the-loss-of-logical-purity.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/08/06/byzantine-algorithm-studies-using-math.html",
        "title": "Byzantine algorithm studies: Using math to reverse an integer",
        "content_html": "<p>Making code do something requires exactness but that doesn&rsquo;t necessarily mean programmers will express grammars with any particular concision or ease. Code is an outcome of social construction, background, perhaps aesthetic desire. Toy code problems reveal the apparatus, for sure. If you ask me to reverse an integer I&rsquo;ll build a world of arrays &ndash; because I like them. Directionality makes me think of traversal, therefore arrays. I also recall the <code>reverse()</code> convenience immediately. However, as a result, I&rsquo;m forced to deploy morphological contortions; which might feel icky for someone derived within an algorithmic hermitage, auto-recursively deriving pleasure therein.</p>\n<div class=\"klipse-js\">\nfunction reverseInt(int) {\n  // STEP 1 - morph\n  let intAsArrayOfStrings = int.toString().split(\"\");\n}\n</div>\n<p>Reversal is now nearby:</p>\n<div class=\"klipse-js\">\nfunction reverseInt(int) {\n  // let intAsArrayOfChars = int.toString().split('')\n<p>// STEP 2 - traverse, recombine\nlet reversedIntString = intAsArrayOfStrings.reverse().join(&quot;&quot;);\n}</p>\n</div>\n<p>All that remains is a second transmogrification back to the initial type and signing:</p>\n<div class=\"klipse-js\">\nfunction reverseInt(int) {\n  // let intAsArrayOfChars = int.toString().split('')\n  // let reversedIntString = intAsArrayOfChars.reverse().join('')\n<p>// STEP 3 - Sign\nlet result = Number(reversedIntString) * Math.sign(num);\n}</p>\n</div>\n<p>But it has come to my attention that a mathy person prefers preservation, whereby the input is arithmetically recombinated with the help of division and multiplication.</p>\n<div class=\"klipse-js\">\nfunction reverseInt(int) {\n  let remainder = 0;\n  let result = 0;\n<p>while (int) {\nremainder = int % 10;\nresult = result * 10 + remainder;\nint = parseInt(int / 10);\n}\nreturn result;\n}</p>\n<p>reverseInt(12345);</p>\n</div>\n<p>But there&rsquo;s no translation from integer to array. No shift. Grammar school level maths instead. I guess this solution exalts type consistency. Perhaps belies an obsession with <code>10</code>? The base binary pair. I can&rsquo;t imagine the benefit of doing that in a commercial software project so it could only be an academic fancy, benchmarked under extreme conditions. It&rsquo;s really clever, though.</p>\n<p>Also, been thinking about <code>slice</code> a lot today. Never stop dreaming:</p>\n<div class=\"klipse-js\">\nlet int = 12345;\nlet intAsStr = int.toString();\nnew Array(intAsStr.length)\n  .fill(null)\n  .map((_, idx) =&gt; intAsStr.slice(-(idx + 1))[0])\n  .join(\"\");\n</div>\n",
        "date_published": "2020-08-06T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/08/06/byzantine-algorithm-studies-using-math.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/07/15/whats-a-bug.html",
        "title": "What's a bug?",
        "content_html": "<p>&gt; &hellip;bugs are interesting and important in themselves: they define the boundary between what is understood and what is not. Hence, they show us where our weaknees are, and provide opportunities for us to learn and grow.\n&gt;\n&gt; <footer><small><cite>Software Development and Reality Construction</cite></small></footer>\n&gt; <footer><small>Ch 5.1: The Denial of Error,  Joseph A Goguen</small></footer></p>\n<p>The rush to fix bugs to recoup customer satisfaction is absolutely necessary when writing for capital. I just worry that without the proper retrospection we won&rsquo;t actually increase our understanding of the software, and therefore the recidivism rate of error will remain constant; or likely increase in the tail wind of growing complexity and entropy.</p>\n",
        "date_published": "2020-07-15T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/07/15/whats-a-bug.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/07/11/recursion-is-too-easy-for.html",
        "title": "Recursion is too easy for writing nested menus in UI",
        "content_html": "<figure>\n  <figcaption><center><small>Hannah Höch, Für ein Fest gemacht (Made for a Party), 1936\nCollage</small></center></figcaption>\n</figure>\n<p>When paired with component-based framework tools and HTML&rsquo;s unordered lists. Since the rendering is done by the framework, we simply need to progressively stack render calls as we traverse the data. Such brutalist Dada.</p>\n<pre><code class=\"language-jsx\">function List({ items }) {\n  return items.map((item) =&gt; (\n    <ul key=\"{item.id}\">\n      <li>{item.name}</li>\n      {item.children &amp;&amp; <list expanded=\"{expanded}\" items=\"{item.children}\"></list>}\n    </ul>\n  ));\n}\n</code></pre>\n",
        "date_published": "2020-07-11T16:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/07/11/recursion-is-too-easy-for.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/07/05/a-recursive-validation-function-with.html",
        "title": "A Recursive Validation Function with User-Defined Exceptions",
        "content_html": "<p>Each time I implement a recursive function when writing practicalities for commercial software, my notional machine of it&rsquo;s behavior is refined. A small list of heuristics continues to amass in memory:</p>\n<ol>\n<li>&ldquo;It&rsquo;s a function that calls itself.&rdquo;</li>\n<li>&ldquo;You make your list of tasks first then start from the last and work your way back up&rdquo; or &ldquo;It&rsquo;s like unpacking a box with other, smaller boxes, with other smaller boxes, with other&hellip;and then only start looking at the boxes from the smallest to the largest, one at a time&rdquo; (🎩👌 Aditya Bhargava&rsquo;s <em>grokking algorithms</em>)</li>\n<li>&ldquo;It&rsquo;s good for building up a list or value, kind of like reduce&rdquo;</li>\n<li>&ldquo;It can be less code but less performant.&rdquo;</li>\n</ol>\n<p>After working on another problem recently that involved deep-diving a nested JavaScript object and executing validations against each level I&rsquo;m adding:</p>\n<p>&gt; &ldquo;Recursion is awkward if you need to break early.&rdquo;</p>\n<p>In my particular case I needed to validate a recursive data structure representing an org chart of Employees <em>and return invalid immediately</em> if the code traversed an Employee with bad data &ndash; extra fields, missing required fields, fields of the wrong type, etc&hellip;.</p>\n<p>Breaking out from a recursive function is not quite as straightforward as you&rsquo;d think. Also, historically I was used to seeing recursive code employed for tasks that wanted the call stack to build up all the way through the data.</p>\n<p>Like, (deep) flattening an array:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">deepFlatten</span>(<span style=\"color:#a6e22e\">nestedArray</span>, <span style=\"color:#a6e22e\">result</span> <span style=\"color:#f92672\">=</span> []) {\n  <span style=\"color:#66d9ef\">for</span> (<span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">element</span> <span style=\"color:#66d9ef\">of</span> <span style=\"color:#a6e22e\">nestedArray</span>) {\n    <span style=\"color:#66d9ef\">if</span> (Array.<span style=\"color:#a6e22e\">isArray</span>(<span style=\"color:#a6e22e\">element</span>)) {\n      <span style=\"color:#a6e22e\">deepFlatten</span>(<span style=\"color:#a6e22e\">element</span>, <span style=\"color:#a6e22e\">result</span>);\n    } <span style=\"color:#66d9ef\">else</span> {\n      <span style=\"color:#a6e22e\">result</span>.<span style=\"color:#a6e22e\">push</span>(<span style=\"color:#a6e22e\">element</span>);\n    }\n  }\n\n  <span style=\"color:#66d9ef\">return</span> <span style=\"color:#a6e22e\">result</span>;\n}\n</code></pre></div><p>Or, fetching a complete set of data from a remote source in chunks:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">async</span> <span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">fetchAll</span>(<span style=\"color:#a6e22e\">params</span>, <span style=\"color:#a6e22e\">all</span> <span style=\"color:#f92672\">=</span> []) {\n  <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">chunk</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#66d9ef\">await</span> <span style=\"color:#a6e22e\">fetch</span>(<span style=\"color:#a6e22e\">params</span>);\n  <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">nextPage</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">chunk</span>.<span style=\"color:#a6e22e\">nextPage</span>;\n  <span style=\"color:#a6e22e\">all</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">all</span>.<span style=\"color:#a6e22e\">concat</span>(<span style=\"color:#a6e22e\">chunk</span>.<span style=\"color:#a6e22e\">data</span>);\n\n  <span style=\"color:#66d9ef\">if</span> (<span style=\"color:#a6e22e\">nextPage</span>) {\n    <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">nextParams</span> <span style=\"color:#f92672\">=</span> { ...<span style=\"color:#a6e22e\">params</span>, <span style=\"color:#a6e22e\">page</span><span style=\"color:#f92672\">:</span> <span style=\"color:#a6e22e\">nextPage</span> };\n    <span style=\"color:#66d9ef\">return</span> <span style=\"color:#66d9ef\">await</span> <span style=\"color:#a6e22e\">fetchAll</span>(<span style=\"color:#a6e22e\">nextParams</span>, <span style=\"color:#a6e22e\">all</span>);\n  }\n\n  <span style=\"color:#66d9ef\">return</span> <span style=\"color:#a6e22e\">all</span>;\n}\n</code></pre></div><p>What I quickly discovered is that just trying to capture and emit an error from a recursive call stack is already a bit funky. Simply returning <code>false</code> in your function doesn&rsquo;t work because calls lower on the stack may return <code>true</code>; and since we&rsquo;re (kind of) &ldquo;building a value&rdquo; it only matters what the final call returns. This approach won&rsquo;t work:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#75715e\">// Will only return false if the last call in the stack returns false\n</span><span style=\"color:#75715e\"></span><span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">validate</span>(<span style=\"color:#a6e22e\">data</span>, <span style=\"color:#a6e22e\">schema</span>) {\n  <span style=\"color:#66d9ef\">for</span> (<span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">item</span> <span style=\"color:#66d9ef\">of</span> <span style=\"color:#a6e22e\">data</span>) {\n    <span style=\"color:#66d9ef\">for</span> (<span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">rule</span> <span style=\"color:#66d9ef\">of</span> <span style=\"color:#a6e22e\">schema</span>) {\n      <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">field</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">item</span>[<span style=\"color:#a6e22e\">rule</span>.<span style=\"color:#a6e22e\">name</span>];\n      <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">required</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">rule</span>.<span style=\"color:#a6e22e\">required</span>;\n\n      <span style=\"color:#66d9ef\">if</span> (<span style=\"color:#a6e22e\">required</span> <span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">amp</span>;<span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">amp</span>; <span style=\"color:#f92672\">!</span><span style=\"color:#a6e22e\">field</span>) <span style=\"color:#66d9ef\">return</span> <span style=\"color:#66d9ef\">false</span>;\n\n      <span style=\"color:#75715e\">// Recurse\n</span><span style=\"color:#75715e\"></span>      <span style=\"color:#66d9ef\">if</span> (Array.<span style=\"color:#a6e22e\">isArray</span>(<span style=\"color:#a6e22e\">field</span>)) {\n        <span style=\"color:#a6e22e\">validate</span>(<span style=\"color:#a6e22e\">field</span>, <span style=\"color:#a6e22e\">schema</span>);\n      }\n    }\n  }\n\n  <span style=\"color:#66d9ef\">return</span> <span style=\"color:#66d9ef\">true</span>;\n}\n</code></pre></div><p>Using recursion is more like a leap of faith - you are handing over control to the JS engine over an unbounded data set; it&rsquo;s quite reminiscent to the manner in which higher order functions operate with Array and Object collections. For example, <code>forEach</code> is a powerful and declarative alternative to <code>for</code> and <code>for..of/in</code> loops until you find yourself needing to skip over an iteration or break out of the loop. Keywords like <code>continue</code> and <code>break</code> are unavailable in Array and Object collection methods &ndash; these are <em>closed</em> iterators.</p>\n<p>Your only recourse in a recursive function is relying on outer calls &ndash; since the call stack is LIFO - to set that flag and pass it through each stack layer. So capturing and emitting an error from your recursive function might look like this:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">validate</span>(<span style=\"color:#a6e22e\">data</span>, <span style=\"color:#a6e22e\">schema</span>, <span style=\"color:#a6e22e\">errors</span> <span style=\"color:#f92672\">=</span> []) {\n  <span style=\"color:#66d9ef\">for</span> (<span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">item</span> <span style=\"color:#66d9ef\">of</span> <span style=\"color:#a6e22e\">data</span>) {\n    <span style=\"color:#66d9ef\">for</span> (<span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">rule</span> <span style=\"color:#66d9ef\">of</span> <span style=\"color:#a6e22e\">schema</span>) {\n      <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">field</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">item</span>[<span style=\"color:#a6e22e\">rule</span>.<span style=\"color:#a6e22e\">name</span>];\n      <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">required</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">rule</span>.<span style=\"color:#a6e22e\">required</span>;\n\n      <span style=\"color:#66d9ef\">if</span> (<span style=\"color:#a6e22e\">required</span> <span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">amp</span>;<span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">amp</span>; <span style=\"color:#f92672\">!</span><span style=\"color:#a6e22e\">field</span>) {\n        <span style=\"color:#a6e22e\">errors</span>.<span style=\"color:#a6e22e\">push</span>(<span style=\"color:#a6e22e\">error</span>);\n      }\n\n      <span style=\"color:#75715e\">// Recurse\n</span><span style=\"color:#75715e\"></span>      <span style=\"color:#66d9ef\">if</span> (Array.<span style=\"color:#a6e22e\">isArray</span>(<span style=\"color:#a6e22e\">field</span>)) {\n        <span style=\"color:#a6e22e\">validate</span>(<span style=\"color:#a6e22e\">field</span>, <span style=\"color:#a6e22e\">schema</span>, <span style=\"color:#a6e22e\">errors</span>);\n      }\n    }\n  }\n\n  <span style=\"color:#66d9ef\">return</span> <span style=\"color:#a6e22e\">errors</span>;\n}\n</code></pre></div><p>If our program requirements suggest we want to parse the entire org chart for bad data, this function will give us a result array we can further process to report errors. But for my purpose, there&rsquo;s too big a potential cost of unnecessary runs while a large call stack is cleared for a large org chart.</p>\n<p>In order to stop processing the org chart and return an <em>invalid</em> result early, we need a solution that stops execution entirely when the invalid check is entered in the outermost call. Alas, the solution ends up being rather elegant and simple, though counter-intuitive. Rather than returning (false, an error list, etc&hellip;), you can <em>throw</em> and thereby forcibly halt the engine&rsquo;s execution of the code. Here&rsquo;s an example with <code>throw</code>:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">validate</span>(<span style=\"color:#a6e22e\">data</span>, <span style=\"color:#a6e22e\">schema</span>) {\n  <span style=\"color:#66d9ef\">for</span> (<span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">item</span> <span style=\"color:#66d9ef\">of</span> <span style=\"color:#a6e22e\">data</span>) {\n    <span style=\"color:#66d9ef\">for</span> (<span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">rule</span> <span style=\"color:#66d9ef\">of</span> <span style=\"color:#a6e22e\">schema</span>) {\n      <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">field</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">item</span>[<span style=\"color:#a6e22e\">rule</span>.<span style=\"color:#a6e22e\">name</span>];\n      <span style=\"color:#66d9ef\">let</span> <span style=\"color:#a6e22e\">required</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">rule</span>.<span style=\"color:#a6e22e\">required</span>;\n\n      <span style=\"color:#75715e\">// It&#39;s even one less character to write! 🤣\n</span><span style=\"color:#75715e\"></span>      <span style=\"color:#75715e\">// Also now we have total control over the exception content\n</span><span style=\"color:#75715e\"></span>      <span style=\"color:#66d9ef\">if</span> (<span style=\"color:#a6e22e\">required</span> <span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">amp</span>;<span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">amp</span>; <span style=\"color:#f92672\">!</span><span style=\"color:#a6e22e\">field</span>) <span style=\"color:#66d9ef\">throw</span> <span style=\"color:#66d9ef\">new</span> <span style=\"color:#a6e22e\">MissingFieldError</span>(<span style=\"color:#a6e22e\">item</span>, <span style=\"color:#a6e22e\">rule</span>);\n\n      <span style=\"color:#75715e\">// Recurse\n</span><span style=\"color:#75715e\"></span>      <span style=\"color:#66d9ef\">if</span> (Array.<span style=\"color:#a6e22e\">isArray</span>(<span style=\"color:#a6e22e\">field</span>)) {\n        <span style=\"color:#a6e22e\">validate</span>(<span style=\"color:#a6e22e\">field</span>, <span style=\"color:#a6e22e\">schema</span>);\n      }\n    }\n  }\n\n  <span style=\"color:#66d9ef\">return</span> <span style=\"color:#66d9ef\">true</span>;\n}\n</code></pre></div><p>Day in, day out we work constantly with client applications that only trhow as a result of unintended bugs in the program. But we can take advantage of this standard JavaScript behavior and erect an appropriate error boundary. Remember:</p>\n<p>&gt; Execution of the current function will stop (the statements after throw won&rsquo;t be executed), and control will be passed to the first catch block in the call stack. <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw\">🔗</a></p>\n<p>Therefore we can rename and wrap our recursive function that throws, and put it inside an error boundary to achieve that early break we want. This approach even comes with the added advantage of declaring the content of our <em>user-defined exception</em> at throw site; eg, utilizing meaningful error constructors or factories like <code>missingFieldError()</code>.</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">validate</span>(<span style=\"color:#a6e22e\">data</span>, <span style=\"color:#a6e22e\">schema</span>) {\n  <span style=\"color:#66d9ef\">try</span> {\n    <span style=\"color:#a6e22e\">validateInner</span>(<span style=\"color:#a6e22e\">data</span>, <span style=\"color:#a6e22e\">schema</span>);\n  } <span style=\"color:#66d9ef\">catch</span> (<span style=\"color:#a6e22e\">error</span>) {\n    <span style=\"color:#75715e\">// returns new MissingFieldError()!\n</span><span style=\"color:#75715e\"></span>    <span style=\"color:#66d9ef\">return</span> <span style=\"color:#a6e22e\">error</span>;\n  }\n  <span style=\"color:#66d9ef\">return</span> <span style=\"color:#66d9ef\">true</span>;\n}\n</code></pre></div><p>Even more, the elegance of this design with an outer try/catch allows for separate testing of our validation business logic &ndash; the rules against which bad data throw &ndash; and error handling &ndash; what errors we emit for certain cases.</p>\n",
        "date_published": "2020-07-05T15:51:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/07/05/a-recursive-validation-function-with.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/06/16/debugging-ts-in-vscode-and.html",
        "title": "Debugging TS in VSCode and Russel Ackhoff's Problem Treatments",
        "content_html": "<p>During a global pandemic and massive civil rights upheaval, as I drift between jobs I tease away some time from protest and anti-racist organizing to study programming basics. I plunge below the membranes of web frameworks. The first thing you notice when sitting down to write some code is the brutal lack of the full-featured dev environment you had on the job.</p>\n<p>I had a serious moment of angst this morning about whether I could achieve debugging for TypeScript files in VSCode within a reasonable amount of time &ndash; that is, an amount of time that wouldn&rsquo;t deplete all my creative energy before I could even write a single little char. To my very pleasant surprise this was much easier than expected. You need two things.</p>\n<ol>\n<li>Add a task to run the compiler in watch mode (this is totally boilerplate):</li>\n</ol>\n<pre tabindex=\"0\"><code>{\n  &quot;version&quot;: &quot;2.0.0&quot;,\n  &quot;tasks&quot;: [\n    {\n      &quot;type&quot;: &quot;typescript&quot;,\n      &quot;tsconfig&quot;: &quot;tsconfig.json&quot;,\n      &quot;option&quot;: &quot;watch&quot;,\n      &quot;problemMatcher&quot;: [&quot;$tsc-watch&quot;],\n      &quot;group&quot;: &quot;build&quot;,\n      &quot;label&quot;: &quot;tsc: watch - tsconfig.json&quot;\n    }\n  ]\n}\n</code></pre><ol>\n<li>Add your outfiles (dist) target glob to your launch.json file:</li>\n</ol>\n<pre tabindex=\"0\"><code>{\n  // Use IntelliSense to learn about possible attributes.\n  // Hover to view descriptions of existing attributes.\n  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n  &quot;version&quot;: &quot;0.2.0&quot;,\n  &quot;configurations&quot;: [\n    {\n      &quot;name&quot;: &quot;Launch server.js via nodemon&quot;,\n      &quot;type&quot;: &quot;node&quot;,\n      &quot;request&quot;: &quot;launch&quot;,\n      &quot;runtimeExecutable&quot;: &quot;nodemon&quot;,\n      &quot;program&quot;: &quot;${file}&quot;,\n      &quot;restart&quot;: true,\n      &quot;console&quot;: &quot;integratedTerminal&quot;,\n      &quot;internalConsoleOptions&quot;: &quot;neverOpen&quot;,\n      &quot;runtimeArgs&quot;: [&quot;--experimental-modules&quot;],\n      &quot;outFiles&quot;: [&quot;${workspaceFolder}/out/**/*.js&quot;] // &amp;lt;-- ADD YOUR OUTFILES GLOB HERE\n    }\n  ]\n}\n</code></pre><p>And voila, here I am pausing on a breakpoint:</p>\n<img src=\"https://internetross.space/uploads/2020/d2e47c2f87.gif\">\n<p><em>Ok new topic&hellip;</em></p>\n<p>During episode 138 of the <a href=\"https://www.greaterthancode.com/how-we-learn\">&gt; Code podcast</a> with guest Vaidehi Joshi of BaseCS podcast fame, amongst many other things, the discussion veers into the topic of problem solving ~20:30. Jamey and Vaidehi riff about that condition we all know and love, and never seem to appreciate enough, whereby solutions come to you while away from the computer. While your brain is &ldquo;percolating&rdquo; (Jamey) or in a &ldquo;mental marinade&rdquo; (Vaidehi). Jacob Stoebel chimes in describing another common mental turnabout we programmers do: when we catch ourselves down a rabbit hole trying to <em>solve</em> (big &ldquo;S&rdquo;) the problem with our first instinct and the increasingly deeper and muddier slog forcing us back up for air, whence we pause, shake off the adrenaline, and climb out of the hole to wonder: how do I just get rid of this problem zone entirely? Rein, per usual, picks up the thread and introduces the panel/listeners to a theorist named Russell Ackoff who minted a classification for approaches to problems called &ldquo;Problem Treatments,&rdquo; which includes the concept of &ldquo;dissolution&rdquo; that applies to Jacob&rsquo;s case.</p>\n<p>To list and paraphrase them:</p>\n<ol>\n<li>\n<p>Absolution - Ignore the problem and hope it goes away</p>\n<p>It&rsquo;s easy to joke about this one, but Rein provided a compelling case for this. For example, security engineers often make the tradeoff to ignore a security loophole if the threat isn&rsquo;t great enough.</p>\n</li>\n<li>\n<p>Resolution - Doing something something &ldquo;good enough&rdquo;</p>\n<p>This feels like a pretty standard principle for building products considering some of these typical aspects of commercial software development:<br>\na) Your team will never have a complete understanding of how your software will express itself once &ldquo;running&rdquo; or &ldquo;used&rdquo; by customers. Therefore perfection, completeness, wholeness are not desirable or ever, actually, achievable.</p>\n<p>b) Deadlines and other external stakeholder pressures will force you to sacrifice however your team defines &ldquo;great&rdquo; or &ldquo;better&rdquo; software</p>\n</li>\n<li>\n<p>Solution - Finding an optimal solution with experimentation or research</p>\n<p>There are touchstone moments in the development of software where this happens. When choosing a framework. When designing a styleguide. When choosing a caching strategy. When designing a migration plan.</p>\n</li>\n<li>\n<p>Dissolution - Redesigning the system so that the problem no longer exists</p>\n<p>This is what Jacob was hinting at. That pure land you inhabit when refactoring code to circumvent an immediate impasse in the software by reframing the problem.</p>\n</li>\n</ol>\n<p>I fondly remember dissolving a particularly tricky conditional statement in a web client by working with a backend engineer to implement an enum for a resource type. This removed a bunch of object introspection (Law of Demeter violations, etc&hellip;) in favor of a simple switch statement.</p>\n",
        "date_published": "2020-06-16T15:39:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/06/16/debugging-ts-in-vscode-and.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/06/16/the-explanation-of-question-of.html",
        "title": "The explanation of Question 12 of Lydia Hallie's fabulous list of JS interview questions, and others",
        "content_html": "<p>Lydia Hallie&rsquo;s list of JS interview questions are extensive and probably one of the most comprehensive resources out there. The laundry list of questions runs the gamut from basic to esoteric language features, each of which progress you though various themes in what seem like meaningful sequences. It appears some modicum of pedagogy is involved, which therefore avoids that oft vacancy of substance typical of a listicle.</p>\n<p>Yesterday I was running through a block of questions with an ex-colleague and we noticed that some of the answers were a bit inchoate. It&rsquo;s so easy for meaning to drift when talking about language features especially when it comes to JS. Consider navigating the following taxonomy &ndash; related to creating objects in JS &ndash; for readers of all skill levels without specious reasoning (the kind of short-hand <em>you get the point</em> or <em>close-enough</em> superstitious explanation we sometimes use; which, by the way, I think greatly hindered my early career development): object, constructor, function, class, prototype, instance, static, method, <code>new</code>, <code>this</code>. It&rsquo;s quite hard but really worth being as correct as interpreting ECMAScript affords us.</p>\n<p>I decided to open up some discussion on Question 12 which tests one&rsquo;s knowledge of the differentiated effects of using the <code>new</code> operator before a function call:</p>\n<p><a href=\"https://github.com/lydiahallie/javascript-questions/issues/82#issuecomment-645022140\">https://github.com/lydiahallie/javascript-questions/issues/82#issuecomment-645022140</a></p>\n<p>Definitely called for a little revisit of YDKJS, no doubt.</p>\n<p>I also feel like I need some clarification on Question 14. What do we call the very root object in JS that all objects delegate to?</p>\n<p><a href=\"https://github.com/lydiahallie/javascript-questions/issues/26#issuecomment-645058195\">https://github.com/lydiahallie/javascript-questions/issues/26#issuecomment-645058195</a></p>\n<p>Coming up with examples is hard. I think Question 11 could use a bit of rework too because there is a <code>this</code> scope issue that somewhat overloads the focus of the problem. Here I go again:</p>\n<p><a href=\"https://github.com/lydiahallie/javascript-questions/issues/355#issuecomment-645066354\">https://github.com/lydiahallie/javascript-questions/issues/355#issuecomment-645066354</a></p>\n",
        "date_published": "2020-06-16T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/06/16/the-explanation-of-question-of.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/06/08/book-quotes-and-commentary-software.html",
        "title": "Book quotes and commentary: _Software Theory_ by Federica Frabetti",
        "content_html": "<p>In which Frederica Frabetti locates the &ldquo;points of opacity&rdquo; &ndash; malfunction &ndash; in/of software through study of the Garmisch (Germany) report &ndash; a foundational text of software from the first Conference on Software Engineering in 1968 organized by the NATO Science Committee. (Also careful you don&rsquo;t mince the word &ldquo;Garmisch&rdquo; into Gramsci.)</p>\n<p>&gt; &ldquo;&hellip;these two aspects&hellip;the necessity of calculating incalculable risks, and of attributing responsibility for them&hellip;is a point where software engineering &lsquo;undoes itself&rsquo; precisely at the moment of its constitution.&rdquo; -p75</p>\n<p>As in discovering responsibility outside of the software: in the likeness of user demands, society&rsquo;s problems, ever-increasing demands on existing software from users.</p>\n<p>&gt; &ldquo;&hellip;there are problems <em>out there</em> that software helps to solve.&rdquo; -p79</p>\n<p>&gt; &ldquo;&hellip;the system and it&rsquo;s development are never clearly separated&rdquo; -78</p>\n<p>&gt; &ldquo;&hellip;they must acknowledge that such a process is not in fact linear, but at the same time they have to avoid backward steps at all cost.&rdquo; -p78</p>\n<p>And how professionalization, as in the planning and management of software development over time &ndash; or formalism, or &ldquo;linearization&rdquo;; where we literally write many things to organize time (external and internal design specs, JIRA stories, prototypes, then finally the code (I guess) etc&hellip;) &ndash; relegates software to the realm of instrumentality and further destabilizes what software is; albeit by attempting to create an interiorized structure that skirts isolation. Thus the evergreen frustrations of the business side.</p>\n<p>&gt; &ldquo;&hellip;this appeal to the lineraization of time is part of the general attempt to &lsquo;control&rsquo; software &ndash; that is, to think of software in instrumental terms.&rdquo;</p>\n<p>&gt; &ldquo;&hellip;software is both a problem and a solution &ndash; indeed, it emerges at the point where the distinction between the two becomes undone and it exists only as the precarious stabilization of this distinction.&rdquo; -p81</p>\n<p>Software development is a fleeting discipline. I guess a line of flight in the rhizome. So maybe we&rsquo;re hearding rats not cats. This partly explains, for me, why I can iterate again and again over a simple &ldquo;implementation.&rdquo; Because we&rsquo;re never done, we&rsquo;re always undone.</p>\n<p>Hence our continued, common problematic to characterize when commercial software development <em>happens</em>. Is it when you change all <em>var</em> to <em>let</em>? The moment your brain begins to mull over a requirement presented by your PM in sprint planning? The final inscription of the company&rsquo;s mission statement? During a whiteboarding design exercise? The moments of realization you have in the shower, during a lunch conversation? The isncription of an idea you copy/steal from your last job without attribution? The deletion of unused code? The moment you decide to delete the unused code?</p>\n<p>Or perhaps the moment we recognize it is bound to break, malfunction, fail:</p>\n<p>&gt; &ldquo;&hellip;software engineering performs an impossible expulsion of consititutive failure from technology, with this move establishing itself as a discipline.&rdquo; -p76</p>\n<p>And further, what else software development <em>is</em>. Because it couldn&rsquo;t just be about formalizing the process, right? Because how do we account for the incalculability of costs/time between problem and solution?</p>\n<p>&gt; &ldquo;Thus, Dijkstra resorts to individual creativeity &ndash; or, as Derrida would have it, &lsquo;genius&rsquo; &ndash; as an explanation for what is in excess of a procedural method and constitutes a leap beyond the programmable.&rdquo; -p82</p>\n<p>But others from the conference warn about the cult of genius. Interesting earlier this year I was mulling over a similar <a href=\"%3C#(#some-patriarchal-intervention-at-google-io-a-while-back)%3E\">intervention</a> four decades later:</p>\n<p>&gt; &ldquo;The &lsquo;exessive&rsquo; creativity of the &lsquo;system type&rsquo; is in turn portrayed as &lsquo;bad&rsquo; unexpected&ndash;something that exceeds the management of the project and threatens it.&rdquo; -p84</p>\n<p>Replace &ldquo;system type&rdquo; with our modern-day <em>10x programmer</em> or <em>rockstar</em> and it&rsquo;s comforting to think that 50 years ago computer scientists were already weary of the danger this person posed to software development. It certainly seems like Frabetti is jabbing at that here.</p>\n<p>Software resists instrumentality, to be merely called &ldquo;code&rdquo;; it follows, then, that engineers resist becoming fungible resources in a complicated domain space. Software&rsquo;s realization is a co-consititutive process of increasing understanding of the problem and the solving of the problem itself. I like the way this passage sums it up:</p>\n<p>&gt; &ldquo;How can something based on the lack of knowledge be realized successfully? This paradox clarifies the particular understanding of time that programmers develop in their interaction with software. Not only does one find out what the system does only by constructing it; the original ignorance of what the system does is <em>constitutive of</em> the system&hellip;Infelicity is constitutive of the possibility of felicity&hellip;One always starts albeit one does not know what will be.&rdquo; -p90</p>\n<p>Of course, the solution is never an end. Or have you ever built software that should not be extensible?</p>\n",
        "date_published": "2020-06-08T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/06/08/book-quotes-and-commentary-software.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/04/26/lets-talk-about-orchestration-vs.html",
        "title": "Let's talk about Orchestration vs Separation of Concerns",
        "content_html": "<p>Check out the second &ndash; and I believe last &ndash; in this short series: <a href=\"https://dev.to/internetross/let-s-talk-about-orchestration-vs-separation-of-concerns-react-redux-edition-part-2-imo\" rel=\"syndication\"><a href=\"https://dev.to/internetross/let-s-talk-about-orchestration-vs-separation-of-concerns-react-redux-edition-part-2-imo\">https://dev.to/internetross/let-s-talk-about-orchestration-vs-separation-of-concerns-react-redux-edition-part-2-imo</a></a></p>\n<hr>\n<p>I&rsquo;m emerging from the shadows, a bit, and trying out dev.to. Check out this first in a two part series: <a href=\"https://dev.to/internetross/let-s-privilege-orchestration-over-separation-of-concerns-4410\" rel=\"syndication\"><a href=\"https://dev.to/internetross/let-s-privilege-orchestration-over-separation-of-concerns-4410\">https://dev.to/internetross/let-s-privilege-orchestration-over-separation-of-concerns-4410</a></a></p>\n",
        "date_published": "2020-04-26T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/04/26/lets-talk-about-orchestration-vs.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/04/01/preferring-repetitive-action-notifications-over.html",
        "title": "Preferring repetitive Action notifications over reuse",
        "content_html": "<p>Have you ever noticed yourself going to unnecessary lengths to avoid repetition in your code despite the fact that requirements actually represent a complicated world? I swear the longer I write code in the industry the more DRY feels like a leaky ideological imposition that drifts from &ldquo;knowledge&rdquo; duplication into code/documentation &ndash; ie text artifact &ndash; duplication. Sigh. This is a nuance we lose too easily by the ad nauseam peddling of the shorthand DRY; which I suppose also reveals the danger of the supremacist tendency of the axiomatic; axioms all-to-easily claim ontological root. Especially in the minds of early career folks or folks emerging from industry founding fathers cargo cults.</p>\n<p>&gt; Every piece of <strong><em>knowledge</em></strong> must have a single, unambiguous, authoritative representation within a system.\n&gt;\n&gt; <footer><small><cite>The Pragmatic Programmer</cite>, [emphasis mine]</small></footer></p>\n<p>As we&rsquo;re tapping along in an editor, the code that bears some resemblance to other code is, in fact, the precise nuance our applications need to create the richness of these membranes we build between people and machines. Here&rsquo;s an example slightly altered.</p>\n<p>Let&rsquo;s say we are working with an events management system where a new feature is being built to allow event organizers to administer marketing campaigns on their events. In the current world, an event organizer can do two things to a campaign once it&rsquo;s added to the event:</p>\n<ol>\n<li>Activate the campaign.</li>\n<li>Select the campaign to be &ldquo;featured&rdquo; &ndash; this places the campaign into a larger sitewide collection of campaigns that are <em>featured</em> in certain areas of the product.</li>\n</ol>\n<p>A sketch of the stateless component in our graph might look like so (just relevant JSX and event handler):</p>\n<script src=\"https://gist.github.com/rosschapman/ed540e7ff31ae56690db02bc4f7712cc.js\"></script>\n<p>Then Product decides to add a new nicety whereby an event organizer, when activating a marketing campaign, will automatically trigger marking that campaign with the special &ldquo;featured&rdquo; flag <em>if</em> that campaign happens to be the only active marketing campaign on the event. This is effectively a third flow; of course to the user it&rsquo;s just a list item with a couple check boxes (simple stuff, right?).</p>\n<p>As the developer I might think: <em>this doesn&rsquo;t seem all that hard! I already had the foresight to implement a flexible indirection &ndash; a consolidated event handler to coordinate the store notifications for user interactions in one place. This means all I have to do is flavor the conditional will another branch; and I can reuse the current dispatchers. I&rsquo;m a fucking oracle.</em></p>\n<p>Whereby I try:</p>\n<script src=\"https://gist.github.com/rosschapman/86259031a2442315f6201771b557ec4d.js\"></script>\n<p>I mean, that&rsquo;s the right logic. All my test mocks are reusable. We are sailing along.</p>\n<p>Sort of.</p>\n<p>Then something nags at me looking at this code. It&rsquo;s subtle, but there&rsquo;s a risky assumption embedded here. Inside the interior <code>if-then</code> branch under the conditional expression <code>hasNoActivated</code>, we are sending a sequence of two distinct <em>mutative</em> notifications to our data store; moreover, the second depends on the first to complete successfully. Now, we might test this code in the browser and it works every time. Our tests pass.</p>\n<p>But.</p>\n<p>For how long?</p>\n<p>This code lives downstream of our next indirection &ndash; the container &ndash; that shepherds these messages to the store. So this code is trying to coordinate a subroutine of <em>effectful</em> functions (Actions) three (perhaps more) layers away from the store itself.</p>\n<p>Which begs some questions. For example, although the action notifiers I&rsquo;m calling are synchronous, how confident am I in the inner workings of my component framework&rsquo;s render engine and algorithm &ndash; particularly it&rsquo;s collaboration with my data layer (ie Redux)? I might be forcing additional renders here. More importantly, how much can I trust other developers to maintain the correct sequencing in the container? Will a test help? Will a comment help? Will either of these prevent mistakes when additional behavior needs to be added.</p>\n<p>100% maybe.</p>\n<p>Software is weird. Code like this could become a productive, yet forgotten, corner of entropy. But silent risks, if recognized, must be avoided. We can do better, although part of reaching this <em>better</em> is yielding our mental model to become more <em>reactive</em> &ndash; to adapt, to embrace nuance, to become loose as the requirements become more complicated. My observation is that the code is not lack for defensive guards and documentation, but lack for an expanded set &ndash; <em>single, unambiguous, authoritative</em> &ndash; of blessed possibilities with distinct articulations. In other words, an expanded <em>model</em> &ndash; expressed in code &ndash; that <em>models</em> more precisely the desired possibilities of what a user can do.</p>\n<p>Let&rsquo;s try rewriting our component-level event handler to incorporate the new happy path into our domain&rsquo;s lexicon: the Action notifiers, the names of things &ldquo;that depend on when they are called or how many times they are called&rdquo; (see <cite><a href=\"https://www.manning.com/books/grokking-simplicity\">Grokking Simplicity</a></cite>).</p>\n<script src=\"https://gist.github.com/rosschapman/0812df06a1d25138de0fa9ed5ddcc763.js\"></script>\n<p>The modifications in this third example add a new Action notifier (handler) that represents the <em>distinct</em> type of mutation we want to effect against the store. In other words, a function that satisfies the new Product case that <em>narrows</em> attention &ndash; of the developer <em>and</em> program &ndash; on the new case by leveraging a semantic, structural, change to the number of container handlers. (Side note: I fantasize that Zachary Tellman might describe the new handler name as a too &ldquo;natural&rdquo; yet still &ldquo;consistent&rdquo; name (see <cite><a href=\"https://elementsofclojure.com/\">Elements of Clojure</a></cite>).</p>\n<p>Furthermore, let&rsquo;s observe that the payload semantics remain the same. Which means our data layer comprised of the container and action dispatching, only requires similarly modest adjustments to shepherd the same data. Lastly, though quite importantly, our container is now capable of dispatching messages to the store and effecting a mutation in just a single pass if we wish it. For example:</p>\n<pre class=\"language-javascript\"><code>\nupdateCampaignAndUpdateFeaturedCampaigns(data) {\n    dispatch(updateCampaigns(data));\n}\n\n// Whereby our reducer might return the state mutations composed as:\n\n{\n    campaigns: {\n        ...state.campaigns,\n        {\n            id: payload.id,\n            activated: true\n            // other fields...\n        }\n    },\n    featuredCampaigns: [\n        ...state.featuredCampaigns,\n        payload.id\n    ],\n}\n</code></pre>\n<p>Overall this design provides increased confidence that this display component, our presentational leaf node, is more precisely responsible for render and event notification. Perhaps the subtweet here is keeping events and messages 1:1, even if you wind up with similar or duplicate lines of code.</p>\n",
        "date_published": "2020-04-01T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/04/01/preferring-repetitive-action-notifications-over.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/03/12/the-will-to-better-software.html",
        "title": "The will to better software companies",
        "content_html": "<img src=\"https://internetross.space/uploads/2020/c998eb6b6b.png\" alt=\"Semilattice a and Tree Structures b Source A City is Not a Tree 4\" title=\"Semilattice-a-and-Tree-Structures-b-Source-A-City-is-Not-a-Tree-4.png\" border=\"0\" width=\"599\" height=\"401\">\n<p>Lately I&rsquo;ve been thinking about productivity and it&rsquo;s evolutionary rhythm while scaling. Like, how easy the cadence ebbs. My lived experience as a software developer often feels like anfractuous GPS reroutes. For example, we have split teams to tackle different product areas in parallel. Usually this means working separately in our &ldquo;owned&rdquo; codebases. But software is never neat. So when the team in Mendoza needs review on a changeset that touches our code area, we&rsquo;re talking temporal crossings to achieve conciliation.</p>\n<p>It&rsquo;s late afternoon in Argentina wine country when I&rsquo;m just digging my heals into a morning Philz roast.</p>\n<p>The additional burden of a cross-geo async request means that I&rsquo;ll have to hunker down to decipher what they&rsquo;re proposed code is doing and what it&rsquo;s supposed to do &ndash; what might take a few minutes pairing could take tens of minutes. While async communication over Slack is ok, closing the mental gap in understanding the code changes is tough. We are facing a kind of Derridean differánce. As if navigating the palimpsest wasn&rsquo;t enough. Multiple personages reading and explaining the code text, scribbling comments, changing, re-reading the next day; discovering the truth in the spaces/tabs. Reading software is really tough stuff. This impact of distance and time spent to &ldquo;get up to speed&rdquo; (pun intended) is a delta that doesn&rsquo;t always feel satisfyingly addressed by organizational planning.</p>\n<p>Does this sound like what you do for work?:</p>\n<p>&gt; Every software project is like a palimpsest where every developer scratches old text, and writes on top of it their perceived new solution, creating a manuscript where a mix off styles and languages reflect different understandings of the world, different world visions.\n&gt;\n&gt; <footer><small><cite><a href=\"https://medium.com/@old_sound/code-is-a-palimpsest-c4fd0ebcd90c\">Code is a Palimpsest</a></cite></small></footer></p>\n<p>And</p>\n<p>&gt; Différance is the systematic play of differences, of the traces of differences, of the spacing by means of which elements are related to each other. This spacing is the simultaneously active and passive (the a of différance indicates this indecision as concerns activity and passivity, that which cannot be governed by or distributed between the terms of this opposition) production of the intervals without which the &ldquo;full&rdquo; terms would not signify, would not function.\n&gt;\n&gt; <footer><small><cite>Positions</cite></small></p>\n<p>Holy complicatedness, richness, depth! No wonder you can&rsquo;t just throw more devs at the problem. Though apparently that&rsquo;s what men in the industry used to think.</p>\n<p><em>&mdash;</em></p>\n<p>Not too long into my first software gig my team of 5 engineers organized a book club and tackled <em>The Mythical Man Month</em>. That&rsquo;s when I really learned how dev teams became reduced to fungible &ldquo;resources.&rdquo; (It wasn&rsquo;t long before I was at a happy hour and our head of sales was asking me, &ldquo;Why can&rsquo;t we just ship the work you do to India?&rdquo; So I apparently it&rsquo;s a historically recurrent theme.) It was also my first introduction to the idea that you can&rsquo;t just throw more people at software problems to achieve speed gains.</p>\n<p>&gt; Adding manpower to a late software project makes it later.\n&gt;\n&gt; <footer><small><cite>The Mythical Man-Month</cite></small></footer></p>\n<p>If we believe Jessica Kerr and the other cyberneticians of our ilk, and on this point I might &ndash; software is a symmathesy: <em>a learning system of learning parts</em>. Brooks must have believed something similar I just don&rsquo;t remember his exact words.</p>\n<p>Nonetheless, I interpolate. Brooks' insights feel situated as early symmathecist thinking. Software is so highly sophisticated, so highly <em>complicated</em>!, that command and control thinking can&rsquo;t intervene to establish order:</p>\n<p>&gt; As time passes, the system becomes less and less well-ordered. Sooner or later the fixing cease to gain any ground. Each forward step is matched by a backward one.\n&gt;\n&gt; <footer><small><cite>Ibid.</cite></small></footer></p>\n<p>So why does this happen? Like, despite Brooks' spacious, ethereal characterization of our work as <em>only slightly removed from pure thought-stuff</em> where we build <em>castles in the air</em> (words I do remember wonderingly)&hellip;we definitely live through a tangible stickiness, queues, waiting rooms; especially mid-to-late in the build cycle. Things get really hard. I swear there&rsquo;s something even metallic about a build failure.</p>\n<p>&gt; In order to change our system, we need a mental model of it. Each developer has a mental model of the software we work on. Each developer’s mental model is necessarily incomplete and out of date. And, they’re each different from everyone else’s. (This is called Woods’ Law, if I recall correctly.) We spend time reconciling our mental models enough to communicate with each other; this is a coherence penalty.\n&gt;\n&gt; <footer><small><cite><a href=\"https://medium.com/@old_sound/code-is-a-palimpsest-c4fd0ebcd90c\">the Origins of Opera and the Future of Programming</a></cite></small></footer></p>\n<p>Well, we all know the drill and can recall with pretty sharp clarity what tends to happen. Making code changes later in a project becomes increasingly difficult because previous design decisions have constrained possibilities. More consistency is demanded; maybe not total, but if the component handlers should call to the reducer, why are you calling <code>setState()</code> directly in the handler? Because&hellip;the rush to the finish line produces anxiety that strains communication (within the already polynomial channeling). You shift from pensive philosopher to tactician; code breaker. Code review quality suffers; if only for the obvious reason that you need to double down on crafting and glueing code for more hours in the day. This, in turn, decreasing mental reserves for context switching to someone else&rsquo;s code. All that great senior leadership out the door. There&rsquo;s simply less consensus building. Public Slack channels are quieter. Regardless how high-performing the team, I&rsquo;m convinced there will be some communication degradation in the twilight hours.</p>\n<p><em>&mdash;</em></p>\n<p>When I read Coda Hale&rsquo;s recent piece <em>Work Is Work</em> all of this ugh was loaded into view again; and I really appreciate his analysis of how we end up in slog mode; and the antidote. Maybe the industry hadn&rsquo;t received a really concise reflection in a while. Maybe it&rsquo;s the mathematical proofing and formalism that adds a seductive element for the modern SWE struggling in their unwieldy symmathesies; what Karatani would call our &ldquo;will to architecture&rdquo;. This piece was going around the Greater than Code sphere for sure. For my philosopher/poet brain for sure. Ok, so similar to Brooks, but for orgs, Hale says:</p>\n<p>&gt; At some point in time, every organization realizes that it’s slowing down.\n&gt;\n&gt; <footer><small><cite><a href=\"https://codahale.com/work-is-work/\">the Origins of Opera and the Future of Programming</a></cite></small></footer></p>\n<p>Like Brooks, Hale is dealing with that slog. But with the scope zoomed out to help us understand how to manage and overcome the obstacle of big organizations growing at economies of scale. He enriches the idea of the mythical man month with Amdahl&rsquo;s law:</p>\n<p>&gt; The work capacity of an organization scales, at most, linearly as new members are added.\n&gt;\n&gt; <footer><small><cite>Ibid.</cite></small></footer></p>\n<p>Amdahl&rsquo;s law: I&rsquo;m still wrapping my head around it! But I believe the gist is: when we try to add more people to parallelize parts of the dev work, we won&rsquo;t get any dramatic (exponentialized) speed gains over the sequential work of the smaller group. Amdahl observed this behavior while throwing additional processors at a computational task in a computer machine. The &ldquo;parallel fraction&rdquo; of speed increase when adding <em>N</em> new members is only relative to the original group size, and eventually tops out and flattens. Rather than the speed boost our command-control leadership wills, we get something a flip side slog:</p>\n<p>&gt; Coherence costs grow quadratically as new members are added.\n&gt;\n&gt; <footer><small><cite>Ibid.</cite></small></footer></p>\n<p>Slog = coherence costs! That&rsquo;s a sweet little buttoned up phrase for it.</p>\n<p>Around the same time I read Hale&rsquo;s piece I was picking up the aforementioned Kojin Karatani book, <em>Architecture as Metaphor</em>. So while I&rsquo;m sitting with these ahas! about how the frustrating things at work are these somewhat well-understood &ldquo;coherence costs&rdquo; that occur on large teams like mine which can be observed with rigor from the outside (<em>etic</em>)&hellip;I&rsquo;m suddenly finding myself in chapter 4 of <em>Architecture as Metaphor</em> called the <em>Natural City</em> where Karatani continues to build his argument for the ways that theory is entrapped again and again by the architectonic. But the thread I want to pull on is simply Karatani&rsquo;s synopsis of Christopher Alexander&rsquo;s The City Is Not A Tree. Lol, of course I should meet Alexander here. He is like one of the father&rsquo;s of <em>Software Patterns</em> &ndash; see his 1996 keynote at OOPSLA &ndash; that would inspire so much of how our apps are built at scale today.</p>\n<p>In the seminal essay The City Is Not A Tree, that would inspire people across fields and perhaps give rise to the concept of bounded rationality, Alexander proposed mathematically based, formal, structural, ideas (just like Hale is doing) to describe the &ldquo;natural city&rdquo; as a <em>semi-lattice</em>; a concept from Set theory.</p>\n<p>&gt; A collection of sets forms a semilattice if and only if, when two overlapping sets belong to the collection, the set of elements common to both also belongs to the collection.\n&gt;\n&gt; <footer><small><cite>A City is Not a Tree</cite></small></footer></p>\n<p>He is thereby able to reveal the &ldquo;natural city&rdquo; as something we can think about rationally. Particularly, and importantly, rationally distinct from the nemesis &ldquo;artificial city&rdquo; &ndash; a command-and-control style approach to designing cities in a treelike fashion from those who don&rsquo;t appreciate the the richness, subtlety, and complexity in the overlaps that otherwise staves off &ldquo;coming destruction&rdquo; and &ldquo;anarchy.&rdquo;</p>\n<p>&gt; When we think in terms of trees we are trading the humanity and richness of the living city for a conceptual simplicity which benefits only designers, planners, administrators and developers. Every time a piece of a city is torn out, and a tree made to replace the semilattice that was there before, the city takes a further step toward dissociation.\n&gt;\n&gt; <footer><small><cite>Ibid.</cite></small></footer></p>\n<p>And</p>\n<p>&gt; The semilattice&hellip;is the structure of a complex fabric; it is the structure of living things, of great paintings and symphonies.\n&gt;\n&gt; <footer><small><cite>Ibid.</cite></small></footer></p>\n<p>My brain keyed on semilattices because they seemed to describe the structure of a software system I&rsquo;ve been coming to know through Kerr and Bateson (opera, camerata, living) &ndash; not to mention the cutely convenient lexical overlap of mathematical terms in the definition; eg, a &ldquo;Set&rdquo; is a common data structure implemented by many high-level programming languages. Mendoza devs putting their text in our text. Some overlap of time zone. Knowledge overlaps as more tenured developers work in more areas of the codebase. Overlap at the coffee station, at the lunch table. Overlapping documentation, nearly duplicate. Also the incomplete lines of connection. The grassroots partnerships and friendships that emerge across teams. The polymorphic ensemble of patterns and style in our web applications: classes called as functions, state reducers and DOM events, REST with GraphQL, compositional components within hard-bound graphs. Microservices databases implementing Order and User over and over again. The semilattice seems very familiar.</p>\n<p>Therefore, in the context of a symathesy, where Alexander might say our bounded rationality (not to mention hubris, or inexperience, or ego, or other ingressive tendencies) limits our ability to observe and study the subtlety and richness of the organization, throwing more <em>men</em> at the problem is short-sighted as fuck. Managers can&rsquo;t govern from apart, at the top of the edifice. There are superlinear interactions to behold.</p>\n<p>Then the advice that Hale starts giving to tackle coherence costs makes a lot of sense:</p>\n<p>&gt; The only scalable strategy for containing coherence costs is to limit the number of people an individual needs to talk to in order to do their job to a constant factor.\n&gt;\n&gt; <footer><small><cite><a href=\"https://codahale.com/work-is-work/\">the Origins of Opera and the Future of Programming</a></cite></small></footer></p>\n<p>Limit the overlap!</p>\n<p>&gt; As with heavily layered applications, the more distance between those designing the organization and the work being done, the greater the risk of unmanaged points of contention. Top-down organizational methods can lead to subdivisions which seem like parallel efforts when listed on a slide but which are, in actuality, highly interdependent and interlocking. Staffing highly sequential efforts as if they were entirely parallel leads to catastrophe.\n&gt;\n&gt; <footer><small><cite>Ibid.</cite></small></footer></p>\n<p>And</p>\n<p>&gt; As an organization hires more employees, work on productivity improvements must be a constant priority. Internal tooling, training, and services must be developed and fielded to ensure that all members are able to work on problems of continuously increasing impact. The ceaseless pursuit of force multipliers is the only possible route to superlinear productivity improvements as an organization grows.\n&gt;\n&gt; <footer><small><cite>Ibid.</cite></small></footer></p>\n<p>In an essay I assume Hale drew from, and to which Jessica Kerr&rsquo;s above quote references, Michael Nygard makes a similar suggestion:</p>\n<p>&gt; &hellip;take a look at your architecture, language, tools, and team. See where you spend time re-establishing coherence when people make changes to the system&rsquo;s model of the world&hellip;take a look at your architecture, language, tools, and team. See where you spend time re-establishing coherence when people make changes to the system&rsquo;s model of the world.\n&gt;\n&gt; <footer><small><cite><a href=\"https://www.michaelnygard.com/blog/2018/01/coherence-penalty-for-humans/\">Coherence Penalty for Humans</a></cite></small></footer></p>\n<p>I love all this. Of course, it&rsquo;s hard. Alexander tested folks, experimented to discover that the tendency was to &ldquo;reorganize&rdquo; the mental model into a treelike structure (though perhaps he only interviewed a group of limited white men, or folks embedded in white supremacist society?) But I suspect some of the hardness has to do with:</p>\n<ol>\n<li>\n<p>Our inability to see the costs (ie the complexity, simply constrained by our brain&rsquo;s inherent limitation to expansively see/hold it all); for leadership looking at the org we can also probably say that their &ldquo;mental model is necessarily incomplete and out of date&rdquo;.</p>\n<p>&gt; It is similarly difficult to visualize the semi-lattice structure &ndash; where multiple sets overlap&ndash;of the natural city, and thus we tend to reduce it to a tree, the only structure we can visualize.\n&gt;\n&gt; <footer><small><cite>A City is Not a Tree</cite></small></footer></p>\n</li>\n<li>\n<p>An ignorance that we have a semilattice at all. Who out there amongst leadership are systems thinkers? Embracers and students of variety, incompleteness, ambiguity, multiplicity? Who can embrace these, split things, and double down on rewiring the learning (neuronic) threads? Ensembles over A/agile. More of that interspecies contamination, contaminated diversity that Anna Tsing talks about. Mushrooms and the dying earth can help.</p>\n<p>&gt; Where a matrix indicates a high-touch relationship between two groups (e.g., a group of engineers working on a feature and the lawyers trying to ensure the legal compliance of that feature), efforts should be made to reduce the cost of that interaction by colocating their members (e.g., embed a lawyer with the engineers).\n&gt;\n&gt; <footer><small><cite><a href=\"https://codahale.com/work-is-work/\">the Origins of Opera and the Future of Programming</a></cite></small></footer></p>\n</li>\n</ol>\n<p>Management or whatever version of leadership you have must stay on top of it. It&rsquo;s some serious work. Maybe we need better integration tech; it&rsquo;s like we are missing some connective tissue. Maybe it&rsquo;s not tech at all.</p>\n<p>I remember being met with a lot of skepticism when I suggested to some engineers at my company that we create a meeting support team. It was a partially-formed thought, but the basic idea would be to make a self-selected group available to take notes for other peoples' meetings. I don&rsquo;t think many devs grasp the importance of their meeting communication as architectural design records; and similarly how hard it is to accurately and correctly document after the fact; or document in progress for someone who is also trying to participate. Living in entropy is easier than culture change. I also understand that no computer science education ever taught anyone this stuff was important which is why Brooks' observations went unheeded for 50 years.</p>\n<p><strong>Postscript:</strong></p>\n<p>Why did I keep trudging through Karatani while writing this essay?? I should have known better: a few chapters later I&rsquo;m cry-laughing because I bump into that hopeful schizo theory which blew my mind like 20 years ago in undergrad. And now I&rsquo;m like damn because Karatani is saying that the semilattice is probably not the ideal (post)structure I want to imagine upon my software company. Of course, this makes sense in Karatani&rsquo;s argument because he wants to problematize architectonic thinking.</p>\n<p>&gt; Despite its appearance, [the semilattice] is orderly and centered.\n&gt;\n&gt; <footer><small><cite>The Will to Architecture</cite></small></footer></p>\n<p>And</p>\n<p>&gt; What happens when the semilattice is broken?\n&gt;\n&gt; <footer><small><cite>Ibid.</cite></small></footer></p>\n<p>By Delueze and Guattari of course. Whatever, I still think the semilattice is a good formal representation of why coherence costs emerge in the indeterminate, rich encounters of the software symmathesy; the gentle swish of overlapping domains; like at Hearst and Euclid. But the rhizomatic network requires consideration soon. I&rsquo;m urged that way anyway &ndash; see my hints above about interspecies contamination and the anthropocene. I think the ensemble moves toward assemblage soon.</footer></p>\n",
        "date_published": "2020-03-12T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/03/12/the-will-to-better-software.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/01/24/some-patriarchal-intervention-at-google.html",
        "title": "Some patriarchal intervention at Google I/O a while back",
        "content_html": "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/0SARbwvhupQ\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n<p>About 11 years ago at Google I/O two dudes, Brian Fitzpatrick and Ben Collins-Sussman, presented The Myth of the Genius Programmer to an audience of mostly dudes. Well, we can surmise at the demographics because women were still being invented around this time.</p>\n<p>&gt; Women are a very recent invention.\n&gt;\n&gt; <footer><small>Ursula K. Le Guinn, <em>The Wave in the Mind</em></small></footer></p>\n<p>Or, rather, <em>re</em>invented since they had been denied participation in Western STEM since at least the middle 1700s:</p>\n<p>&gt; Women lost their security clearances very early in the stories of leading-edge science.\n&gt;\n&gt; <footer><small>Donna Haraway, <em>Modest Witness</em></small></footer></p>\n<p>Despite the missed opporunity to cite the origins of congressive world-making in non-human-men being experience, indigenous practice, cooperative economics, anarchism, feminism, liberation theologies, etc&hellip;the talk is a pretty good orientation for ingressive types to think congressively about working with other people.</p>\n<p>That&rsquo;s my subtext as I watch. I just wish men were erudite enough to understand they&rsquo;re re-invention. Non-mens have to keep rewinding it back. For example:</p>\n<p>&gt; The men who wrote the [Agile] manifesto are unclear on whether they invited any women. Even so, the thing I notice from both the manifesto, the accompanying principles, and the fact that these 17 men call themselves ‘organizational anarchists’ is that what they came up with is inherently subversive, anti-authoritarian, and feminist. There is an emphasis on self-organising, collaboration, experimentation, welcoming change, and building high-trust and supportive relationships.\n&gt;\n&gt; <footer><small>Hanna Thomas, <cite><a href=\"https://medium.com/@Hanna.Thomas/why-dont-we-just-call-agile-what-it-is-feminist-8bdd9193edba\">Why Don’t We Just Call Agile What It Is: Feminist</a></cite></small><footer></p>\n<p>Tech, like other industries, continues to produce the worst of/from man because its manifest teleology of <em>Progress</em> (what Donna Haraway calls &ldquo;Euclidean tales&hellip;of tragic detumescence&rdquo;, the &ldquo;prick tale.&rdquo; ) &ndash; sieved through history from the industrial revolution &ndash; is wrong for the precarity of the Anthropocene and a damaged earth. For richness of our symmathesies. We all suffer for it.</p>\n<p>Racism and sexism are the key ingredients in the alchemy that has transformed &ldquo;Don&rsquo;t be evil&rdquo; to solving the <em>hard problems</em> of &ldquo;Controlling the explosion of child porn on the platform&rdquo; (Youtube, to name a recent example. The darkest of whoops).</p>\n<p>What these guys are hinting at is that an ingressive mindset can help us move us at the speed of trust, and therefore build better software together. So, yep, there was some movement going on a decade ago. Radical muds seeping into the granite of hard dick culture; white boys catching each other and putting together slides for the other boys.</p>\n<p>The talk is an introduction and invitation in trust-based collaboration and vulnerability. Touchstones include:</p>\n<ul>\n<li>you are unique but not special (meh, reinscribing in sad machismo Tyler Durden reference)</li>\n<li>individual genius is a myth</li>\n<li>ego is dangerous</li>\n<li>stop hero-worshipping, Linus et al</li>\n<li>coding is social</li>\n<li>feedback is important</li>\n<li>getting feedback early and often is good</li>\n<li>being nice is important</li>\n<li>code review is necessary</li>\n<li>failing publicly is ok</li>\n<li>keeping record of your failing is ok (keep documentation for failed designs)</li>\n<li>being non-perfect publickly is ok</li>\n<li>vulnerability at work is a strength</li>\n<li>tools create a sociality</li>\n<li>tools can unnecessarily restrict</li>\n</ul>\n<p>From the progenitor of the terms &ldquo;ingressive&rdquo; and &ldquo;congressive&rdquo; that I&rsquo;ve been flinging about wildly:</p>\n<p>&gt; Ingressive is about going into things and not being waylaid by what people think or by emotions and congressive is about bringing people with you and bringing people together and unifying and making connections between things&hellip;. I&rsquo;ve come to think that congressive behavior is basically better for society but that ingressive behavior is rewarded more by society because society is based on competition. It&rsquo;s based on how you present yourself so for things like competing for a job, you have to be ingressive to put yourself forward for promotion and to talk about how great you are. Whereas, when you&rsquo;re actually doing some work with people, then it&rsquo;s really helpful to be congressive because then you bring people together, you understand people.\n&gt;\n&gt; <footer><small><cite><a href=\"https://www.greaterthancode.com/category-theory-for-normal-humans\">Episode 038: Category Theory for Normal Humans with Dr. Eugenia Cheng</a></cite>, Greater than Code</small></footer></p>\n<p>It&rsquo;s devastating to think about the enormity of emotional intelligence training men needed/need/will need; how expensive it is to refactor patriarchy&rsquo;s structural grammar; that ambition which pits men against one another in an end game for supreme master and commander. In this ever-war even order and peace means the seizing of power; power must be assumed by the individual. It is not shared.</p>\n<p>Sure, there is a drip of undoing of Patriarchy when disenfranchisng the myth of genius; but the non-human-men bear the major brunt of burden for maintaining the moral center and possible salvation.</p>\n<p>I&rsquo;m reminded of another talk.</p>\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/WELBnE33dpY\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n<p>Hillel Wayne turns a similar gaze navel-y and spotlights the peril of &ldquo;charisma-driven development&rdquo; we suffer in engineering culture. We might say another symptom of cock-sure genius arising. I love this talk. Recognizing the artifice of loudness and leaning, he looks at the data and calls bullshit on men. The data is good. It&rsquo;s a tool. Nonetheless, I&rsquo;m not sure Hillel&rsquo;s Empiricism will be as powerfully feminist as interventions like Thomas' archeology. Of course, Cheng&rsquo;s metonymic replacements are interesting in that they make it easier to implicate women&rsquo;s complicit was in patriarchy. Hot take: overall let&rsquo;s be skeptical of the neo-classical &ndash; logic can win &ndash; and neo-liberal &ndash; we can reach across the aisle tactics.</footer></footer></p>\n",
        "date_published": "2020-01-24T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/01/24/some-patriarchal-intervention-at-google.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2020/01/20/thinking-about-heuristics-for-avoiding.html",
        "title": "Thinking about heuristics for avoiding code duplication across the stack",
        "content_html": "<img src=\"https://internetross.space/uploads/2020/de42e3984a.jpg\" alt=\"Doublemint 1\" title=\"doublemint-1.jpg\" border=\"0\" height=\"409\">\n<p>At the office I&rsquo;ve sprinkled some glue labor on a piece of documentation that attempts a heuristics for avoiding code duplication <em>across</em> client and api layers. I kept seeing this type of repetition occur and it was creating too much maintenance risk in the code.</p>\n<p>Here&rsquo;s an example. Imagine a piece of code that takes inventory items from an order and derives a cost based on the order status. This calculation could be executed in the api layer, where it would be serialized into response body adjacent to the original cost data. Something like:</p>\n<pre class=\"language-javascript\"><code>{\n    inventory_items: [\n        {\n            order_id: 1234\n            cost: {\n                major: ...,\n                minor: ...,\n                // etc...\n            },\n            cost_display: 'MXN186.67' // &lt;== augmented data\n        }\n    ]\n}\n</code></pre>\n<p>This is a totally reasonable API design. However, a client developer could decide to do the calculation in the view code with a more raw serialization of the inventory item and order objects, and then merge that data:</p>\n<pre class=\"language-javascript\"><code>const composeInventoryItemForDisplay = (inventoryItem) {\n    ...inventoryItem,\n    costDisplay: calculateCostForDisplay(inventoryItem);\n}\n\nfunction calculateCostForDisplay(inventoryItem) {\n    let newCost;\n    const order = lookupOrder(inventoryItem.get('order_id'));\n    const currency = order.get('currency');\n    // subsequent processing steps...\n    return newCost;\n}\n</code></pre>\n<p>In a software system there are many floating nodes urged toward similar ends: teams, software that&rsquo;s running, software that&rsquo;s being worked on, etc&hellip; It hardly uncommon for both a front and back end team to write some code to solve a similar problem &ndash; what might even be a simple calculation &ndash; while totally blind to the other side tapping away. Frequent team project reassignments, geospatial and organizational distance, depth of expertise, weak cultural value around curious coding, etc&hellip; these types of contention costs create the regrettable complicatedness, the vivant natura, that results in risky duplications. Especially risky for inconsitencies that might develop inside essential software modules like pricing computations.</p>\n<p>Supplemental thoughts from Coda Hale&rsquo;s <a href=\"https://codahale.com/work-is-work/\">new blog post</a> going around:</p>\n<p>&gt; Contention costs grow superlinearly as new members are added.</p>\n<p>&gt; Coherence costs grow quadratically as new members are added.</p>\n<p>&gt; Limit the number of people an individual needs to talk to in order to do their job to a constant factor.</p>\n<p>I&rsquo;m not sure I would have believed this type of thing would happen before I joined a larger company with an engineering group spread across geos; teams flung across the ownership matrix by the high winds of market shift. <em>This investor and wall street casino shit drives tough team decisions.</em> Lol team pet names: stunted protologisms. Like, what happened to the Squirrel team? Oh, they are the <em>Crib Gto Pomp</em> team now. Well, at least we are consistently circumlocutory at naming teams.</p>\n<p>But lo and behold, such an example like the above cost calculation <em>exists</em>. I saw something like it in our JavaScript code. Then I asked the folks who work on backend if the frontend really needed to be doing this work. We shouldn&rsquo;t. We literally shouldn&rsquo;t because the computation for this existed in our backend service already. This is one reason we can&rsquo;t have nice things.</p>\n<p>So I&rsquo;ve been thinking a lot about an approach to code, a kind of mental shim, to mitigate the coherence costs across the stack. Even with a fluctuating number of devs with knowledge about the code. Maybe we should just call this predicament <em>patchy</em>; patchy coding. Here&rsquo;s what I&rsquo;ve got so far with a cute story and <em>real life</em> examples:</p>\n<pre tabindex=\"0\"><code>Avoid duplicating code across the stack\n\nConsider the following scenario which is based on true events.\n\nOne day Team RocketShip is working on a feature for Big Initiative X. They implement some computational logic in Ticket Availability Service which adds a new attribute on TicketClass. The code is great, it ships, customers are elated. But soon after, Team SpaceShip is tasked with another piece of Big Initiative X and needs to display the result of similar computational logic in a React app. However, Team SpaceShip doesn't know about Team RocketShip's previous implementation in TAS, and they decide they can actually write this computational logic into the client code using existing TicketClass data. The code is great, it ships, customers are elated.\n\nUh oh. Now we have duplicate code on the backend and frontend. Which means code that is very likely to become out-of-sync and result in disruptive maintenance work or bugs in the future. But how do we avoid this situation? Unfortunately, this is one of those social (read: people) problems of software engineering. There's no way to reliably automate prevention with static analysis of the code.\n\nHeuristics:\n\n    There &amp;gt; 1 attributes returned from the API that are similarly named\n        Here's a real life example:\n        TicketClass used to have attributes for auto_hide, hide, auto_hide_before, and auto_hide_after that client code in checkout utilized to compute the ticket's &quot;hidden&quot; status. In other words, client code asked of these associated attributes: should this ticket be unavailable for purchase. However, creating statically derived properties from a mixture of data may be an indication the backend can do this work for you, or already has.\n            Ticket Availability Service already had code that computed this logic. Ultimately the frontend computation was replaced with a new attribute added to the TicketClass API.\n    There &amp;gt; 1 attributes returned from the API that are related &quot;communicationally,&quot; in that they reference similar types of data that are computed differently.\n        Similar to the example above, the existence of auto_hide and hide attributes seem conceptually related – through &quot;hide&quot; – and can be a clue that there may be logic on the backend that could be reused to for hidden status calculation.\n    I need a static value that won't be impacted by user behavior after first load\n\nMake the backend do the work\n\nHeuristics:\n\n    Will the iOS and Android team's have to implement this too?\n        Always remember that the desktop website is just one place where we write code for consumers of our applications. If the feature you are building will likely end up on a device, it's likely the backend code can expose what you need in the API.\n</code></pre>",
        "date_published": "2020-01-20T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2020/01/20/thinking-about-heuristics-for-avoiding.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/12/10/maybe-eithers-with-promises.html",
        "title": "Maybe Eithers with Promises",
        "content_html": "<p>In the most recent issue of JS Weekly, a <a href=\"https://medium.com/javascript-scene/handling-null-and-undefined-in-javascript-1500c65d51ae\">new piece</a> from Eric Elliot about optional values in JavaScript reminded of one of the first Lambda Cast episodes I listened. <a href=\"https://soundcloud.com/lambda-cast/6-null-and-friends\">#6</a>: <em>Null and Friends</em>. At that point in time I was near the start of my functional programming research and finishing Kyle Simpson&rsquo;s <a href=\"https://github.com/getify/functional-light-js\"><em>Functional-Light JavaScript</em></a>. During the podcast I was delightedly shocked to hear the hosts discuss functional languages that are  actually designed to keep null out of your programs. I could feel myself pulled toward the FP language hype, especially if that hype was about solving the real-world unpleasantness of working with ambiguity in code.</p>\n<p>Because of JavaScript&rsquo;s dynamic type system, optional values like <code>null</code>, <code>undefined</code>, or an empty string can easily make trouble in your software. The language lets us get away with saying <em>I don&rsquo;t know</em> without any compose-time feedback. Therefore spinning up the browser and pushing play is often your only recourse to see how optionals are actually handled.</p>\n<p>In his article, Elliot lists the common progenitors of <code>null</code>:</p>\n<p>&gt; 1. User input\n&gt; 1. Database/network records\n&gt; 1. <strong>Uninitialized state</strong>\n&gt; 1. Functions which could return nothing</p>\n<p>Oh boy #3. I&rsquo;ve got an example from the office, bear with me.</p>\n<p>In our Event management application there is a form field. This field represents a maximum limit on the number of holds for an event ticket. There are two types of input this field can receive from a user: 1) an integer or 2) nothing (ie, be left empty). The latter signifies that the user desires to unrestrict the number of holds.</p>\n<p>Nullable fields! These are quite commonplace and a user would never think twice about the dark alchemy we&rsquo;re performing behind the scenes. What the user doesn&rsquo;t know is that this field maps to a database columm that expects an integer (<code>INT</code>). Thus, when the user leaves the field empty and then submits the form, we need to make sure that an empty string is cast as a stringified representation of zero to slot in the POST body: <code>{limit: 0}</code>. Zero means unlimited. Leaving the field blank is not a <em>lack</em>, but bountiful! Nothing is not nothing. Logically sound, but conceptually wacky. A sensible default.</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">serializeFormData</span>(<span style=\"color:#a6e22e\">formData</span>) {\n  <span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">limit</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">formData</span>.<span style=\"color:#a6e22e\">limit</span> <span style=\"color:#f92672\">||</span> <span style=\"color:#ae81ff\">0</span>; <span style=\"color:#75715e\">// the empty input string is nullable!\n</span><span style=\"color:#75715e\"></span>  <span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">nextField</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#75715e\">//...\n</span><span style=\"color:#75715e\"></span>  <span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">body</span> <span style=\"color:#f92672\">=</span> {\n    <span style=\"color:#a6e22e\">limit</span>,\n    <span style=\"color:#a6e22e\">nextField</span>,\n    <span style=\"color:#75715e\">// ...\n</span><span style=\"color:#75715e\"></span>  }\n\n  <span style=\"color:#66d9ef\">return</span> <span style=\"color:#a6e22e\">body</span>;\n}\n</code></pre></div><p>Of course, a reverse alchemy must occur from the other direction when our React code initializes the form to begin with. We first hand our form builder an empty object &ndash; key/value pairs with field names as keys and <code>undefined</code>s as values. The builder then converts these <code>undefined</code>s to appropriate defaults.</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">function</span> <span style=\"color:#a6e22e\">getInitialFormData</span>(<span style=\"color:#a6e22e\">initialData</span>) {\n  <span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">limit</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">initialData</span>.<span style=\"color:#a6e22e\">limit</span> <span style=\"color:#f92672\">||</span> <span style=\"color:#e6db74\">&#39;&#39;</span>;\n  <span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">nextField</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#75715e\">//...\n</span><span style=\"color:#75715e\"></span>  <span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">initialFormData</span> <span style=\"color:#f92672\">=</span> {\n    <span style=\"color:#a6e22e\">limit</span>,\n    <span style=\"color:#a6e22e\">nextField</span>,\n    <span style=\"color:#75715e\">// ...\n</span><span style=\"color:#75715e\"></span>  }\n\n  <span style=\"color:#66d9ef\">return</span> <span style=\"color:#a6e22e\">initialFormData</span>;\n}\n\n</code></pre></div><p>Looks familiar.</p>\n<p>Thusly, the JavaScripter putzes around with a notion of <em>nothingness</em> by phase-shifting duck typed values.</p>\n<p><code>null</code> &lt;-&gt; <code>''</code> &lt;-&gt; <code>0</code></p>\n<p>(There&rsquo;s probably cooler mathematical notation for this.)</p>\n<p>Unforch we have to use <code>null</code> and friends for lack of a better optional option. Like, for lack of formal invariants in-language. It&rsquo;s impossible to truly prevent these meaningless <em>nothings</em> from entering our JavaScript programs. (Meaningless like may never receive meaning, ambiguous, undecided. Totally <code>void 0</code>: what a good euphemism from the grammar.) Like, you can&rsquo;t serialize <em>nothing</em> for a value an API response formatted as JSON.</p>\n<pre tabindex=\"0\"><code>&amp;gt;&amp;gt;&amp;gt; json.dumps({name: }\n  File &quot;&lt;stdin&gt;&quot;, line 1\n    json.dumps({name: }\n                     ^\nSyntaxError: invalid syntax\n</code></pre><p>Or try and stringify an <code>Object</code> back up again with the same:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">gt</span>;<span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">JSON</span>.<span style=\"color:#a6e22e\">stringify</span>({<span style=\"color:#a6e22e\">name</span><span style=\"color:#f92672\">:</span> })\n<span style=\"color:#a6e22e\">SyntaxError</span><span style=\"color:#f92672\">:</span> <span style=\"color:#a6e22e\">expected</span> <span style=\"color:#a6e22e\">expression</span>, <span style=\"color:#a6e22e\">got</span> <span style=\"color:#e6db74\">&#39;}&#39;</span>\n</code></pre></div><p><code>Null</code> and <code>undefined</code> are optional in JS but they are not illegal. Like in Haskell, which wraps up the ambiguity in a fat Nothing.</p>\n<p>Elliot does an interesting rhetorical jiu jitsu by giving us new options for optional values. In liue of eviscerating null from JS, we can work to push <code>null</code> to the edge of our programs with a handful of innovative approaches. In a sense we can ignore nullables and declutter areas of code which can just focus on data pipelining and other UI biz logic. Techniques include: constructing state machines &ndash; highly determined object interfaces &ndash; that error without values set to a wanted data type; ie <em>something</em>. We can also take advantage of that new new: Optional Chaining. And then there&rsquo;s borrowing from FP. The last I love.</p>\n<p>I&rsquo;ve already been thinking about Maybes a lot recently. My last post was about using &ldquo;maybe&rdquo; in function names to negotiate the unrealistic binary of if/else with better signaling to other developers; like, a function may or may not complete it&rsquo;s designated purpose if an async call fails or an argument is unacceptable. The real word is far too fuzzy. In contrast to the imperatives of JS, FP languages substitute nullable data with algebraic structures that encapsulate possibilities of existence or nothingness. For example, the actual <em>Maybe</em> data type represents either a <em>Just</em> (truth, success, completion) or <em>Nothing</em> (false, error, incompatibility). Data that&rsquo;s wrapped in a Maybe and operated on won&rsquo;t leak a nullable into our program, like the commonly observed <code>undefined</code>. Obviously implementations vary across libaries. Here&rsquo;s a simple example from the <a href=\"https://github.com/rametta/pratica\">Practica</a> library which demonstrates the way that using Maybe can simplify code:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">import</span> { <span style=\"color:#a6e22e\">Maybe</span> } <span style=\"color:#a6e22e\">from</span> <span style=\"color:#e6db74\">&#39;pratica&#39;</span>;\n\n<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">data</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#66d9ef\">await</span> <span style=\"color:#a6e22e\">fetchAllPeople</span>(...);\n\n<span style=\"color:#a6e22e\">Maybe</span>(<span style=\"color:#a6e22e\">data</span>)\n  .<span style=\"color:#a6e22e\">map</span>(<span style=\"color:#a6e22e\">people</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">people</span>.<span style=\"color:#a6e22e\">filter</span>(<span style=\"color:#a6e22e\">person</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">person</span>.<span style=\"color:#a6e22e\">cool</span>))\n  .<span style=\"color:#a6e22e\">map</span>(<span style=\"color:#a6e22e\">people</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">people</span>.<span style=\"color:#a6e22e\">map</span>(<span style=\"color:#a6e22e\">getNames</span>))\n  .<span style=\"color:#a6e22e\">map</span>(<span style=\"color:#a6e22e\">names</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">name</span>.<span style=\"color:#a6e22e\">toUpperCase</span>())\n  .<span style=\"color:#a6e22e\">cata</span>({\n    <span style=\"color:#a6e22e\">Just</span><span style=\"color:#f92672\">:</span> <span style=\"color:#a6e22e\">transformedData</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">render</span>(<span style=\"color:#a6e22e\">transformedData</span>),\n    <span style=\"color:#a6e22e\">Nothing</span><span style=\"color:#f92672\">:</span> () <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">console</span>.<span style=\"color:#a6e22e\">log</span>(<span style=\"color:#e6db74\">&#39;Womp, no data returned from API.&#39;</span>)\n  })\n</code></pre></div><p>(Btw, &ldquo;cata&rdquo; stands for <em>catamorphism</em> and means to decompose the Maybe container into simple values. Honestly, I&rsquo;m not good enough in the category theory yet to confidently distill it for you completely &ndash; pun intended &ndash; but that&rsquo;s the gist.)</p>\n<p>A more basic JS solution might look like:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">data</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#66d9ef\">await</span> <span style=\"color:#a6e22e\">fetchAllPeople</span>(...);\n\n<span style=\"color:#66d9ef\">if</span> (<span style=\"color:#a6e22e\">data</span>) {\n    <span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">coolPeople</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">people</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">people</span>.<span style=\"color:#a6e22e\">filter</span>(<span style=\"color:#a6e22e\">person</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">person</span>.<span style=\"color:#a6e22e\">kind</span>);\n\n    <span style=\"color:#66d9ef\">if</span> (<span style=\"color:#a6e22e\">coolPeople</span>.<span style=\"color:#a6e22e\">length</span>) {\n        <span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">formattedKindPeople</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">people</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">people</span>.<span style=\"color:#a6e22e\">map</span>(<span style=\"color:#a6e22e\">formatPersonForDisplay</span>);\n        <span style=\"color:#a6e22e\">render</span>(<span style=\"color:#a6e22e\">formattedKindPeople</span>)\n    } <span style=\"color:#66d9ef\">else</span> {\n        <span style=\"color:#a6e22e\">console</span>.<span style=\"color:#a6e22e\">log</span>(<span style=\"color:#e6db74\">&#39;Womp, only unkind people.&#39;</span>)\n    }\n} <span style=\"color:#66d9ef\">else</span> {\n    <span style=\"color:#a6e22e\">console</span>.<span style=\"color:#a6e22e\">log</span>(<span style=\"color:#e6db74\">&#39;Womp, no data returned from API.&#39;</span>)\n}\n</code></pre></div><p>The combination of FP-style data pipelining &ndash; allowed by Maybe&rsquo;s monadic interface, I think? &ndash; and control flow encapsulated in the data type itself, we get a semantically rich and easy-to-read solution without nullables and exhausting boilerplate; ie, param existence checks.</p>\n<p>Where Elliot really surprised me was drawing a line between FP&rsquo;s similar-to-Maybe data type <em>Either</em> and JS&rsquo;s Promise. Tucking <code>null</code> away with Promises is super neat. Let&rsquo;s see how that plays out in a sec.</p>\n<p>While maybes represent one or no value, Just or Nothing, Either implementations are slightly different in that they represent one <em>or</em> the other, but not both. If you&rsquo;re familiar with bitwise XOR, it&rsquo;s the same algorithm, except that in place of a Nothing or performing a noop, Eithers provide a secondary branch for an error case. Let&rsquo;s see it in action.</p>\n<p>Take Elliot&rsquo;s example of a small abstraction that hides <code>null</code> checking away in a kind of promisified ternary (which I&rsquo;ve slightly modified):</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">exists</span> <span style=\"color:#f92672\">=</span> (<span style=\"color:#a6e22e\">x</span>) <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">x</span> <span style=\"color:#f92672\">!==</span> <span style=\"color:#66d9ef\">null</span>;\n<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">ifExists</span> <span style=\"color:#f92672\">=</span> (<span style=\"color:#a6e22e\">value</span>) <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>;\n  <span style=\"color:#a6e22e\">exists</span>(<span style=\"color:#a6e22e\">value</span>)\n    <span style=\"color:#f92672\">?</span> Promise.<span style=\"color:#a6e22e\">resolve</span>(<span style=\"color:#a6e22e\">value</span>)\n    <span style=\"color:#f92672\">:</span> Promise.<span style=\"color:#a6e22e\">reject</span>(<span style=\"color:#e6db74\">`Invalid prop: </span><span style=\"color:#e6db74\">${</span><span style=\"color:#a6e22e\">value</span><span style=\"color:#e6db74\">}</span><span style=\"color:#e6db74\">`</span>);\n\n<span style=\"color:#a6e22e\">ifExists</span>(<span style=\"color:#a6e22e\">prop</span>.<span style=\"color:#a6e22e\">name</span>).<span style=\"color:#a6e22e\">then</span>(<span style=\"color:#a6e22e\">renderName</span>).<span style=\"color:#66d9ef\">catch</span>(<span style=\"color:#a6e22e\">log</span>);\n</code></pre></div><p>Here basic null checking and *primitive&quot; if/else binaries are replaced with a more expressive, semantically rich statement for the logical disjunction: proceed this way if success, or that way.</p>\n<p>Now, logging an error doesn&rsquo;t get us very far from param checking and early returns. A slightly more interesting example might be something like:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">inputExists</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">x</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">x</span> <span style=\"color:#f92672\">!==</span> <span style=\"color:#e6db74\">&#39;&#39;</span>;\n<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">ifInputExists</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">value</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">inputExists</span>(<span style=\"color:#a6e22e\">value</span>) <span style=\"color:#f92672\">?</span>\n  Promise.<span style=\"color:#a6e22e\">resolve</span>(<span style=\"color:#a6e22e\">value</span>) <span style=\"color:#f92672\">:</span>\n  Promise.<span style=\"color:#a6e22e\">reject</span>(<span style=\"color:#e6db74\">`Input is blank`</span>);\n\n<span style=\"color:#a6e22e\">onInput</span>((<span style=\"color:#a6e22e\">prevValue</span>, <span style=\"color:#a6e22e\">nextValue</span>) <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>;\n    <span style=\"color:#a6e22e\">ifInputExists</span>(<span style=\"color:#a6e22e\">nextValue</span>)\n        .<span style=\"color:#a6e22e\">then</span>(<span style=\"color:#a6e22e\">validate</span>)\n        .<span style=\"color:#66d9ef\">catch</span>(<span style=\"color:#a6e22e\">trackClearInput</span>(<span style=\"color:#a6e22e\">prevValue</span>))\n</code></pre></div><p>It&rsquo;s hard to see the real power of this for a simple resolve/reject example. It just feels like a fancy if/else, right? But if we extrapolate from this base interesting things start to happen. Here&rsquo;s a slightly modified version of an example from Practica&rsquo;s docs with an imaginary Either that uses Promises under the hood and implements a <code>chain</code> behavior:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">isPerson</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">p</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">p</span>.<span style=\"color:#a6e22e\">name</span> <span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">amp</span>;<span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">amp</span>; <span style=\"color:#a6e22e\">p</span>.<span style=\"color:#a6e22e\">age</span>\n  <span style=\"color:#f92672\">?</span> Promise.<span style=\"color:#a6e22e\">resolve</span>(<span style=\"color:#a6e22e\">p</span>)\n  <span style=\"color:#f92672\">:</span> Promise.<span style=\"color:#a6e22e\">reject</span>(<span style=\"color:#e6db74\">&#39;Not a person&#39;</span>)\n\n<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">isOlderThan2</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">p</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">p</span>.<span style=\"color:#a6e22e\">age</span> <span style=\"color:#f92672\">&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#ae81ff\">2</span>\n  <span style=\"color:#f92672\">?</span> Promise.<span style=\"color:#a6e22e\">resolve</span>(<span style=\"color:#a6e22e\">p</span>)\n  <span style=\"color:#f92672\">:</span> Promise.<span style=\"color:#a6e22e\">reject</span>(<span style=\"color:#e6db74\">&#39;Not older than 2&#39;</span>)\n\n<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">isJason</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">p</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">p</span>.<span style=\"color:#a6e22e\">name</span> <span style=\"color:#f92672\">===</span> <span style=\"color:#e6db74\">&#39;jason&#39;</span>\n  <span style=\"color:#f92672\">?</span> Promise.<span style=\"color:#a6e22e\">resolve</span>(<span style=\"color:#a6e22e\">p</span>)\n  <span style=\"color:#f92672\">:</span> Promise.<span style=\"color:#a6e22e\">reject</span>(<span style=\"color:#e6db74\">&#39;Not jason&#39;</span>)\n\n<span style=\"color:#66d9ef\">const</span> <span style=\"color:#a6e22e\">person</span> <span style=\"color:#f92672\">=</span> <span style=\"color:#a6e22e\">awaitfetchPerson</span>(...);\n\n<span style=\"color:#a6e22e\">Either</span>(<span style=\"color:#a6e22e\">person</span>)\n  .<span style=\"color:#a6e22e\">chain</span>(<span style=\"color:#a6e22e\">isPerson</span>)\n  .<span style=\"color:#a6e22e\">chain</span>(<span style=\"color:#a6e22e\">isOlderThan2</span>)\n  .<span style=\"color:#a6e22e\">chain</span>(<span style=\"color:#a6e22e\">isJason</span>)\n  .<span style=\"color:#a6e22e\">then</span>(<span style=\"color:#a6e22e\">p</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">console</span>.<span style=\"color:#a6e22e\">log</span>(<span style=\"color:#e6db74\">&#39;this person satisfies all the checks&#39;</span>))\n  .<span style=\"color:#66d9ef\">catch</span>(<span style=\"color:#a6e22e\">msg</span> <span style=\"color:#f92672\">=&amp;</span><span style=\"color:#a6e22e\">gt</span>; <span style=\"color:#a6e22e\">console</span>.<span style=\"color:#a6e22e\">log</span>(<span style=\"color:#a6e22e\">msg</span>)); <span style=\"color:#75715e\">// if any checks reject, then this function will be called. If isPerson rejects, then isOlderThan2 and isJason functions won&#39;t even execute, and the err msg would be &#39;Not a person&#39;\n</span></code></pre></div><p>Suffice to say I&rsquo;m quite tickled by the re-purposing of Promises as Eithers. You can start to imagine how one might construct custom-fit control flow <em>chains</em> and layer cakes using thenable types to play nicely with other function composition and pipelining. I&rsquo;m not always in love with (what feels like) sacrificed readability with chaining over stacked lines of assigned returns or async/await. But seeing it an action using Practica I&rsquo;m starting to believe more and more in its viability, even in a codebase touched by less experienced or new developers.</p>\n<p>Gripes with FP readability aside, it&rsquo;s eye-opening to look at available JS language features and see them in a different light. Also, aside from the clever use of Promises, just getting the null check into an abstraction <code>exists(...)</code> already has us using an FP mindset to build strong declarative (function-first) foundations.</stdin></p>\n",
        "date_published": "2019-12-10T15:13:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/12/10/maybe-eithers-with-promises.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/11/18/maybe-maybes.html",
        "title": "Maybe maybes",
        "content_html": "<p>Migrating my content from Medium was due, but this past week became a particularly opportune time to repost some old content on the subject of naming. Because I&rsquo;m in one of those feels again, y&rsquo;ll. And it&rsquo;s about one of the two hard things enshrined by Phil Karlton. Really we just float in a crisis of language trying to speak correct enough to make some money. Between thought and action. Between computer and person. Between persons.</p>\n<p><em>How do I communicate to the next developer that this function might do one thing, or it might do another?</em></p>\n<p>The other day I&rsquo;m refactoring some code and picking apart a function to understand how it works. Let&rsquo;s call this function <code>saveThing</code>. It&rsquo;s about 60 lines. Kinda medium-sized but a lot of lines are neat procedural steps of computation. The part that&rsquo;s quizzical to me is a condition that will exit the function if the user is missing a permission. So&hellip;sometimes this function won&rsquo;t save a thing.</p>\n<p>This is FUNKY. I want to rename the function to <code>maybeSaveThing</code> because the steadfast verbiage seemed incorrect. Like, literally it was signaling something wrong to me about its gist. I think I may have been particularly sensitive because I had already spent two days refactoring a bunch of code in this area and was becoming a bit exasperated with various kinds of misdirection. I really wanted the code to start being straight with me. But it&rsquo;s when we&rsquo;re weakest that we need the code to be <em>brutally</em> honest. Fixing critical bugs. Nearing deadlines. When stuff&rsquo;s happening at home. In the world. Ironically, these modes reveal the code&rsquo;s honest readability.</p>\n<p>But this could be a matter of style. I&rsquo;m not sure. I&rsquo;m mulling it over. I have colleagues who think <code>maybeSaveThing</code> isn&rsquo;t really necessary. The internal conditional is obvious enough once you peer inside. I think I&rsquo;m going to fight with them more about it.</p>\n<p>I felt validated when a homie from a JS community I hang with on Slack gave me an example of production code from his place of work:</p>\n<pre class=\"language-javascript\"><code>componentDidUpdate() {\n    this.maybeRedirect();\n    this.updateTitle();\n    this.maybeDoActivation();\n    this.maybeInjectSampleTimelineItems();\n},\n</code></pre>\n<p>I LOVE this. Don&rsquo;t you think it reads nicely? Like, you can really understand the sequence. The <em>maybes</em> communicate a true story of many possibilities. I&rsquo;m imagining refactoring this component transition block. These function names are helping me decide what to care about now or later; to <em>maybe</em> deal with them or not.</p>\n",
        "date_published": "2019-11-18T15:11:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/11/18/maybe-maybes.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/11/10/do-helper-for-emphasis-in.html",
        "title": "“do” helper for emphasis in variable naming",
        "content_html": "<p>However you mental wrap the process of realizing virtual things (writing, accretion, rose gardening), there’s no question literary-ness does imprint at some point on IDE surfaces. In my experience working in the higher stories of the tower (cloudgineering, we so high): up there with web pages, casually cast instructions inRuby and JavaScript, cascades in hierarchical CSS computer notation, and declarative document formatters (XML, HTML); up here you’re definitely notating control flows and arguments that require semblances to English lang. Arguments. Computer languages.</p>\n<p>The other day I surprised myself by forming an excited opinion during code review about what a variable should be called. I guess the time had done arrived; I had spent just enough time in Ember and client state management to become OCD about the signifiers being passed around. And so I found myself feeling incomplete when I read over a line of code announcing a state change event that facetChanged. I can’t totally explain it but this wording felt insufficient. I instinctively wanted more. Needed surge troops. Something like…facetDidChange.</p>\n<p>The difference is slight, but important.</p>\n<p>(It’s hard, y’all. One of two things.)</p>\n<p>I researched the grammar to figure out why the variable was letting me down.</p>\n<p>Turns out the “do” helping verb isn’t a special thing. But when added to another verb in the preterite, it increases emphatic assertion heaping deeper credibility on the thing that did happen. You can really feel it on your brain tongue, right? The additional slam ofd in the phrase, like doors shutting — the hardness more certain.</p>\n<p>Or maybe the reassurance is there because of the influence of the black/southern dialect on modern American english; the Shakespearian-like emphasis where past finality is hammered home when something done happened, or 2x emphasized when someone done did.</p>\n<p>The code doth protest too much??</p>\n<p>Eh, I didn’t push for a rewrite in the code review. Naming is a bar brawl and sometimes you fight and sometimes you don’t. The author is balancing empathy for their colleagues with their own mental frame of the application at the moment they create the code; and then there are many an english word and conventional abbreviations, degrees of formality and tone. There’s a reason Steve McConnell dedicates 30 pages on The Power of Variable Names. And this section doesn’t even explicitly tackle naming receivers, subscribers, etc…</p>\n<p>Just tryna make sense of what these users be doing.</p>\n",
        "date_published": "2019-11-10T15:10:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/11/10/do-helper-for-emphasis-in.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/11/07/more-about-anointed-princes-and.html",
        "title": "More about anointed princes and gatekeeping culture",
        "content_html": "<p>Ok, gonna brain dump a little because I got excited about some synergy! Maybe I&rsquo;m just really starting to find some peeps in the trillicon valley zeitgeist.</p>\n<p>Gee Paw Hill published a <a href=\"https://www.geepawhill.org/2019/11/01/thin-culture-and-stories/\">blog</a> a few days ago that retrospects on geek culture gatekeeping (I think we can basically proxy <em>software industry</em> for geek culture here). He presents this notion of our geek culture as &ldquo;thin culture&rdquo;; boundaried, exclusive. Lo and behold I was pleasantly surprised to see him use the phrase &ldquo;anointed princes&rdquo; to describe the folks &ndash; &ldquo;they&rsquo;re usually men&rdquo; &ndash; who perpetrate the thinness. Yay because this is nearly identical language I used in my <a href=\"#harmful-ways-to-write-about-software\">last post</a> for analyzing the behavior I saw in some other internet writing that made me feel poopy. I feel validated.</p>\n<p>Feels!</p>\n<p>I like that he backtracks the finger-pointing though; like, a fire with fire counter is a non-helpful meanness here. But also, I&rsquo;d argue some anger first is ok. &ldquo;Anger is clarifying&rdquo; &ndash; as Fleet Maull once told me many years ago. Or maybe a tool. Today during the Human Dimension of Business training at work we practiced the art of the <em>rant</em> &ndash; privately journal your story of blame &ndash; as a bridge step to toward truth and clarity; and as a way to measure and check our extra assumptions against the NVC-like framework (&ldquo;The facts are&hellip;&rdquo;, &ldquo;I feel&hellip;&rdquo;, etc&hellip;).</p>\n<p>There&rsquo;s some interesting stuff in Gee Paw&rsquo;s reflection. I feel armed with richer clues about where gatekeeping culture is inherited from, and inspired again to work with it in my own being.</p>\n<p>Loneliness, isolation, computer as friend, for some of these guys. I mean these are kind of obvious origin story props that will perpetuate harm and abuse across generations. It also may be a narrative setup for geek thinness that Gee Paw warns us to see for fiction.</p>\n<p>But I think, bringing his frame of three gatekeeping behaviors that keep our culture narrowly defined &ndash; &ldquo;badging, self-blindedness, atemporality&rdquo; &ndash; to any reading or conversation with the <em>anointed princes</em> in our industry will likely save us from feelings of smallness. (Those of us who came in through the side door; ie not academia). And to my fellow white dudes, it will help us break the cycle of abuse.</p>\n<p>Lets freestyle this a little bit:</p>\n<ul>\n<li>Not badging. &ldquo;I look like an eningeer.&rdquo; &ldquo;You look like an engineer.&rdquo; Ugh, let&rsquo;s not deploy the informal logical <a href=\"https://en.wikipedia.org/wiki/No_true_Scotsman\"><em>no true Scotsman</em></a> fallacy to move the goal post for what an engineer means. There&rsquo;s so much more to coding than producing code artifacts in a text editor.</li>\n<li>Self-awareness. &ldquo;My story is not the only story.&rdquo; Am I projecting my loneliness and sense of scarcity? Lately I&rsquo;ve really been feeling the idea that patriarchy teaches that there is a scarcity of power. If only there was someone capable of wielding the power that&rsquo;s there for the taking; then, then real change could be achieved. Why do we use an authorative voice in technical writing? Software is always so messy. Mastery should not be tied to self-worth.</li>\n<li>Historical. There used to be more women in tech but men kicked them out. Hidden figures. Our industry was born out of cold war-time fear. Our interview practices were designed to select codebreakers. Our greatest successes have created more work, not less; have created the perfect, legal, capitalistic social engineering appliance for foreign powers to influence our democracy.</li>\n</ul>\n",
        "date_published": "2019-11-07T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/11/07/more-about-anointed-princes-and.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/10/10/harmful-ways-to-write-about.html",
        "title": "Harmful ways to write about software",
        "content_html": "<p><em>Dispatch from Soekarno-Hatta International Airport.</em>\n<em>Arrived way too early because of traffic fantasies.</em></p>\n<p>While leafing through my daily software briefs I came across an article with that dissapointing refrain in our industry: <em>this should be easy to do</em>. There&rsquo;s probably no better way to put a reader on the defensive and create an adversarial teaching situation. Suddenly I&rsquo;m challenged to match the author&rsquo;s intellectual prowess or else remain befuddled and continue writing shitty code. Why you fuckin with my head???</p>\n<p>The article is another offering to the OO world which introduces the dependency indirection &ldquo;injectable factory&rdquo; design pattern as a cure for &ldquo;rigid direct dependencies&rdquo; in unit tests. Super simple stuff.</p>\n<p>Also just LOL the indexical disambiguation science of the OO world. I&rsquo;m just in love with Steve Yegge&rsquo;s satire about this. A true <a href=\"https://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html\">kingdom of nouns</a>. Frankly it&rsquo;s a deliciously bookish world compared to JS-land where it&rsquo;s function function function function.</p>\n<p>If I grokked it right, I think the article is just a way of instructing the use of mocks without dependency injection, helping you avoid writing a service implementation for your tests that looks like this:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-java\" data-lang=\"java\"><span style=\"color:#66d9ef\">public</span> <span style=\"color:#66d9ef\">class</span> <span style=\"color:#a6e22e\">OrderServiceImpl</span> implement OrderService <span style=\"color:#f92672\">{</span>\n  <span style=\"color:#66d9ef\">private</span> <span style=\"color:#66d9ef\">final</span> ShoppingCartService cartService<span style=\"color:#f92672\">;</span>\n  <span style=\"color:#66d9ef\">private</span> <span style=\"color:#66d9ef\">final</span> PricingService pricingService<span style=\"color:#f92672\">;</span>\n  <span style=\"color:#66d9ef\">private</span> <span style=\"color:#66d9ef\">final</span> InventoryService inventoryService<span style=\"color:#f92672\">;</span>\n  <span style=\"color:#66d9ef\">private</span> <span style=\"color:#66d9ef\">final</span> UserSession userSession<span style=\"color:#f92672\">;</span>\n  <span style=\"color:#66d9ef\">private</span> <span style=\"color:#66d9ef\">final</span> TimeProvider timeProvider<span style=\"color:#f92672\">;</span>\n  <span style=\"color:#75715e\">// ... and many more, this list will keep increasing when more requirements added\n</span><span style=\"color:#75715e\"></span>\n  <span style=\"color:#66d9ef\">public</span> <span style=\"color:#a6e22e\">OrderService</span><span style=\"color:#f92672\">(</span>\n      ShoppingCartService cartService<span style=\"color:#f92672\">,</span>\n      PricingService pricingService<span style=\"color:#f92672\">,</span>\n      InventoryService inventoryService<span style=\"color:#f92672\">,</span>\n      UserSession userSession<span style=\"color:#f92672\">,</span>\n      TimeProvider timeProvider<span style=\"color:#f92672\">)</span> <span style=\"color:#f92672\">{</span>\n    <span style=\"color:#66d9ef\">this</span><span style=\"color:#f92672\">.</span><span style=\"color:#a6e22e\">cartService</span> <span style=\"color:#f92672\">=</span> cartService<span style=\"color:#f92672\">;</span>\n    <span style=\"color:#66d9ef\">this</span><span style=\"color:#f92672\">.</span><span style=\"color:#a6e22e\">pricingService</span> <span style=\"color:#f92672\">=</span> pricingService<span style=\"color:#f92672\">;</span>\n    <span style=\"color:#75715e\">// ....\n</span><span style=\"color:#75715e\"></span>  <span style=\"color:#f92672\">}</span>\n\n  <span style=\"color:#66d9ef\">public</span> CreateOrderResponse <span style=\"color:#a6e22e\">createOrder</span><span style=\"color:#f92672\">(</span>CreateOrderRequest req<span style=\"color:#f92672\">)</span> <span style=\"color:#f92672\">{</span>\n    <span style=\"color:#75715e\">// ...\n</span><span style=\"color:#75715e\"></span>  <span style=\"color:#f92672\">}</span>\n<span style=\"color:#f92672\">}</span>\n</code></pre></div><p>Ah yeah that looks hairy. I&rsquo;m flashing to Jest unit tests where small function implementation details are mocked all the way down.</p>\n<p>I remember a moment, a phase if you will, in my first couple of years working professionally as a softwhere engineer when I thought that understanding OO design patterns was part of our right of passage into&hellip;seniority, I guess? At the time I was beginning to write more in the Rails parts of our codebase and as a consequence, began inheriting a pressure, a notion &ndash; from where I&rsquo;m not sure &ndash; to achieve familiarity with common OO design patterns.</p>\n<p>From where, indeed. It&rsquo;s really subtle how this worldview is propogated amongst our ilk but I think I&rsquo;m starting to see, with clear eyes, the quiet, viral expansion.</p>\n<p>For example, this digesis about &ldquo;injectable factory&rdquo; thats got me irked. When the author completes the situation and complication setup, he begins his solution section with:</p>\n<p>&gt; The pattern is pretty simple.</p>\n<p>Umm great, so what you&rsquo;re proposing is just a fancy name for something I probably already know about? But then:</p>\n<p>&gt; It’s implemented as a mutable value holder. This pattern is related to the factory, service locator, singleton pattern and ambient context pattern. All these patterns are considered anti-patterns according to most DI articles. But in practice, those patterns, especially singleton, are very handy and useful. They are prevalent in almost every non-trivial project. But they come with caveats. InjectableFactory tries to prevent those caveats at the same time keep the convenience and simplicity of those patterns.</p>\n<p>It&rsquo;s so simple I just need to have a solid undertanding of these (what must be other simple) concepts as well:</p>\n<ol>\n<li>dependency injection</li>\n<li>a value holder (probably Java slang for some kind of variable?)</li>\n<li>mutable value holder</li>\n<li>factory pattern</li>\n<li>service locater pattern</li>\n<li>singleton pattern</li>\n<li>ambient context pattern</li>\n</ol>\n<p>I&rsquo;m reminded of Rich Hickey&rsquo;s 2012 Rails Conf <a href=\"https://www.youtube.com/watch?v=rI8tNMsozo0\">talk</a> where he disambiguates <em>simple</em> from <em>easy</em> which is a linguistic casuality which creates confusion in our industry about what &ldquo;simple&rdquo; or &ldquo;easy&rdquo; software really is or achieves. In the talk Hickey helps recoup a specificity for each word through an etymological tracing. Distilled you take away that <em>simple</em> is objective and <em>easy</em> is relativistic.</p>\n<p>In consideration of the foregoing, our Javian knight likely means <em>easy</em>, which, by Hickey&rsquo;s redefinition (rather reinstatement of acuity), means a spacial relativism of <em>nearness</em>. As in <em>easy to go to or get</em> or near to our understanding. In other words <em>familiar</em>. Like a better developer experience. Like:</p>\n<p>&gt; &hellip;can I get this instantly and start running it in five seconds?</p>\n<p>But he probably also means <em>&ldquo;being near to our capabilities&rdquo;</em>, the promise of easy.</p>\n<p>Even if the usage intent is closer to Hickey&rsquo;s <em>easy</em>, what about this list of like seven things I need to know that may not be near my capabilities? Like, easy for whom? What type of reader is summoned here? Since the author never names his imagined reader/audience we&rsquo;ll never know for sure, but we can infer it&rsquo;s likely folks who are experts in OO and the Java lang. Perhaps that&rsquo;s the transgression that bothers me. This invocation of <em>simple</em> to self anoint as meister amongst a court of meisters, but without warning patronizingly forecloses access for an unitiatied reader. I think this is the gatekeeping emerging, infectiously. Almost too quickly to observe. I&rsquo;m really glad Hickey also finds circumscribing code as <em>easy</em> dangerous for our industry&rsquo;s wellbeing:</p>\n<p>&gt; And we don&rsquo;t like to talk about this because it makes us uncomfortable because what kind of capabilities are we talking about? If we&rsquo;re talking about easy in the case of violin playing or piano playing or mountain climbing or something like that, well, you know, I don&rsquo;t personally feel bad if I don&rsquo;t play the violin well because I don&rsquo;t play the violin at all.</p>\n<p>&gt; But the work that we&rsquo;re in is conceptual work, so when we start talking about something being outside of our capability, well, you know, it really starts trampling on our egos in a big way. And so, you know, due to a combination of hubris and insecurity, we never really talk about whether or not something is outside of our capabilities. It ends up that it&rsquo;s not so embarrassing after all because we don&rsquo;t have tremendously divergent abilities in that area.</p>\n<p>Sigh. The deleterious effect of gatekeeping. Like is there some insecurity at play here for the author that requires he front his meisterness?</p>\n<p>Though what if&hellip;I wonder if the author actually intended to describe injectable factory as <em>simple</em> by Hickey&rsquo;s definition? As in, requiring less effort to &ldquo;repurpose, substitute, move, combine, extend&rdquo;, and less coupled (&ldquo;interleaved&rdquo;). The root of the word is <em>one fold, braid, or twist</em>. That does seem to be accomplished in the design. Nevertheless, I can&rsquo;t get over the heavy connotation of reader culpability and capability implied in the (weak) qualification of &ldquo;pretty simple.&rdquo; Language is weird.</p>\n<p>I&rsquo;m thinking it&rsquo;s probably best to avoid &ldquo;simple&rdquo; and &ldquo;easy&rdquo; in technical writing. Let&rsquo;s not fuzzy match.</p>\n<p>This reminds of when the words <em>good</em> or <em>bad</em> are used when discussing code. Without more objective substance, <em>simple</em> evidence, they just do a big hand-wave over facts and truths of the software&rsquo;s outcomes and the shared understanding of the folks in the conversation. Is the software reliable, easy to change? What level of expertise is required, what audience are you interpolating into this discourse of nouns?</p>\n<p>Is simplicity achieved?:</p>\n<p>&gt; There are tons of libraries that look, oh, look, there&rsquo;s different classes; there&rsquo;s separate classes. They call each other in sort of these nice ways, right? Then you get out in the field and you&rsquo;re like, oh, my God! This thing presumes that that thing never returns the number 17. What is that?</p>\n<p>Is easiness achieved?:</p>\n<p>&gt; &hellip;can I get this instantly and start running it in five seconds?</p>\n",
        "date_published": "2019-10-10T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/10/10/harmful-ways-to-write-about.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/10/06/a-better-term-for-unintentional.html",
        "title": "A better term for unintentional technical debt",
        "content_html": "<p>The other day I got into a tiff with coworkers during our retro sailboat exercise, hunched over stickies and milling about thoughtfully. Abruptly, I leaped from my chair and smacked a note on the whiteboard: <em>application too big</em>. Did this qualify as technical debt, and therefore start in motion various debt protocols and procedures (tagging, itemizing, scoping, slotting, mapping&hellip;).</p>\n<p>The damned slice of monorepo which we had been toiling in since last sprint was damaging our pace  with a super bloom of contributions from different teams. The code was getting hard to reason about, we were feeling immobile amidst the swarm; it was getting too <a href=\"https://blog.jessitron.com/2019/09/26/from-complicated-to-complex/\">complicated</a>:</p>\n<p>&gt; It has many interconnected parts, each full of details. Conditionals abound, forming intricate rules that may surprise us when we read them.</p>\n<p>Lately I&rsquo;d been thinking about debt as the future IOW on quality to increase speed in the present. A somewhat common definition. But that definition didn&rsquo;t seem to characterize what I had slapped on the board. By that narrow definition, if this nuanced latticework were debt, we&rsquo;d be able to rustle up the ledger, analyze the running amortization plan, protocls and procedures and so far and get eh work scheduled or assigned as noop or what-have-you. Yet, but nope, to think of complicated code emerging from a combination of variegated knowledge across teams, and the teleologic weight of entropy (bit rot, cruft, and so forth) &ndash; that didn&rsquo;t situate in Cunningham&rsquo;s metaphor for me. All this new code was showing up as a stunning kind of surprise not as a calculated tradeoff.</p>\n<p>Perhaps other sources of debt people discuss could help us understand our current morass? Could it be situated as procrastination, not revisiting architecture, postponing test-writing? I don&rsquo;t think so. I truly believe the teams working in this code were doing right by all these additions.</p>\n<p>Then there&rsquo;s the category of &ldquo;unintentional&rdquo; debt. But that still missed. There was an aspect of stuff out of our control but the intent/unintent dichotomy felt unsatisfying if do, in fact, believe that software is a rich system of people, code, automations, feedbacks&hellip;I don&rsquo;t know. Language is hard. I guess I&rsquo;m gliding at the edges of a linguistic constraint with the lexicon that was tossed around the table by my colleagues. Some sort of <em>weak</em> Sapir–Whorfian <a href=\"https://en.wikipedia.org/wiki/Linguistic_relativity\">confusion</a> that I couldn&rsquo;t peak around.</p>\n<p>Nonetheless, I conceded to my fellow engineers &ndash; to wares that are soft:</p>\n<p><strong>ok, fine, this debt that so cunningly creeped with bold surprise was, in fact, a (indefinite) form of technical debt</strong></p>\n<p>In fact again, the frame I particularly appreciated was this: while it may not have been a result of a conscious decision, now that we observed this mucky muck we could <em>choose</em> to deal with it as debt. Ok, debt is debt whether it arrives by forethought or entropy.</p>\n<p>Luckily, as I was catching up on my daily doses of software newsletters this morning, jessitron (who I can&rsquo;t stop quoting) hyperlinked her latest <a href=\"https://blog.jessitron.com/2019/10/05/dont-just-keep-trying-report-your-limits/\">blog</a> to another <a href=\"https://blog.atomist.com/whats-lurking/\">post</a> from the Atomist site that gives us what I think is a more accurate language for this very type of technical debt. Frankly, any optimistic (re)casting of language in our field is welcome; we&rsquo;re so prone to a feeling of unfinished, incomplete, or overwhelmed, everything is fine (eh, nope).</p>\n<p>&gt; Technology drift is a form of technical debt that comes from progress. As our target architecture advances, it leaves a trail of projects in all its momentary incarnations. As repositories proliferate, the accumulation holds us back. We have many technologies and many versions of each. We have the risks of all of them.</p>\n<p><mark>TECHNICAL DRIFT</mark></p>\n<p>Fuck yeah, let&rsquo;s use that!</p>\n",
        "date_published": "2019-10-06T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/10/06/a-better-term-for-unintentional.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/10/01/two-tales-of-binary-search.html",
        "title": "Two tales of Binary Search",
        "content_html": "<p>I still have lingering rage from two years ago when an interviewer said to me: &ldquo;I could probably implement this in about 20 minutes.&rdquo; Seriously crushing words to utter offhand during a facetime code screen for someone who has been programming and building web apps professionally for 3+ years.</p>\n<p>The problem was something like <em>find the nearest value to x in the array</em>. I&rsquo;m so bad at toy algorithm questions since I basically spent those first 3sh years smashing a ton of Rails and Ember into my brain and worked to be productive building more typical business app/e-commerce style UIs. I wasn&rsquo;t a whiz at data traversal. More like a deep component interface expert. What else would you call it? Suffice to say a simple <em>filter</em> function at 0(n) time would satisfy the requirements. That is lived experience.</p>\n<p>But my interviewer pushed me to consider a big fat array. I was stumped, and failing hard in the spotlight. <em>Only 20 minutes</em>. Bro even let me spend some time after the interview coming up with a solution to email later, but that was futile. I didn&rsquo;t even know how to properly phrase the problem for Google. I got rejected.</p>\n<p>What I learned later is that bro was looking for a solution implementing binary search &ndash; something any CS grad would know. I didn&rsquo;t have a CS background. I learned to program on the job and never had to care about that level of performance in the apps I worked on.</p>\n<p>To this day, around 6 years into my career, I haven&rsquo;t had to implement a binary search algorithm to scan over a big data set.</p>\n<hr>\n<p>Julia Evans put out a short series of zine pages recently that describe best practices for debugging. And guess who showed up? Binary search! Leaning back at my desk chair I realized that all along I&rsquo;ve been using binary search in my every day work.</p>\n<p>When fixing a bug without a useful stack trace, triangulating the problematic code requires what I used to think as a kind of cludgy technique: step by step, commenting out large parts of the code at the top and/or bottom of suspect files. Like, literally just comment out half the file where you think the buggy code lives. Does the error still throw? If yes, the problem is not in that half. Try commenting out the other half. If no, then keep halving that part of the file. Recursively repeat. This is binary search. Also, did you notice we&rsquo;re now also talking about recursion, a topic that even senior programmers have trouble with?</p>\n<p>&ldquo;Advanced&rdquo; CS concepts can show up in our work all the time. Whether it&rsquo;s UI, backend, databases, ops, throughout all layers of this mushy cake stack. (&ldquo;Mushy&rdquo; as in blended, bleeding, fluid, transitional. Not as in gross, unfit, unstable.) We need to begin reconciling with the danger of narrowly defining their employ and weaponizing them in toy code examples for gatekeeping (cough cough interviewing).</p>\n<p>When we learn the meaning behind these CS concepts, we may actually discover more creative ways to use them. Or how they are already part of our toolkit. For example, <em>git-bisect</em>!</p>\n",
        "date_published": "2019-10-01T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/10/01/two-tales-of-binary-search.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/09/16/deeper-software-concepts-showing-up.html",
        "title": "Deeper software concepts showing up in UI problems",
        "content_html": "<p>I&rsquo;ve got three posts in my brain backlog now about more complex software concepts showing up in UI work. Here&rsquo;s the first!</p>\n<p>I&rsquo;ve been waiting for years, thumbing a bitwise operator curiously. Finally the opportunity presented itself the other day.</p>\n<p>Writing UI, most of the time the basic comparison and logical operators of JavaScript give us the power and control we need to deliver product requirements. Equal, not equal, AND, OR, NOT, etc.. But then there&rsquo;s that arcane set of <strong>bitwise</strong> comparison operators. These special boolean operators give us expressiveness for more complex comparison scenarios. Their weirdness stems from the fact they do comparisons at the binary integral level. They coerce the values to bits first, far from view.</p>\n<p>Take XOR &ndash; &ldquo;exclusive OR&rdquo;. In JavaScript XOR will return <code>1</code> when the output of either side of the operator is different, else 0. Similar to a boolean return, we can easily pass around the result of a bitwise operator as a predicate.</p>\n<p>As it turns out, this happens to be the very logic we need for testing existence between two dependent form fields on the frontend.</p>\n<p>At Eventbrite, the UI library has graphical pickers for both date and time fields that we use in Event creation workflows. Our designs typically place these fields next to each other and make them required. We provide sensible defaults, but event creators can freely modify the values, unpredictably, even nulling them out. For example, it&rsquo;s possible for the user to leave one field blank. We want to give event creator immediate feedback before they go on to other tasks on the page. If they put the form in this state, we run a validation on blur. And we can do it using XOR logic!</p>\n<p>Nevertheless, for checking existence, we don&rsquo;t want to bitwise compare the two sides of the expression directly. These fields liberally capture data as strings (versus ints, datetime, etc&hellip;). To make the comparison reliable, we first cast each side to boolean values with using bangs for brevity. Then we wrap up the expression in a composable function. The result is a very concise one-liner:</p>\n<pre class=\"language-javascript\"><code>const isOneTruthyAndTheOtherNot = (a, b) =&gt; !a ^ !b;</code></pre>\n<p>Which might be passed around in a hypothetical React event handler like:</p>\n<pre class=\"language-javascript\"><code>dateTimeValidator: (dateValue, timeValue) =&gt; {\n    const hasEmptyField = isOneTruthyAndTheOtherNot(dateValue, timeValue);\n    const error = hasEmptyField ? FORM_ERRORS('dateTimeField') : null;\n\n    this.setState({\n        dateTimeFieldError: error\n    }\n\n    this.props.onError(error)\n}\n</code></pre>\n<p>This could be written in a couple ways without the more arcane XOR:</p>\n<pre class=\"language-javascript\"><code>... = ( foo &amp;&amp; !bar ) || ( !foo &amp;&amp; bar );\n... = foo ? !bar : bar\n</code></pre>\n<p>But those expressions are tough to mentally load on glance. On the other hand, the bitwise operators are clever, but the single operator is a standard interface. Even a less experienced engineer can quickly reference the MDN docs which are crystal clear about how the XOR algorithm works:</p>\n<p>&gt; &ldquo;Performs the XOR operation on each pair of bits. a XOR b yields 1 if a and b are different&rdquo;</p>\n<p>The docs will also introduce you to the algorithmic decision table for the operator logic, which is a great learning device for engineers of all levels.</p>\n<pre tabindex=\"0\"><code>|  a  |  b  | a XOR b |\n| :-: | :-: | :-----: |\n|  0  |  0  |    0    |\n|  0  |  1  |    1    |\n|  1  |  0  |    1    |\n|  1  |  1  |    0    |\n</code></pre><p>What always makes this sort of exposé interesting to me is that we get a chance to trouble the early-web understanding of UI as document structure and style. There&rsquo;s still too much emotional labor educating the web dev community about complexity throughout all layers of what&rsquo;s becoming an increasingly mushy layer cake stack. Computer science in form logic. Like blended, bleeding, fluid, transitional. Not the pejorative gross, unfit, or unstable.</p>\n",
        "date_published": "2019-09-16T15:04:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/09/16/deeper-software-concepts-showing-up.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/07/31/react-inline-function-gotcha-but.html",
        "title": "React inline function gotcha, but in a non-obvious way",
        "content_html": "<p>I think a lot about Hillel Wayne’s blog post <a href=\"https://www.hillelwayne.com/post/persuasive-examples/\"><em>INSTRUCTIVE AND PERSUASIVE EXAMPLES</em></a>: an interpolative critique of a best practice article on unit testing.</p>\n<p>Wayne argues that “instructive” examples don’t make a reader care. In contrast, we should labor harder to craft “persuasive” examples that attempt to satisfy simian desiring machines:</p>\n<p>&gt; 1.  If your example is too simple, people brush it off.\n&gt; 2.  If your example is too complicated, people won’t follow. They’re also less likely - to trust it, because you complicated example might be concealing a simpler way.\n&gt; 3.  If your example is too abstract, people won’t see how it’s useful in practice.\n&gt; 4.  If your example is too concrete, people won’t see how it generalizes to their own - problems.</p>\n<p>We see examples of #1 and #4 all of the time in technical writing – maybe because a lot of it is written for marketing purposes.</p>\n<p>Extrapolating Wayne’s plea: let’s be careful about how we present anti-patterns and best practices when we’re trying to thought leader. Often this writing ends up being spec or framework documentation plagiarized and adorned with gifs. But without contextual complexity we may be doing a disservice to our fellow humans who dev – especially less experienced devs.</p>\n<p>Persuasive examples are harder but the payoff is bigger. By <em>demonstrating</em> the why and why not there’s a better chance of putting knowledge into your reader’s brain and making it stick. This is certainly my experience. If you:</p>\n<ol>\n<li>Share the reasoning behind all of the small decisions getting from A to B, or determining why A or B is important</li>\n<li>Give me code that looks more like code “in the wild”</li>\n<li>Contextualize your example as either a novel approach or re-visitation</li>\n</ol>\n<p>To wit. (An attempt at a persuasive example.)</p>\n<p>Just this week I toiled on a bug with a colleague that ultimately turned out to be a case of a classic React anti-pattern where an inline function declaration caused undesirable re-renders of a Pure Component.</p>\n<p>Now, I’ve definitely read at least a 3–4 <em>instructive</em> articles on the pitfalls of declaring functions inside of <code>render()</code>. Perf implications and unnecessary function creation, etc…. But that insight didn’t help me – or my similarly schooled – colleague come to resolution with any alacrity. We failed spectacularly to bring our academic rigor to bear because we weren’t working with sandboxed toy code from instructive examples. The root cause became obvious only after hours of thought-work finally revealed <em>where</em> the problem code even was.</p>\n<p>Again, finding problematic inline functions in something like this triviality of Hillel’s lament would, of course, be much easier:</p>\n<pre class=\"language-javascript\"><code>render() {\n    return (\n        <button> this.setState(…)}&gt;\n            Click Me\n        </button>\n    )\n}\n</code></pre>\n<p>But in our case, the problem function was buried in a nested component wrapped in a separate constructor function and abstracted into a separate helper in a separate file and blah dee blah…you get the point. Our journey was starting miles from <code>render()</code>.</p>\n<p>Our code better resembled:</p>\n<pre class=\"language-javascript\"><code>// Template.js\nexport default (...props) =&gt; {\n    // ...\n    const Sidebar = connectSidebar(Sidebar);\n    const Main = connectMain(Main);\n\n    return ;\n}\n\n// Page.js\nimport Template from `./Template`;\n\nexport class Page extends Component {\n    // ...\n    render() {\n        return (\n            &lt;- Template {...props} /&gt;\n        )\n    }\n}\n</code></pre>\n<p>The bug was observed when a user clicks the “Buy on Map” button in the Sidebar. The click was getting swallowed and not transitioning the view.</p>\n<p>So what was going on?</p>\n<p>When we dug deeper we noticed that at the moment of click an unwanted blur event would be triggered on the form field in the <code>&lt;main&gt;&lt;/main&gt;</code> component; which would update its state. This redux-form state update would then ripple through the component tree and cause the sidebar to be re-rendered, even though none of the props passed to <code>&lt;sidebar&gt;&lt;/sidebar&gt;</code> had changed. The result was the sidebar button getting re-rendered <em>in the middle of the click event</em>; which meant the click handlers of the newly rendered button were not capturing the click and able to transition to the next view! Client concurrency issues.</p>\n<p><img src=\"https://internetross.space/uploads/2020/57a595de41.jpg\" alt=\"Inline gotcha funtimes\" title=\"inline_gotcha_funtimes.jpg\"></p>\n<p>One hack we considered was changing the <code>onClick</code> handler of the sidebar button to <code>onMouseUp</code> – the newly rendered button could seemingly receive that event just fine in the thrash sequence (browsers are weird). But we knew our bandage likely wouldn’t last long, o we decided to troubleshoot the real issue: the unnecessary re-renders of the sidebar upon field blur.</p>\n<p>After binary searching the code up and down <code>&lt;page&gt;&lt;/page&gt;</code>, deleting chunk by chunk until the re-renders stopped, we discovered the fix to be fairly straight forward. Just move the invocation of <code>connectSidebar</code> and <code>connectMain</code> outside of the <code>Template</code> function context into the module context.</p>\n<pre><code>// Template.js\nconst Sidebar = connectSidebar(Sidebar);\nconst Main = connectMain(Main);\n\nexport default (...props) =&amp;gt; {\n  // ...\n  return ;\n};\n</code></pre>\n<p>After this mod, when <code>&lt;layout&gt;&lt;/layout&gt;</code> was rendered, the child component passed as the prop <code>sidebar</code> wouldn’t be invoked – it’s already been invoked and the return value of the component has been assigned. In other words, we are not creating a new function in memory and executing it fresh every time <em>just like all those instructive examples say!</em></p>\n<p>Sigh. We likely ended up in this place by not being careful with nested connectors and their subscription boundaries. Sometimes you forget that it’s just functions all the way down. Like, declaring and assigning a component constructor inside another component constructor would not be how you’d typically compose your functions. I will humbly accept this not uncommon (read: forgivable) symptom of “bottom-up” programming. (See David Kourshid’s <a href=\"https://www.youtube.com/watch?v=RqTxtOXcv8Y\">talk</a> about finite state machines and the sad stories of “bottom-up”).</p>\n<p>In sum, unlike the pristine nirvanic fields of instructive examples, we make our bed in large projects born from large organizations – cue Conway’s law. The requirements for the application accrete in fantastic ways over time. Cue McConnell’s oyster farms. The primitives you start with to satisfy embryonic requirements, like a root-level <code>&lt;page&gt;&lt;/page&gt;</code> component, may just become one large prop-drilled well. Graph hell.</p>\n<p>This means you suddenly find yourself debugging why a click event on a sidebar button is being swallowed. You notice the divs are flashing in the Elements tab of Chrome dev tools, which means the browser is repainting the sidebar on click – re-renders!</p>\n<p>Ok, so instructive examples won’t necessarily help you. But I’ll add an asterisk and deign they aren’t worthless either. Because I’ve read these instructives, I am able identify and classify this bug <em>post facto</em> as a commonly known React problem – that is, a problem with React composition not a problem inherent to React – because the instructive examples are out there contouring a problem space and a shared vocabulary. I can then use this shared language when communicating the <em>what</em> or <em>what caused this…</em> during a retrospective or or incident report. Notwithstanding, we should endeavor to be better.</p>\n",
        "date_published": "2019-07-31T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/07/31/react-inline-function-gotcha-but.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/07/13/closed-connections.html",
        "title": "499 closed connections",
        "content_html": "<p>Bugs reveal. I look, observe. I learn things. I just experienced another one.</p>\n<p>The customer can&rsquo;t <em>publish</em>. Ensue existential <a href=\"https://vimeo.com/157670461\">how come???</a></p>\n<p>After poking around I noticed our client code was deleting a parent entity too eagerly during a fail case while create operations were in flight for hiearchically bound entities &ndash; too sanguine, our home-backd front-end  <code>ROLLBACK</code>. If the parent save call failed, subsequent saves of child data would nevertheless proceed, leaving unhooked child data stranded in the db. When the user would later hit &ldquo;Publish&rdquo;, our system would crash, unable to reconcil the ill-begotten state.</p>\n<p>Take a look at the code (simplified for example):</p>\n<script src=\"https://gist.github.com/rosschapman/2d75d45892720f70672fb0b4f5625a3c.js\"></script>\n<p>Can you see how this code was written a bit too simplistically? From what I can tell there are at least two latent problems that make this code prone to fail in a way we don&rsquo;t want.</p>\n<ol>\n<li>\n<p>First, a parse error may be thrown during &ldquo;other synchronous things&rdquo; after the <code>saveChildEntity</code> promise is fulfilled. See a contrived example of that: <a href=\"https://codesandbox.io/embed/asyncawait-with-synchronous-error-7c7d5?fontsize=14\">async/await with synchronous error</a></p>\n</li>\n<li>\n<p>Second, it&rsquo;s possible that the POST request initiated by <code>saveChildEntity</code> may succeed on the backend and persist the child data, but the connection between browser and server may be severed before the browser recieves the <code>200</code> and the promise becomes fulfilled! When that happens, the promise is actually rejected and the runtime goes into the catch block.</p>\n</li>\n</ol>\n<p>In the end, it was the latter.</p>\n<p>It seems obvious in retrospect. We allow the user to hit Publish anytime which kicks off a heavy network sequence that finishes with a full page reload. Yet, while the publish sequence is in flight the user can still interact with the page. Meaning they could click another visible button &ndash; &ldquo;Save&rdquo; &ndash; that triggers <code>saveStuffThunk</code>. Based on the server logs, it seems that fairly often the Publish sequence would complete and then start to reload the page <em>right in the middle</em> of the second <code>try/catch</code> block of <code>saveStuffThunk</code>. When that happens <code>nginx</code> sends down a special <code>499</code> status code meaning <em>the client closed the connection before the server responded with a request</em>. The client code then interprets this as an error and sends the runtime into the catch-delete block.</p>\n<p>The server logs (simplified):</p>\n<ul>\n<li>POST /save/<id></li>\n<li>DELETE /<id> 499</li>\n</ul>\n<p>It still blows my mind this happened consistently to effect hundreds of records. The browser deterministically queues/coordinates? It was a very strange UX-driven race condition.</p>\n<p>In addition to realizing that our thunk code was written too optimistically, another aspect of this bug that fascinates me was the discovery that we had missed the <em>really really</em> important requirement of locking the page for the user when they click the &ldquo;Publish&rdquo; button. This was actually implemented for other similar interfaces, but when my team implemented a new screen with similar access to the &ldquo;Publish&rdquo; button, we didn&rsquo;t fully understanding the potentiality of allowing this race condition. Or how to prevent it.</p>\n<p>Organizational debt becoming bug. A big complex system with fast-shifting pubertal code and fugitive ownership creating blind spots.</p>\n<p>&gt; &ldquo;Every existing feature, and even past bugs, makes every new feature harder. Every user with expectations is a drag on change.&rdquo; - <a href=\"https://blog.jessitron.com/2019/06/17/feature-interaction/\">jessitron</a></p>\n<p>It was a weird one but we observed some new things and thereby pushed our learning edge farther out.</p>\n<p>Like, tangential learning came from investigating potential sources of 499s. While digging, folowing a hunch about the load balancers sitting in front of our API servers, I discovered that connections could be cancelled eagerly by such a load balancer upon a timeout. Because Publishing was a long-ish operation, at one point in the debugging adventure we surmised a heavy query might be exceeding the a timeout interval. See: <a href=\"https://stackoverflow.com/questions/12973304/nginx-499-error-codes#comment98898883_18410932\">Nginx 499 error codes</a>. Nevertheless that was a false start; our ops folks were able to confirm we didn&rsquo;t have load balancers managing these particular requests.</p>\n<p>Demystifying architecture is an important part of this process for the perspicacious dev.</p>\n<p>I&rsquo;m just hard reflecting on how signals of &ldquo;broken&rdquo; &ndash; like bad data &ndash; can reveal many interesting things about the system. Just think about how much our client promise handling hid national treasures.</id></id></p>\n",
        "date_published": "2019-07-13T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/07/13/closed-connections.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/06/24/debugging-a-test-that-does.html",
        "title": "Debugging a test that does nothing",
        "content_html": "<p>This weekend I spotted Julia Evans posting tips about debugging &ndash; of course a zine quickly followed. This  resonated deeeply because it touches on one aspect of debugging that I often struggle with. It&rsquo;s comforting to know this is a common kind of struggle!</p>\n<img src=\"https://softlydeveloping.micro.blog/uploads/2026/e4cea74c97.jpg\" width=\"600\" style=\"margin: 0 auto; display: block\">\n<p>What Evans articulates so well is how we are always standing in a muddy, vast ecology. When we sit down and begin to debug a single piece of a program we start by gathering all the things we think we know to be true. But we&rsquo;re already at a loss. Our starting point is an incomplete, locally maximal set of facts about how the program <em>should</em> work based on a collection of initial assumptions from a limited field of reasoning. We&rsquo;re fenced off, bounded.</p>\n<p>Assumption is what makes the debugging process laborious. Each attempt to decipher error output or logs becomes a heated, lasting tango between your assumptive limit and proofs against the current reality. Herbert Simon, who coined the term &ldquo;bounded rationality&rdquo;, describes humans in this mode (quoting from Donella Meadows):</p>\n<p>&gt; blundering “satisficers,” attempting to meet (satisfy) our needs well enough (sufficiently) before moving on to the next decision. (p106, <em>Thinking in Systems</em>)</p>\n<p>While this trial-and-error process ensues you begin to receive feedback, often surprising, which may cause your steps to travel different hypotheses. Or it may require a pause in the action when you cancel one idea and foreclose the set of possibilities; though bounded, you are not entirely helpless. You unlearn, go back, change course. The tango lasts.</p>\n<p>Also&hellip;</p>\n<p>It&rsquo;s impossible to throw out all we know at the beginning and re-interrogate every line of code.</p>\n<p>&gt; &hellip;you just have to pick one and start checking.</p>\n<p>Patience is what we need, as we methodically unpack our worldview from the inside out.</p>\n<hr>\n<p>This past week I spent a good part of two days wrestling with a broken acceptance test in a somewhat unfamiliar part of code. My initial assumptions misled me from the start.</p>\n<p>The test was written to observe a state change by simulating a click on the first menu item in a dropdown, which would flip the disabled state of a Purchase Button elsewhere in the container component. That assertion was no longer passing. Because my new code had changed the source of the the initial values for the dropdown, I had set my sights on determining if that source data in the test was wrong.</p>\n<p>Sigh, that was an incorrect assumption. I spent a bunch of time interrogating these source values in the test setup for the dropdown menu but in the end they were correct &ndash; my initial presumption and assumption (worldview) steering me into a void. Sucked.</p>\n<p>After repeatedly playing with the test instructions and comparing to the outcome in the browser, I discovered the click action was doing nothing because the initial state for the Purchase Button was already set through a test setup step which <em>equaled the first value of the dropdown menu</em>; so the click action didn&rsquo;t actually change the value in the test (I was finally able to repro this in the browser). There was no state change to observe. In fact, and this is the best part, the test wasn&rsquo;t needed at all. My code change inadvertently exposed a test that was applying false assumptions to the code.</p>\n<p>Lol, how much of our software is layer cakes of fallacious worldviews???</p>\n",
        "date_published": "2019-06-24T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/06/24/debugging-a-test-that-does.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/06/19/precrude-development.html",
        "title": "Pre-crude development",
        "content_html": "<p>I caught <a href=\"https://twitter.com/ruthmalan/status/1312819266757029888?s=20\">this tweet</a> by Ruth Malan yesterday. It&rsquo;s a wonderful reminder about the tension between continuous evolution and product instability in software development.</p>\n<p>&gt; But like putting &ldquo;product stability&rdquo; in tension with &ldquo;continuous evolution&rdquo; is a very (relevant) &ldquo;today&rdquo; recognition. For example, if we keep changing a complex dashboard UI, we frustrate users (perpetual learning curve/adaptation pushed onto them) and it may even be unsafe&hellip;</p>\n<p>Are you having a Val Garland DING DONG moment? It truly is a daily battle attempting to sit comfortably in this oversized chair, right? Like, certainly not a quotidian gracelessness I was prepared for at the start of my career. Back then I imagined long-lived codebases more manicured and predictable than the embryonic Rails app I would find myself working on in my first software job. Presently I&rsquo;m working in a legacy codebase (like 10+ years running, ancient in software years), and I’m not really sure if it’s much more stable than that 3 year-old startup experiment. Sure, there are ignorable fossilized bits in corner tar pits that have run largely unattended for years; and quite elegant code abounds; it&rsquo;s a mixed bag. Nonetheless, I often find myself in labored negotiation with the code in-between those ends, in that muddy mix; code that&rsquo;s branched and maundered, <em>complected</em> semi-recently, as well as pubescent new growth. We might call this code pre-crude pressurized compounds with some new raw material shoveled in &ndash; does code <em>storm, form, norm</em>?<sup>1</sup> These are tension points where I struggle the most. There are just enough layers of abstraction, code reuse, shared responsibility, etc… – tensile strength – that don’t make changing the code easy. Any change could destabilize things, like expose bugs, ie break existing functionality.</p>\n<p>The day-to-day discipline of working with legacy code is wiggling in tension, but also support all existing behavior. jessitron quotes in a <a href=\"https://jessitron.com/2019/06/17/feature-interaction/\">recent blog</a>:</p>\n<p>&gt; Every new feature comes with the invisible requirement: “and everything else still works.”</p>\n<p>This is a wild task in pre-crude places!</p>\n<p class=\"small\">[1]: en.wikipedia.org/wiki/Tuckman's_stages_of_group_development</p>\n",
        "date_published": "2019-06-19T00:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/06/19/precrude-development.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2019/05/11/too-many-imports-eyes-tired.html",
        "title": "Too many imports, eyes tired",
        "content_html": "<p>There are too many imports in this React component file. I’m staring down like 50 lines of imports. External libraries (React, Lodash, etc…), our own internal libraries, components files, helpers, constants. The last bothers me the most because they feel like implementation details I want hidden away in these other components or helpers. So I’m looking at this statement inside a <code>render()</code> block:</p>\n<pre class=\"language-javascript\">\n<code>const isSoldOut = this.props.statusType == SOLD_OUT;</code>\n</pre>\n<p>And suddenly I&rsquo;m reminded of what Kyle Simpson told me on twitter a couple weeks ago:</p>\n<p>&gt; “in &lsquo;functional programming,&rsquo; we love and embrace functions! functions everywhere!” – @getify</p>\n<p>That’s it, that’s my out. We can refactor the equality expression into a function that represents data:</p>\n<pre class=\"language-javascript\">\n<code>const isSoldOut = ({ status }) =&gt; status === SOLD_OUT;</code>\n</pre>\n<p>We might find our code getting repetitive for computing different statuses:</p>\n<pre class=\"language-javascript\">\n<code>const isSoldOut = ({ status }) =&gt; status === SOLD_OUT;\nconst isAvailable = ({ status }) =&gt; status !== UNAVAILABLE &amp;&amp; status !== SOLD_OUT; \nconst isUnavailable = ({ status }) =&gt; status !== UNAVAILABLE; \n// etc...</code>\n</pre>\n<p>In which case we might find an indirection at a higher level that hides the implementation details of our equality expressions:</p>\n<pre class=\"language-javascript\">\n<code>const getTicketStatusType = (ticketProps) =&gt; STATUS_TYPES_MAP[get(ticketProps, \"status\")];</code>\n</pre>\n<p><code>STATUS_TYPES_MAP</code> could implement an object hash where the equality expressions are values or our data functions.</p>\n<p>This post almost became about mitigating import noise. But exploratory development while waxing with words wandered a bit. This is my day writing code in a nutshell &ndash; felicitous detours. Refactoring constants used for direct comparison into a reusable module. At the least those status constants can live in this new module. Nevertheless, the abstraction work yields other interesting propositions:</p>\n<ul>\n<li>Creating a reusable abstraction – which I know can be leveraged elsewhere</li>\n<li>De-cluttering render() which makes integration tests simpler, possibly unnecessary for some cases since logic can be independently unit tested</li>\n</ul>\n<p>That last point is important. At least to me. Untidy <code>render()</code> blocks are hard to scan, debug, and test. The machinations for constructing and composing the things to render can happen in other places: above the component class definition, in class methods, or in a separate file. The first options is one I quite like because abstractions don’t have to be all that general. It’s great if they are localized to the component at hand.</p>\n",
        "date_published": "2019-05-11T00:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2019/05/11/too-many-imports-eyes-tired.html",
        "tags": ["speculative nonfiction"]
      },
      {
        "id": "http://softlydeveloping.micro.blog/2015/09/19/whats-in-aname.html",
        "title": "What's in a name?",
        "content_html": "<p>There&rsquo;s always heated babbling (err…babeling) on the cyberspace to assign metaphor to our embryonic field of building digital things: writing or engineering or accretion. One thing for sure, humans have a religious proclivity to conquistador in the bikeshed when faced with terra incognita. Perhaps, ironically, because it&rsquo;s something of a science and therefore seems to ask for a pinning down. But these guys, some of us, just seem unable to leave it alone to variance; to let it lie under a broad, mercurial atmospheric plane of something like creating.</p>\n<p>I remember when I attended my first Railsconf in 2014. In the opening keynote DHH made a todo about software writing (and more famously that TDD was dead).</p>\n<p>Hello, World!</p>\n<p>Fucking comma in there. You have an author-face.</p>\n<p>At that time, 2014 in Chi-city (my place of birth), I was too green building product to really care what you called what I was doing. (Maybe I&rsquo;ll never actually care that much.) It wouldn&rsquo;t have helped me get a quicker handle on the revealing module pattern.</p>\n<p>And then, a couple days later in the closing keynote, Aaron Patterson rebukes the writing metaphor and talks about the advanced engineering of improving Rails 4 query performance. Did they do that on purpose?</p>\n<p>What&rsquo;s in a name? Sigh, we don&rsquo;t have the luxury of poetic soliloquy when getting business done and keeping this company afloat. Shitty code smells like shit no matter what you call it. I&rsquo;m not gonna care too much for now what the pontificators put on the LHS.</p>\n<p><code>- &amp;lt;-{@</code></p>\n",
        "date_published": "2015-09-19T01:00:00-07:00",
        "url": "https://softlydeveloping.micro.blog/2015/09/19/whats-in-aname.html",
        "tags": ["speculative nonfiction"]
      }
  ]
}
