Make Your Commit Messages Inversely Proportional To Diff Length

You’d think based on the title that this post is about commit messages. It’s not. At least, not really.

What I want to reflect on is how we go about grouping changes into a commit history. It is my opinion that some styles are better than others. And if you agree with my style, you too might find that your commit messages are inversely proportional to the length of the commit diff.

Continue Reading

Unit Testing: A Black Box?

The beauty of declarative programming—regexs, SQL, CSS selectors—is that you don’t have to think about the execution model, at least not most of the time. Yet… somewhere along the journey to mastery you will be forced to understand the execution model if you want to progress.

If you’ll allow the analogy, I think the same pattern occurs with unit testing. When you start, it’s a thing of beauty that you can treat the code under test as a black box. But as you progress, well…

Continue Reading

Install LineageOS On OnePlus 6

This guide will walk you through installing LineageOS 16 on the OnePlus 6 phone. There are official installation instructions, but they don’t explain the nuances of working with an A/B phone like ours. Let me help you avoid hard bricking your phone like I did. And if it happens anyway, don’t worry—I can show you how to fix that too.

No previous Android experience is necessary. Everything you need to know will be explained here, or covered by a link to the relevant page elsewhere. Having command line experience will be helpful. However, if you don’t know it, you can probably figure it out.

You will need a computer to be able to complete all the steps. With one exception, everything in this guide should work regardless of whether you are on Linux, OS X, or Windows.

Update 2019/11/5: it has come to my attention that there is an issue with this guide. It works great for installing LineageOS on your phone. However, if you follow the exact steps outlined here you may run into issues when updating LineageOS to a newer version. I believe the issue occurs if you don’t have the latest stock ROM flashed to both slots. When I have more time I would like to update the steps in this guide to ensure that updates will work. In the meanwhile, you have been warned.


  1. Update Your Phone To The Latest Version (Optional)
  2. Unlock the bootloader
  3. Transfer ROM files to the phone
  4. Boot TWRP with FastBoot
  5. Flash the latest, stock OxygenOS ROM
  6. Swap slots
  7. Wipe the system partition
  8. Perform a factory reset
  9. Swap slots
  10. Flash the LineageOS zip file
  11. Flash TWRP
  12. Reboot into Recovery
  13. Install GApps (Optional)
  14. Install Root (Optional)
  15. Reboot into the system

Yes, that is an intimidating list. But the list is actually complete. And many of the steps are repeats, so once you get the hang of it the process will go quickly.

Continue Reading

A Pattern For Cancelling Fetch API Requests

There is a fairly reproducible bug in that occurs when you quickly switch back and forth between Calendar and Mail while everything is still loading in:

async bug in outlook

Outlook thinks you are in the Calendar when actually it is the Mail section that loaded in last. The navigation basically stops working at that point.

I’m picking on Outlook because it is a major web application that presumably has a large quality assurance team behind it. But once you start to look for these out-of-order execution bugs, you can see them pop up in just about every JavaScript application.

Continue Reading

Using The Null Object Pattern With 3rd Party Types

Feel free to skip ahead if you are already familiar with the Null Object Pattern. What follows is a quick introduction to the pattern.

Imagine you want to format a money object before displaying it to the user, but the problem is that the object might be null. Any coder knows how to handle that:

const formatMoney = (money) => {
  if (money === null) {
    return '[price unavailable]';
  return money.format();

console.log('it costs ' + formatMoney(getPrice()));

Nothing wrong with that code, right?

But what if I told you we could simplify the same code to this:

console.log('it costs ' + getPrice().format());

How would that even work?? How does .format() not throw TypeError: Cannot read property 'format' of null when getPrice() returns null?

In one sense it is impossible to avoid throwing an error. However, the funny thing about impossible challenges is how often they become possible after examining one’s assumptions.

Continue Reading