29 Sep 2019, 21:28

Thinking Critically About Code Quality

I have been thinking recently about an aspect of software development which I feel can often be overlooked. The catalyst that triggered the thoughts in question was a post to Erlang mailing list from Joe Armstrong (the author of the Elang programming language). The email is titled with the subject ‘Why do we need modules at all?’. Joe’s post starts with a bold opening statement:

I’m proposing a slightly different way of programming here The basic idea is

  • do away with modules
  • all functions have unique distinct names
  • all functions have (lots of) meta data
  • all functions go into a global (searchable) Key-value database …

On it’s surface this completely flys in the face of an idea that as developers we get told is this axiomatic truth; global variables are bad. Although Joe’s post wasn’t really about code quality, it did get me thinking about it. We often have these ideals that we hold dear and hold others too in social rituals such as code reviews and meetup talks.

Yet for a profession that is steeped in correctness, exactitudes and objectivity, there are many elements of software development that are an aesthetic or cognitive preference. The classic case of this being tabs vs spaces. Indeed, it feels the growth and adoption of linters/formatters across languages and projects is not so much a pursuit to make a codebase more ‘correct’ but to sideline aesthetic and preferential ideals.

The longer I write code it seems to be more apparent that writing code is a near endless series of trade offs. The binary of ‘good’ and ‘bad’ code seems to break down when taking into account the writers constraints and the near limitless characteristics you could optimize for. To pick a few common ideals:

  • Correctness
  • Readability
  • Conciseness
  • Constency
  • Maintainability
  • Simplicity
  • Testability
  • Portability
  • Defensiveness
  • Performance
  • Security
  • Extensibility
  • DRYness
  • Modularity
  • Idiomatic

Not to mention that the meaning of these words is somewhat subjective, differ from (programming) language to language and are also transient. Is it possible to have code that is uniformly agreed to be ‘testable’ for example? Of course some of these characteristics are arguably more quantifiable or objective than others (e.g. performance), but even for these there will always be questions of which metrics and which results are acceptable.

So what does that mean in practice? I think it means accepting that no code will ever be ‘perfect’, that coding is a series of trade-offs, and that we need to decide what qualities we want to optimize for. If you’re writing a quick script at the weekend to rename some files, would you optimize for modularity and testability? Perhaps not. However, if you were writing production code in a team, the answer might be a little different. Maybe, as Joe did, sometimes it’s healthy to question beliefs that we hold strongly and ask if they always hold true (or if they are true at all). For example, is it always necessary to be DRY? Are their times it’s okay for things to be tightly coupled? What if we didn’t have 100% test coverage?

Do I think that the strive for code quality is redundant? Absolutely not. However, as I have grown as a developer it feels a fair portion of the things I was taught as universal truths about ‘good’ and ‘bad’ code seem to actually be socially reinforced norms. From a personal standpoint, I think it’s important to strive towards having a team outlook and agreement on what the meaning of ‘good’ code is. Taking this a step further maybe this means having it written down in a guide or even codified in linters/tool configs where possible. Here it feels that being empathetic and open-minded to others input are key to being successful in software, as the understandings of what constitutes good code differ from person to person. Perhaps the goal is treating coding collaboratively as an opportunity to learn from others and teach them, and less as an opportunity to assert an ideal of perfect code.

30 Jul 2019, 20:37

External Blog Post Roundup

You may notice that I have not blogged in a while, at least not on this site. Recently I have been blogging on my current employers (SitePen) blog on a whole host of different topics. I thought it may be useful to round these up and link to them here for reference. This is the list:

I will aim to keep this list updated with any additional posts in the future. Let me know if there’s anything specific you’d like to hear about!

01 Oct 2018, 20:37

A Quick Look at WorkerDOM

In the browser, many operations occur on a single main thread. Due to the number of things we need to handle as web developers such as styling, DOM updates, fetches, data transforms, timers and so forth we can end up with a lot going on that thread. Unfortunately, this thread is also responsible for handling user inputs and rendering to the screen, which are user critical requirements and have large impacts on their experience. Here if we have tasks that run for long periods this can block responding to user input and rendering new frames.

In the browser we have access to threading via Web Workers. Web Workers allow us to run JavaScript in a separate thread whilst also being able to message back to the main thread. The limitations of Web Workers are that they have transfer times for data between the main and worker thread, limited transfer types (i.e. Functions and Errors aren’t allowed) and also perhaps most importantly no DOM access (i.e. document.getElementByID for example). I have experimented and written about transfer times for workers, showing that for small loads the fear is probably over played. However a core aspect of frontend development is, maybe somewhat obviously, trying to update what is happening on the screen (render new content). This makes the DOM limitation pretty painful for those using Web Workers, as it mostly limits it to computational logic which we then proxy back to the main thread.

