Personally, I break it out into variables.
var isAEqualToB = a === b
var isCEqualToD = c === d
var isEEqualToA = e === a
var isAOrDTruthy = a || d
var isEEqualToAAndAOrDTruthy = isEEqualToA && isAOrDTruthy
if ((isAEqualToB || isCEqualToD) && isEEqualToAAndAOrDTruthy) {
// Do your thing here
}
A lot of people think that having fewer lines is a sign of good code, but it's definitely NOT. Readability and maintainability are far more meaningful to every developer who has to deal with any code.
Break out the conditions into very understandable variables (ie use variable names that describe the condition), and reduce it down into simpler things. You may find that breaking your full condition into smaller functions may also help.
So let's do another more meaningful boolean equation. Let's say we only want to execute a block of code if:
- It is between 6am and 2pm
- The value of skyColor is 'grey'
- Your name is either 'ozbarry' or 'web-dev'
- The value of n is either 2 or 999
Based on your current example, we'd start with something like:
var skyColor = 'grey';
var name = 'ozbarry';
var n = 2;
if (
// Condition 1, time is between 6am and 2pm
((new Date()).getHours() >= 6 && (new Date()).getHours() <= 14) &&
// Condition 2, skyColor is 'grey'
(skyColor === 'grey') &&
// Condition 3, name is either 'ozbarry' or 'web-dev'
(name == 'ozbarry' || name == 'web-dev') &&
// Condition 4, n is either 2 or 999
(n == 2 || n == 999)
) {
// Do a thing here
}
This will do the right thing, but this will be a nightmare to maintain, and this is a pretty basic example. Let's do some refactoring!
First, let's pull some of these conditions into variables so we can track them better, and remove comments, since the variable names will reflect what we're testing:
var skyColor = 'grey';
var name = 'ozbarry';
var n = 2;
var isHourBetween6And14 = (new Date()).getHours() >= 6 && (new Date()).getHours() <= 14;
var isSkyGrey = skyColor === 'grey';
var isNameValid = name === 'ozbarry' || name === 'web-dev'
var isN2Or999 = n === 2 || n === 999
if (
isHourBetween6And14 &&
isSkyGrey &&
isNameValid &&
isN2Or999
) {
// Do a thing here
}
This is better, but there is still some problems. Some conditions are still long or unclear from a code perspective. I'm mainly looking at isHourBetween6And14
, but the last two could also use some attention, so let's split these out into meaningful functions:
function isNumberBetween(value, min, max) {
return value >= min && value <= max
}
function isValueOneOf(value, validValues) {
for(validIdx=0; validIdx < validValues.length; validIdx++) {
if (validValues[validIdx] === value) {
return true;
}
}
return false;
}
var skyColor = 'grey';
var name = 'ozbarry';
var n = 2;
var isHourBetween6And14 = isNumberBetween((new Date()).getHours(), 6, 14)
var isSkyGrey = skyColor === 'grey';
var isNameValid = isValueOneOf(name, ['ozbarry', 'web-dev']);
var isN2Or999 = isValueOneOf(n, [2, 999])
if (
isHourBetween6And14 &&
isSkyGrey &&
isNameValid &&
isN2Or999
) {
// Do a thing here
}
Finally, a thing I like to do is join long conditions before the if statement. It will make your condition much more readable while future developers won't need to mentally do the logic each time to know whether it will execute the block:
function isNumberBetween(value, min, max) {
return value >= min && value <= max
}
function isValueOneOf(value, validValues) {
for(validIdx=0; validIdx < validValues.length; validIdx++) {
if (validValues[validIdx] === value) {
return true;
}
}
return false;
}
var skyColor = 'grey';
var name = 'ozbarry';
var n = 2;
var isHourBetween6And14 = isNumberBetween((new Date()).getHours(), 6, 14)
var isSkyGrey = skyColor === 'grey';
var isNameValid = isValueOneOf(name, ['ozbarry', 'web-dev']);
var isN2Or999 = isValueOneOf(n, [2, 999])
var canDoThing = isHourBetween6And14 && isSkyGrey && isNameValie && isN2Or999;
if (canDoThing) {
// Do a thing here
}
This is a completely opinionated way to do things, and most people don't like their code getting larger after a refactor, but it is better to have maintainable code than smaller code.