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.

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 – that is, an amount of time that wouldn’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.

  1. Add a task to run the compiler in watch mode (this is totally boilerplate):
{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "typescript",
      "tsconfig": "tsconfig.json",
      "option": "watch",
      "problemMatcher": ["$tsc-watch"],
      "group": "build",
      "label": "tsc: watch - tsconfig.json"
    }
  ]
}
  1. Add your outfiles (dist) target glob to your launch.json file:
{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch server.js via nodemon",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "nodemon",
      "program": "${file}",
      "restart": true,
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "runtimeArgs": ["--experimental-modules"],
      "outFiles": ["${workspaceFolder}/out/**/*.js"] // <-- ADD YOUR OUTFILES GLOB HERE
    }
  ]
}

And voila, here I am pausing on a breakpoint:

Ok new topic…

During episode 138 of the > Code podcast 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 “percolating” (Jamey) or in a “mental marinade” (Vaidehi). Jacob Stoebel chimes in describing another common mental turnabout we programmers do: when we catch ourselves down a rabbit hole trying to solve (big “S”) 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 “Problem Treatments,” which includes the concept of “dissolution” that applies to Jacob’s case.

To list and paraphrase them:

  1. Absolution - Ignore the problem and hope it goes away

    It’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’t great enough.

  2. Resolution - Doing something something “good enough”

    This feels like a pretty standard principle for building products considering some of these typical aspects of commercial software development:
    a) Your team will never have a complete understanding of how your software will express itself once “running” or “used” by customers. Therefore perfection, completeness, wholeness are not desirable or ever, actually, achievable.

    b) Deadlines and other external stakeholder pressures will force you to sacrifice however your team defines “great” or “better” software

  3. Solution - Finding an optimal solution with experimentation or research

    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.

  4. Dissolution - Redesigning the system so that the problem no longer exists

    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.

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…) in favor of a simple switch statement.