Return early from a function when checking initial conditions
When conditionally executing logic in a function based on some initial condition(s), consider returning early.
Guards implement this pattern.
❌Bad:
function getConfigOption(filePath, key) {
if (typeof filePath === 'string') {
const contents = fs.readFileSync(filePath, 'utf8');
const configJson = JSON.parse(contents);
return configJson[key];
} else {
throw new Error('No config file path was supplied');
}
}
✅Good:
function getConfigOption(filePath, key) {
if (!filePath) {
throw new Error('No config file path was supplied');
}
const contents = fs.readFileSync(filePath, 'utf8');
const configJson = JSON.parse(contents);
return configJson[key];
}
By returning (or throwing!) early, we reduce the level of nesting for the rest of the function, improving readability.
You can write multiple guards at the top of the function:
function getConfigOption(filePath, key) {
assert(typeof filePath === 'string', 'config file path must be supplied');
assert(typeof key === 'string', 'config key must be supplied');
const contents = fs.readFileSync(filePath, 'utf8');
const configJson = JSON.parse(contents);
return configJson[key];
}
Note: This doesn't advocate for randomly returning in the middle of a function - which would be somewhat chaotic :)
Further reading: