Weekly log

Highlights of what I'm working on. Updated weekly.

2021

Week 3

πŸ‘¨β€πŸ’Ό Work

  • Participated in our team's Q1 planning session and other lengthy meetings. O'boy how exhausted I now am.
  • Got assigned to Agile Master's role in our team. (Agile Master is like Scrum Master but cooler.) It happened so fast that I didn't have much time to think about it, but I actually look forward to it.

πŸ‘¨β€πŸš€ Personal projects and open source

  • Signed up for a free 30-day trial of Plausible Analytics and added it to my site.
    • Plausible is simple, which is nice because I wouldn't utilize complex metrics anyway.
    • Plausible is also lightweight (< 1 KB) and privacy-friendly. I really appreciate these qualities.
    • Now we'll just have to wait and see if I become too addicted to the metrics. (Haha, like anybody would accidentally find my site.)
  • Wrote 14 new answers on Stack Overflow. Someone please explain why I become addicted to Stack Overflow when I'm very tired. (14 answers per week is a lot for me. Last year I wrote a total of 15 answers.)

πŸ‘¨β€πŸŽ“ Learnings

  • "Illegal invocation" errors in JavaScript are thrown when the context of a function is lost, i.e. when the function's this keyword isn't referring to where it should.

    Some context (pun intended): I tried to destructure the abort method from an AbortController, but all I got was the error:

    const abortController = new AbortController()
    const { abort } = abortController

    // In another file:

    abort()
    //=> TypeError: Illegal invocation

    abort.apply(abortController)
    // Now `this` refers to `abortController` again,
    // so everything's ok

    This seems like a basic concept, but somehow the error message didn't ring any bells when I encountered it this week.

    Firefox seems to produce a much more descriptive error:

    TypeError: 'abort' called on an object that does not implement interface AbortController.

    So does iOS Safari:

    TypeError: Can only call AbortController.abort on instances of AbortController

  • The Date() constructor is poor at parsing date strings. From the linked page:

    Parsing of date strings with the Date constructor (and Date.parse(), which works the same way) is strongly discouraged due to browser differences and inconsistencies.

    I thought that one could be quite lax about what they provide for the Date() constructor, but that's not the case. When writing an answer to a date-related question on Stack Overflow, I noticed that the date string "2021-01-10 12:47:29 UTC" results in "Invalid Date" on Firefox and iOS Safari:

    new Date('2021-01-10 12:47:29 UTC')
    //=> Chrome: Sun Jan 10 2021 14:47:29 GMT+0200 (Eastern European Standard Time)
    // Firefox: Invalid Date
    // iOS Safari: Invalid Date

    Compare with the standard string representation of a date time string:

    new Date('2021-01-10T12:47:29.000Z') // Z = UTC
    //=> Chrome: Sun Jan 10 2021 14:47:29 GMT+0200 (Eastern European Standard Time)
    // Firefox: Sun Jan 10 2021 14:47:29 GMT+0200 (Eastern European Standard Time)
    // iOS Safari: Sun Jan 10 2021 14:47:29 GMT+0200 (EET)
  • Pug supports dynamic tag names:

    - const tag = 'article'

    #{tag}
    #{tag}.foo
    #{tag}.foo(class="bar")
    #{tag}(class="bar")

    // Output:
    <article></article>
    <article class="foo"></article>
    <article class="foo bar"></article>
    <article class="bar"></article>

