# Code snippets
For reference, the following code snippets were used in the experiments that resulted in statistically significant metrics. For each exercise, the participant saw one of the two code snippets at random.
# Boolean Algebra
Each exercise contains a boolean expression. In one snippet it is in expanded form, and the other it is in a simplified form using brackets.
# Excercise 1
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);
# Excercise 2
Expanded
function withinRange(value, start, end) {
var beforeStart = value < start;
var afterEnd = value > end;
return !beforeStart && !afterEnd;
}
var result = withinRange(10, 4, 20);
Simplified
function withinRange(value, start, end) {
var beforeStart = value < start;
var afterEnd = value > end;
return !(beforeStart || afterEnd);
}
var result = withinRange(10, 4, 20);
# Excercise 3
Expanded
function isNotADuck(quacksLikeADuck, walksLikeADuck) {
return !quacksLikeADuck || !walksLikeADuck;
}
var result = isNotADuck(true, false);
Simplified
function isNotADuck(quacksLikeADuck, walksLikeADuck) {
return !(quacksLikeADuck && walksLikeADuck);
}
var result = isNotADuck(true, false);
# Excercise 4
Expanded
function differentNamesAndValues(input1, input2) {
return input1.name !== input2.name && input1.value !== input2.value;
}
var object1 = { name: 'bob', value: 3 };
var object2 = { name: 'bob', value: 4 };
var result = differentNamesAndValues(object1, object2);
Simplified
function differentNamesAndValues(input1, input2) {
return !(input1.name === input2.name || input1.value === input2.value);
}
var object1 = { name: 'bob', value: 3 };
var object2 = { name: 'bob', value: 4 };
var result = differentNamesAndValues(object1, object2);
# Excercise 5
Expanded
function isValidPassword(input) {
var containsLetter = /[a-z]/.test(input);
var containsNumber = /[0-9]/.test(input);
var isLongEnough = input.length >= 8;
if (!containsLetter || !containsNumber || !isLongEnough) {
return false;
}
return true;
}
var result = isValidPassword('pass9');
Simplified
function isValidPassword(input) {
var containsLetter = /[a-z]/.test(input);
var containsNumber = /[0-9]/.test(input);
var isLongEnough = input.length >= 8;
if (!(containsLetter && containsNumber && isLongEnough)) {
return false;
}
return true;
}
var result = isValidPassword('pass9');
# Excercise 6
Expanded
var you = {
happy: true,
knowsIt: false
};
function shouldClapHands(person) {
if (!person.happy || !person.knowsIt) {
return false;
}
return true;
}
var result = shouldClapHands(you);
Simplified
var you = {
happy: true,
knowsIt: false
};
function shouldClapHands(person) {
if (!(person.happy && person.knowsIt)) {
return false;
}
return true;
}
var result = shouldClapHands(you);
# Chaining Methods
Each exercise contains a sequence of consecutive methods operating on a single variable. In one version the functions are chained together. In the second version intermediate variables with meaningful names are introduced.
# Exercise 1
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');
# Exercise 2
Chaining methods
function sentenceCase(input) {
return input.charAt(0).toUpperCase() + input.slice(1, input.length);
}
var result = sentenceCase('the right answer');
Intermediate variables
function sentenceCase(input) {
var firstCharacter = input.charAt(0);
var capitalizedFirstCharacter = firstCharacter.toUpperCase();
var restOfInput = input.slice(1, input.length);
return capitalizedFirstCharacter + restOfInput;
}
var result = sentenceCase('the right answer');
# Exercise 3
Chaining methods
var list = ['a', 'b', 'b', 'c', 'a'];
function keepDuplicates(value, index) {
return index !== list.indexOf(value) || index !== list.lastIndexOf(value);
}
function capitalize(item) {
return item.toUpperCase();
}
var result = list.filter(keepDuplicates).map(capitalize)[1];
Intermediate variables
var list = ['a', 'b', 'b', 'c', 'a'];
function keepDuplicates(value, index) {
return index !== list.indexOf(value) || index !== list.lastIndexOf(value);
}
function capitalize(item) {
return item.toUpperCase();
}
var duplicates = list.filter(keepDuplicates);
var capitalizedDuplicates = duplicates.map(capitalize);
var result = capitalizedDuplicates[1];
# Exercise 4
Chaining methods
function reverse(sentence) {
return sentence
.split(' ')
.reverse()
.join(' ');
}
var sentence = 'Hello world!';
var result = reverse(sentence);
Intermediate variables
function reverse(sentence) {
var words = sentence.split(' ');
var reversedWords = words.reverse();
var reversedSentence = reversedWords.join(' ');
return reversedSentence;
}
var sentence = 'Hello world!';
var result = reverse(sentence);
# Exercise 5
Chaining methods
function getMultiples(str) {
return str
.split('')
.map(function(num) {
return num / 3;
})
.filter(function(num) {
return num.toString().indexOf('.') === -1;
})
.map(function(num) {
return num * 3;
});
}
var result = getMultiples('0123456789')[2];
Intermediate variables
function getMultiples(str) {
var digits = str.split('');
var digitsDiv3 = digits.map(function(number) {
return number / 3;
});
var wholeNumbers = digitsDiv3.filter(function(number) {
return number.toString().indexOf('.') === -1;
});
var multiplesOf3 = wholeNumbers.map(function(number) {
return number * 3;
});
return multiplesOf3;
}
var result = getMultiples('0123456789')[2];
# Exercise 6
Chaining methods
function getLetterCounts(stringInput) {
return stringInput.split('').reduce(function(counts, letter) {
if (counts[letter]) {
counts[letter] += 1;
} else {
counts[letter] = 1;
}
return counts;
}, {});
}
var result = getLetterCounts('aaabbcccc').c;
Intermediate variables
function getLetterCounts(stringInput) {
var letters = stringInput.split('');
var counts = letters.reduce(function(counts, letter) {
if (counts[letter]) {
counts[letter] += 1;
} else {
counts[letter] = 1;
}
return counts;
}, {});
return counts;
}
var result = getLetterCounts('aaabbcccc').c;
# Extracting Functions:
In each of these snippets contains a series of operations that could be extracted into a function. In one version the function is extracted and given a meaningful name. In the other, the operations are left inline.
# Exercise 1
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]);
# Exercise 2
Extracted function
var nonNumericCards = {
1: 'Ace',
11: 'Jack',
12: 'Queen',
13: 'King'
};
var suits = ['Hearts', 'Clubs', 'Spades', 'Diamonds'];
var pack = [];
function addSuit(suit) {
for (var number = 1; number < 14; number++) {
var value = nonNumericCards[number] || number;
pack.push(value + ' of ' + suit);
}
}
for (var suitIndex = 0; suitIndex < suits.length; suitIndex++) {
var suit = suits[suitIndex];
addSuit(suit);
}
var result = pack[0];
Inline operations
var nonNumericCards = {
1: 'Ace',
11: 'Jack',
12: 'Queen',
13: 'King'
};
var suits = ['Hearts', 'Clubs', 'Spades', 'Diamonds'];
var pack = [];
for (var suitIndex = 0; suitIndex < suits.length; suitIndex++) {
var suit = suits[suitIndex];
for (var number = 1; number < 14; number++) {
var value = nonNumericCards[number] || number;
pack.push(value + ' of ' + suit);
}
}
var result = pack[0];
# Exercise 3
Extracted function
var person1 = {
name: 'Bob',
dateOfBirth: '1973-01-03'
};
var person2 = {
name: 'Bob',
dateOfBirth: '1982-01-03'
};
function sameDateAndMonth(date1, date2) {
var sameMonth = date1.getMonth() == date2.getMonth();
var sameDate = date1.getDate() == date2.getDate();
return sameMonth && sameDate;
}
function haveSameBirthday(person1, person2) {
var date1 = new Date(person1.dateOfBirth);
var date2 = new Date(person2.dateOfBirth);
return sameDateAndMonth(date1, date2);
}
var result = haveSameBirthday(person1, person2);
Inline operations
var person1 = {
name: 'Bob',
dateOfBirth: '1973-01-03'
};
var person2 = {
name: 'Bob',
dateOfBirth: '1982-01-03'
};
function haveSameBirthday(person1, person2) {
var date1 = new Date(person1.dateOfBirth);
var date2 = new Date(person2.dateOfBirth);
var sameMonth = date1.getMonth() == date2.getMonth();
var sameDate = date1.getDate() == date2.getDate();
return sameMonth && sameDate;
}
var result = haveSameBirthday(person1, person2);
# Exercise 4
Extracted function
function add12Hours(time) {
var hourMinute = time.split(':');
return 12 + parseFloat(hourMinute[0]) + ':' + hourMinute[1];
}
function to24HourTime(time) {
var parts = time.split(' ');
if (parts[1] === 'AM') {
return parts[0];
}
return add12Hours(parts[0]);
}
var result = to24HourTime('7:30 PM');
Inline operations
function to24HourTime(time) {
var parts = time.split(' ');
if (parts[1] === 'AM') {
return parts[0];
}
var hourMinute = parts[0].split(':');
return 12 + parseFloat(hourMinute[0]) + ':' + hourMinute[1];
}
var result = to24HourTime('7:30 PM');
# Exercise 5
Extracted function
function getMultiplesOf3(length) {
var array = new Array(length);
for (var i = 0; i < array.length; i++) {
array[i] = i * 3;
}
return array;
}
var numberArray = getMultiplesOf3(10);
var result = numberArray[8];
Inline operations
var numberArray = new Array(10);
for (var i = 0; i < numberArray.length; i++) {
numberArray[i] = i * 3;
}
var result = numberArray[8];
# Exercise 6
Extracted function
function repeatCharsTwice(inputString) {
var outputString = '';
for (var i = 0; i < string.length; i++) {
var char = string.charAt(i);
outputString += char + char;
}
return outputString;
}
var string = '0123456789';
var newString = repeatCharsTwice(string);
var result = newString.length;
Inline operations
var string = '0123456789';
var newString = '';
for (var i = 0; i < string.length; i++) {
var char = string.charAt(i);
newString += char + char;
}
var result = newString.length;
# Order of If Statements
Each of these snippets contains a conditional with two branches. In one snippet the positive case is processed first, and in the other, the negative case is first.
# Excercise 1
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');
# Excercise 2
Positive first
function getLogin(user) {
var login;
if (user.admin) {
login = user.username;
} else {
login = user.email;
}
return login;
}
var user = {
username: 'jane',
admin: true,
email: '[email protected]'
};
var result = getLogin(user);
Negative first
function getLogin(user) {
var login;
if (!user.admin) {
login = user.email;
} else {
login = user.username;
}
return login;
}
var user = {
username: 'jane',
admin: true,
email: '[email protected]'
};
var result = getLogin(user);
# Excercise 3
Positive first
function canLegallyDrink(age) {
var legal = age >= 18;
if (legal) {
return 'yes';
} else {
return 'no';
}
}
var result = canLegallyDrink(14);
Negative first
function canLegallyDrink(age) {
var legal = age >= 18;
if (!legal) {
return 'no';
} else {
return 'yes';
}
}
var result = canLegallyDrink(14);
# Excercise 4
Positive first
function containsCarbon(compound) {
if (compound.indexOf('C') === -1) {
return 'no';
} else {
return 'yes';
}
}
var result = containsCarbon('H2O');
Negative first
function containsCarbon(compound) {
if (compound.indexOf('C') !== -1) {
return 'yes';
} else {
return 'no';
}
}
var result = containsCarbon('H2O');
# Excercise 5
Positive first
var totalPokemon = 150;
function caughtThemAll(numPokemon) {
if (numPokemon === totalPokemon) {
return 'caught them all';
} else {
return 'gotta catch them all';
}
}
var result = caughtThemAll(102);
Negative first
var totalPokemon = 150;
function caughtThemAll(numPokemon) {
if (numPokemon !== totalPokemon) {
return 'gotta catch them all';
} else {
return 'caught them all';
}
}
var result = caughtThemAll(102);
# Excercise 6
Positive first
function isMeaningOfLife(num) {
if (num === 42) {
return 'yes';
} else {
return 'no';
}
}
var result = isMeaningOfLife(41);
Negative first
function isMeaningOfLife(num) {
if (num !== 42) {
return 'no';
} else {
return 'yes';
}
}
var result = isMeaningOfLife(41);
# Operator Precedence
Each of these snippets contains an expression where the result is dependent on operator precedence. One snippet contains the bare expression, while the other snippet adds parentheses for clarity.
# Excercise 1
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;
# Excercise 2
Parentheses
var result = (true && true) || (true && false);
No parentheses
var result = true && true || true && false;
# Excercise 3
Parentheses
function isTeenager(age) {
return (age < 20) && (age > 12);
}
var result = isTeenager(14);
No parentheses
function isTeenager(age) {
return age < 20 && age > 12;
}
var result = isTeenager(14);
# Excercise 4
Parentheses
var taxRate = 0.2;
var salary = 100;
var bonus = 10;
var result = salary - (salary * taxRate) + bonus;
No parentheses
var taxRate = 0.2;
var salary = 100;
var bonus = 10;
var result = salary - salary * taxRate + bonus;
# Excercise 5
Parentheses
function prefixString(prefix, value) {
return (prefix || '$') + value;
}
var result = prefixString(null, '1,000');
No parentheses
function prefixString(prefix, value) {
return prefix || '$' + value;
}
var result = prefixString(null, '1,000');
# Excercise 6
Parentheses
var employees = 10;
var employeeTurnover = 0.9;
var applications = 3;
var result = applications + (employees * employeeTurnover);
No parentheses
var employees = 10;
var employeeTurnover = 0.9;
var applications = 3;
var result = applications + employees * employeeTurnover;
# Pure Functions
Each of the following snippets contains a function. In one snippet the function is dependent on and/or mutates a variable external to its scope (impure). In the other case, the function is rewritten as a pure function, dependent only on its parameters and without side-effects.
# Exercise 1
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;
# Exercise 2
Pure
var users = [
{ username: 'amy', admin: true },
{ username: 'bob', admin: false },
{ username: 'helen', admin: true },
{ username: 'amir', admin: false },
{ username: 'carmen', admin: false }
];
function countAdmins(userArr) {
var count = 0;
for (var i = 0; i < userArr.length; i++) {
if (userArr[i].admin) {
count = count + 1;
}
}
return count;
}
var result = countAdmins(users);
Impure
var users = [
{ username: 'amy', admin: true },
{ username: 'bob', admin: false },
{ username: 'helen', admin: true },
{ username: 'amir', admin: false },
{ username: 'carmen', admin: false }
];
function countAdmins() {
var count = 0;
for (var i = 0; i < users.length; i++) {
if (users[i].admin) {
count = count + 1;
}
}
return count;
}
var result = countAdmins();
# Exercise 3
Pure
var users = [];
function addUser(users, newUser) {
return [].concat(users, newUser);
}
users = addUser(users, 'bob');
users = addUser(users, 'amy');
users = addUser(users, 'will');
users = addUser(users, 'lin');
var result = users.length;
Impure
var users = [];
function addUser(newUser) {
users.push(newUser);
}
addUser('bob');
addUser('amy');
addUser('will');
addUser('lin');
var result = users.length;
# Exercise 4
Pure
var list = [1, 2, 3];
function doubleItems(input) {
var newList = [];
for (var i = 0; i < input.length; i += 1) {
newList[i] = input[i] * 2;
}
return newList;
}
var result = doubleItems(list)[1];
Impure
var list = [1, 2, 3];
function doubleItems(input) {
for (var i = 0; i < input.length; i += 1) {
input[i] = input[i] * 2;
}
}
doubleItems(list);
var result = list[1];
# Exercise 5
Pure
var animal = {
name: 'Snuffles',
type: 'DOG'
};
function rename(input, newName) {
input.name = newName;
}
rename(animal, 'Snowball');
var result = animal.name;
Impure
var animal = {
name: 'Snuffles',
type: 'DOG'
};
function rename(input, newName) {
return {
name: newName,
type: input.type
};
}
var result = rename(animal, 'Snowball').name;
# Exercise 6
Pure
function calculateMagnitude(vector) {
var magnitudeSquared = (vector.x * vector.x) + (vector.y * vector.y);
var magnitude = Math.sqrt(magnitudeSquared);
return magnitude;
}
var vector = { x: 3, y: 4 };
var result = calculateMagnitude(vector);
Impure
function calculateMagnitude(vector) {
var magnitudeSquared = (vector.x * vector.x) + (vector.y * vector.y);
var magnitude = Math.sqrt(magnitudeSquared);
vector.magnitude = magnitude;
}
var vector = { x: 3, y: 4 };
calculateMagnitude(vector);
var result = vector.magnitude;