On mobile devices, where performance perhaps matters the most, we’re now seeing low-end devices with multiple cores (for example a Nokia 1 and the Micromax Bharat Go both have quadcore processors). Arguably this is where multiple threaded code would probably have the largest benefit. However, we still have a particularly single-threaded approach to writing browser code. This is why it’s interesting to see the emergence of the recently announced WorkerDOM library from the AMP team, which aims to let developers leverage workers more easily, by removing the aforementioned limitation of lack of DOM access (or at least perceived lack of DOM access).

What is WorkerDOM?

WorkerDOM is a library which you can include in your applications and pages. It provides much of the regular DOM API and in turn proxied access to the real DOM on the main thread, passing mutations to the DOM over to the main-thread to be handled. This encourages a lot of logic that was previously happening on the main thread to be handled by the Web Worker, leaving the main thread to handle user input and DOM changes. The library itself is written in TypeScript and is compiled down to both global variable and module formats.

Setting up WorkerDOM

You can include WorkerDOM by installing it via NPM like so:

npm install @ampproject/worker-dom

or if you use Yarn then:

yarn add @ampproject/worker-dom

Alternatively you could use a script tag directly, using a CDN, in the following fashion:

<script src="https://unpkg.com/@ampproject/worker-dom@0.1.2/dist/index.js"></script>

We can actually take this a step further as WorkerDOM is distributed as both a global (aliased as MainThread) and an ES Module, allowing for the import syntax. This means you can do the following;

<script src="https://unpkg.com/@ampproject/worker-dom@0.1.2/dist/index.mjs" type="module"></script>
<script src="https://unpkg.com/@ampproject/worker-dom@0.1.2/dist/index.js" nomodule defer></script>

Here only browsers that understand modules (all modern browsers, except Samsung Internet now support modules) will receive the module script.

First Steps

WorkerDOM allows us to expose a specific part of the DOM to be upgraded, we can do this by doing something we would probably not normally do; we set the src attribute on the containing element we want to upgraded to work with WorkerDOM. The src attribute is updated to be the name of the script we’re interested in running as our worker script. For the purposes of this blog, we are going to generate some prime numbers and render them into the DOM. For our index.html file, we might start with something like this in our case:

<body>
    <div src="primes.js" id="primes">
    </div>
</body>

So now we have an element that we can upgrade in our body. We need to declare explicitly that we want to upgrade the element using the upgradeElement method. We can do that like so:


<script type="module">
    import {upgradeElement} from '/dist/index.mjs';
    upgradeElement(document.getElementById('primes'), '/dist/primes.mjs');
</script>

<script nomodule async=false defer>
    document.addEventListener('DOMContentLoaded', function() {
        MainThread.upgradeElement(document.getElementById('primes'), '/dist/primes.js');
    }, false);
</script>

You can see we take both the module and none module code paths allowing us to handle both scenarios. This means we can now begin looking at our actual worker logic!

The Worker File

The coolest part about WorkerDOM is that it allows us to behave as if we have DOM access in the worker thread. That means we have access to properties like document.createElement for example. Continuing on with the concept that we want to generate primes and add them to the DOM, we could do something like this:


const startNumber = 1;

function generatePrimes() {

    while (document.body.firstChild) {
        document.body.removeChild(document.body.firstChild);
    }

    const numDivs = 1000;
    const limit = startNumber + numDivs;
    const primes = sieveOfEratosthenes(limit); // An algorithm for generating primes up to 'limit'

    const div = document.createElement('div');
    div.className = 'parent';

    for (let i = startNumber; i < limit; i++) {
        const numberDiv = document.createElement('div');
        numberDiv.className = "number";
        const numberText = document.createTextNode(i);
        if (primes.has(i)) {
        numberDiv.style.fontWeight = 'bold';
        numberDiv.style.color = '#240098';
        }
        numberDiv.appendChild(numberText);
        div.appendChild(numberDiv);
    }

    document.body.appendChild(div);
    startNumber += numDivs;

}

setTimeout(generatePrimes, 0); // Not sure why we need this in a timeout?
document.body.addEventListener('click', generatePrimes);

This code will create divs with numbers in them, with prime numbers being highlighted and put in bold. The numbers will update on click on the document. Notice how we can behave as if this worker code is on the main thread, with access to DOM APIs. It’s worth pointing out the main difference here is that the "primes" div from the index.html is considered our document.body here.

As it stands, WorkerDOM is currently in alpha, and as such is still being worked on. Hopefully, this post has given you a reasonable overview of the library, and if you are interested in learning more about WorkerDOM I would recommend these resources: