# Results

# Participation

In total, 545 participants took part in the experiment. On average, each participant completed 13 exercises, leading to around 250 data points for each snippet.

Just under half of the participants said they had been coding for over 10 years, and around a third had been coding for less than 5 years.

In terms of main programming language, over half the participants said that their main programming language was JavaScript, with the rest spread around a variety of other languages.

Charts for years programmming and main language

# Results by construct

# Boolean Algebra

This experiment was based on the principle that the following expressions are identical.

!a && !b /* expanded */ === !(a || b) /* simplified */

The expanded version on the left (with two separate negations) is exactly equivalent to the simplified version on the right (with a single negation applied to the expression in parenthesis). We wanted to see whether there was any difference in readability between these two ways of expressing combined booleans.

We wrote six exercises with pairs of snippets like the following:

# Expanded

function canDrink(drinkerAge, drinkIsAlcoholic) {
  var underAge = drinkerAge < 18;
  return !underAge || !drinkIsAlcoholic;
}

var result = canDrink(21, true);

# Simplified

function canDrink(drinkerAge, drinkIsAlcoholic) {
  var underAge = drinkerAge < 18;
  return !(underAge && drinkIsAlcoholic);
}

var result = canDrink(21, true);

See all snippets

We found a statistically significant difference in the time taken to read the snippets as follows:

Metric Expanded Simplified P value
Time taken 28.0 30.6 0.045

It seems that in our tests, the expanded versions of boolean expressions are faster to parse than the equivalent simplified expressions.

# Chaining Methods

This experiment compared the chaining of consecutive methods, with the introduction of meaningful intermediate variables. For example:

# Chaining methods

function sort(input) {
  return input
    .toLowerCase()
    .split('')
    .sort()
    .join('');
}

var result = sort('bag');

# Intermediate variables

function sort(input) {
  var lowerCase = input.toLowerCase();
  var lettersArray = lowerCase.split('');
  var sorted = lettersArray.sort();
  return sorted.join('');
}

var result = sort('bag');

See all snippets

We found a statistically significant difference in both the accuracy and the time taken, but in different directions:

Metric Chained methods Intermediate variables P value
Accuracy (%) 89.2 93.8 0.044
Time Taken (s) 30.5 39.3 0.001

We found that more people were able to accurately predict the outcome of the snippets with intermediate variables. However, the snippets were faster to read with chained methods.

It seems that there is a readability trade-off between the speed of parsing chained methods and the increased context given by the meaningful intermediate variables.

# Extracting Functions

This experiment tested the effect on readability of extracting a series of operations into a named function, as opposed to performing the operations inline. For example:

# Extracted function

function getSum(values) {
  var sum = 0;
  for (var i = 0; i < values.length; i++) {
    sum += values[i];
  }
  return sum;
}

function getAverage(values) {
  return getSum(values) / values.length;
}

result = getAverage([1, 2, 3]);

# Inline operations

function getAverage(values) {
  var sum = 0;
  for (var i = 0; i < values.length; i++) {
    sum += values[i];
  }
  return sum / values.length;
}

result = getAverage([1, 2, 3]);

See all snippets

We found a statistically significant difference in the time taken to read the code snippets, as follows:

Metric Function Inline P value
Time taken (s) 43.0 38.4 0.048

It seems that in our experiment, extracting a named function adds an overhead in the time taken to read the code.

# Order of If Statements

This experiment tested whether there is any effect on the readability of a conditional statement with two branches, in dealing with the branch case first. For example:

# Positive first

function getSalutation(title, firstName, lastName) {
  var salutation;
  if (title) {
    salutation = title + ' ' + lastName;
  } else {
    salutation = firstName + ' ' + lastName;
  }
  return salutation;
}

var result = getSalutation('Miss', 'Jane', 'Marple');

# Negative first

function getSalutation(title, firstName, lastName) {
  var salutation;
  if (!title) {
    salutation = firstName + ' ' + lastName;
  } else {
    salutation = title + ' ' + lastName;
  }
  return salutation;
}

var result = getSalutation('Miss', 'Jane', 'Marple');

See all snippets

We found a statistically significant difference in the time taken to read the code snippets, as follows:

Metric Positive first Negative first P value
Time taken (s) 17.3 19.3 0.042

It seems that in our experiment, conditional statements where the positive condition appears first are faster to read.

# Operator Precedence

This experiment tested whether expressions that are dependent on operator precedence are made more readable by adding parentheses to remove the ambiguity. It should be noted that some code linters, such as prettier, will remove parentheses that are considered unnecessary by default.

For example:

# Parentheses

var fixedCost = 200;
var monthlyCost = 20;

var result = fixedCost + (monthlyCost * 12);

# No parentheses

var fixedCost = 200;
var monthlyCost = 20;

var result = fixedCost + monthlyCost * 12;

See all snippets

We found a statistically significant difference in both the accuracy and the time taken, as follows:

Metric Parentheses No Parantheses P value
Accuracy (%) 97.2 91.7 0.042
Time Taken (s) 17.0 19.1 0.013

It seems clear that readability is improved by adding explicit brackets, rather than relying on the developers' knowledge of operator precedence.

# Pure Functions

This experiment tested whether there was an inherent difference in readability between pure and impure functions. A pure function has no external dependencies or side effects, and always returns the same output for the same input parameters values.

For example, the following snippets have functions expressed in both impure and pure forms.

# Pure

var score = 10;

function doubleScore(initialScore) {
  return initialScore * 2;
}

var result = doubleScore(score);

# Impure

var score = 10;

function doubleScore() {
  score = score * 2;
}

doubleScore();

var result = score;

See all snippets

We found a statistically significant difference in the time taken to read the code snippets, as follows:

Metric Pure Impure P value
Time taken (s) 26.7 24.6 0.025

It seems that in our experiment, writing a pure function adds an overhead in the time taken to read the code.