πŸ•΅οΈβ€β™‚οΈ Cool stuff

  • Mike Crittenden has written about two types of skills and two types of learning in his blog post Learning a technology you don't need right now is a waste of time. TL;DR:

    • Two types of skills:
      • Expiring skills: hard skills, e.g. TypeScript, React, Kubernetes
      • Permanent skills: soft skills, e.g. attitude, discipline, charisma
    • Two types of learning:
      • Just-in-time: learn when you need the skill/knowledge
      • Just-in-case: learn in case you need the skill/knowledge in the future
    • Hard skills expire, so learning them just-in-case is a waste of time
    • Soft skills are permanent and compound over time, so learning them just-in-case is wise
  • Riot.js looks like a nice alternative to Vue. I like that it's more minimal, more vanilla and more lightweight than Vue. For a quick comparison of the two, I can recommend the article Vue vs. Riot: Both are Winners! by Jordan Brennan.

  • Speaking of Jordan Brennan, he's the author of my all-time favorite React-related quote:

    React's ecosystem is not a benefit. It's a dumb necessity grown from the need to create more stuff, much of it being React-only versions of existing stuff, because React is so incompatible and fussy.

    (Yes, I'm tired. But I also agree!)

Week 2

πŸ‘¨β€πŸ’Ό Work

  • Bought a new microphone: RØDE Procaster + a bunch of accessories.

    • I have previously used Jabra Evolve 65 headset. I always thought it has quite good audio quality – and it kind of has; everything is relative.

      But then I compared my voice recorded with the Jabra to my brother's voice recorded with a decent condenser microphone. The difference in audio quality was immense. No way I'm going back to the Jabra (unless I need portability).

      I have worked mostly remotely for the past few years and plan to continue working remotely, so having high quality audio equipment benefits my colleagues as well.

  • Had fun refactoring a React component to use useReducer() instead of multiple useState()s, and then refactoring it back to use multiple useState()s. Sometimes it takes a few iterations until a good solution is found, right?

πŸ‘¨β€πŸš€ Personal projects and open source

  • Published a couple of solutions to Advent of Code 2015 puzzles that I had done in December but hadn't published yet. More to come next week.
  • Created a quick and dirty content calendar for myself to better keep track of my scheduled blog posts and cookbook recipes. I'll see how this works out and will probably write a blog post about this some day.

πŸ‘¨β€πŸŽ“ Learnings

  • When deciding what microphone to buy, I watched some videos.

    • From Podcastage's video XLR vs USB Microphones, Which Should You Buy?, I learned that

      • USB microphones are easy to use
      • XLR microphones offer better audio quality and more choices.

      Thus, I opted for an XLR microphone. There's no such thing as overkill when it comes to audio stuff, right?

    • From Podcastage's video Dynamic vs Condenser Microphones, What's the Difference?, I learned that

      • condenser microphones are more sensitive so they pick up more background noises, like the sound of the keyboard, air conditioner etc.
      • dynamic microphones are better at suppressing background noises at the cost of reduced audio quality.

      In my case, I'm sure no one (including me) would notice the difference in audio quality between a dynamic and a condenser microphone. But background noises are always annoying, so I opted for a dynamic microphone.

  • Calculating the week number of a date in JavaScript is surprisingly complex. Though that might be because week numbering itself seems complicated, and JavaScript doesn't provide a native way to get the week number of a date.

    In the end, I ended up using the getWeek() function from date-fns. This piece from its implementation on GitHub is amusing:

    // Round the number of days to the nearest integer
    // because the number of milliseconds in a week is not constant
    // (e.g. it's different in the week of the daylight saving time clock shift)
    return Math.round(diff / MILLISECONDS_IN_WEEK) + 1

    I'm glad I haven't had to deal with date stuff much in the past.

πŸ•΅οΈβ€β™‚οΈ Cool stuff

  • Lefthook seems like a better alternative to Husky or Husky + lint-staged. I found this via Stefan Judis's web dev newsletter.

  • Locality of Behavior (LoB) is a nice name for a nice principle. It states that the behavior of code should be obvious on inspection. Check the linked article for a good example – it's a great article.

    I think that the LoB principle explains, at least partly, why I feel productive and happy when using Tailwind. For example, when using it with React, a single component file can contain everything relevant about the component: the HTML structure (JSX), logic (hooks etc.) and stylings (Tailwind classes among the JSX). There's no need to jump between HTML, JS and CSS files. I have heard that e.g. Vue provides a similarly pleasant experience.

Week 1

πŸ‘¨β€πŸ’Ό Work

  • Returned from a 2-week Christmas vacation on Thursday.
    • Protip: try to schedule your vacations so that you return in the middle of the week. This way the first work week will be more pleasant as it will be a short one. I learned this some years ago from my colleague (thanks, Joonas!).
  • Catched up on emails and investigated poorly performing database queries.

πŸ‘¨β€πŸš€ Personal projects and open source

  • Tweaked my website (changelog).
  • Started this weekly log!

πŸ‘¨β€πŸŽ“ Learnings

  • I'm writing a blog post about how to convert an URL path into "cumulative segments" in JavaScript; e.g. '/foo/bar/baz/' into ['/', '/foo/', '/foo/bar/', '/foo/bar/baz']. (I'll publish the post later, when it's ready.) While writing it, I learned that:

    • When a regular expression matches a part of a string, it consumes those characters. This prevents doing overlapping matches, but this can be circumvented by using lookbehinds or lookaheads.

    • String.prototype.match() ignores capturing groups when using the global flag (g), but String.prototype.matchAll() does not.

    • Assignment operators have return values. For example, these two functions are effectively the same:

      () => {
      return (foo += 10)
      }

      () => {
      foo += 10
      return foo
      }
  • My colleague gave a 10-minute introduction to Chrome DevTools' Performance tab. I admittedly haven't used it much, but now I know a couple of things to look for there (thanks, Jukka!).

  • Learned about tail call optimization (TCO) by watching Tail Call Optimization: The Musical!! (found it via a comment on Hacker News). It was funny but informative! My quick notes:

    • Tail call = a function call at the very end of a function, i.e. the function call has to be the very last thing that the function does.
    • Tail call optimization (TCO) = if the language (and engine) supports TCO, tail calls are removed from the call stack because they are kind of unnecessarily there (because of the tail position).
      • Pro: You don't get errors saying "Maximum call stack size exceeded" (Chrome) or "Too much recursion" (Firefox).
      • Con: Stack traces have less information (because tail calls have been removed from the call stack), making debugging errors potentially more difficult.
    • Not in the video but relevant: ECMAScript 6 offers TCO, but TCO "isn't supported by many [JavaScript] engines and that may never change." Source: Tail call optimization in ECMAScript 6 by Dr. Axel Rauschmayer

πŸ•΅οΈβ€β™‚οΈ Cool stuff