Extracting a function is a great way to improve reusability of your code—you see a piece of code repeated throughout the codebase, you create a function with that common code, and then you replace all repeated code with that function call. But it’s not the only reason to extract a function.
Another reason to extract a function is to give a block of complex code a name to reveal the intent of that code—to make it easier to read.
A common place for this complex code is conditional—sometimes you have multiple &&
s and ||
s to check for something before running some other code. Extracting that conditional to a well-named function will make your code easier to read and understand.
Example
In this example, I have a function that adds a product to the user’s shopping cart. The shopping cart accepts the product as an object with some specific fields—like name and price.
addProductToShoppingCart(user, product) {
let price
if (
user.totalOrders === 0 ||
(user.shoppingCart.length > 5 && product.price >= 50)
) {
price = product.price * 0.8
} else {
price = product.price
}
const productToAdd = {
name: product.name,
date: Date.now(),
price: price
}
// ...
}
The if statement above checks if the user can have a discount for that product. Reading the details for that conditional is not necessary unless you want to modify it.
So, I can hide these details by extracting the conditional to a function with a name showing its intent.
addProductToShoppingCart(user, product) {
let price
if (canGetADiscount()) {
price = product.price * 0.8
} else {
price = product.price
}
const productToAdd = {
name: product.name,
date: Date.now(),
price: price
}
function canGetADiscount() {
return user.totalOrders === 0 ||
(user.shoppingCart.length > 5 && product.price >= 50)
}
// ...
}
Since I have defined that function inside addProductToShoppingCart
, I can access all of its data without passing any parameters—which would make it shorter and clearer.
To make the code even easier to read, I can reformat that part using the ternary operator—it wasn’t a good idea before because the conditional logic was very long.
addProductToShoppingCart(user, product) {
const price = canGetADiscount() ? product.price * 0.8 : product.price
// ...