José Matos
•12 May 2023
When it comes to software engineering, writing code is just part of the job. Writing clean and maintainable code is what sets top software engineers apart. Clean code practices make it easier for other developers to read and modify your code, reducing the likelihood of errors and improving overall team productivity. In this article, we’ll explore some tips from top software engineers on how to master the art of clean code.
One of the most important practices when it comes to clean code is writing clear and descriptive names for variables, functions, and classes. Using descriptive names makes your code more readable and makes it easier for future developers to understand your code. Avoid using abbreviations or single-letter names that don't describe the purpose of the variable or function. As an example:
/* DO NOT USE */
let a = 'John';
let b = 'Doe';
/* USE DESCRIPTIVE NAMES INSTEAD */
let firstName = 'John';
let lastName = 'Doe';
Functions should be short and focused on a single task. This makes it easier to understand what the function does and reduces the likelihood of errors. A good rule of thumb is to keep your functions under 20 lines of code. If your function is longer than that, consider breaking it down into smaller functions. For instance:
/* DO NOT USE */
function calculateTotalPrice(items) {
for (let i = 0; i < items.length; i++) {
/* Many lines of complex logic */
}
/* Many lines of complex logic */
return totalPrice;
}
/* USE FOCUSED FUNCTIONS INSTEAD */
function calculateTotalPrice(items) {
let totalPrice = 0;
items.forEach((item) => {
totalPrice += item.price;
});
return totalPrice;
}
Complex code is difficult to understand and debug. Try to keep your code as simple as possible by breaking down complex problems into smaller, more manageable tasks. Avoid nested loops or conditionals, excessive use of variables, and long function chains. Here is an example:
/* DO NOT USE */
for (let i = 0; i < countries.length; i++) {
for (let j = 0; j < countries[i].cities.length; j++) {
if (countries[i].cities[j].name === 'New York') {
console.log('New York found in ' + countries[i].name);
return;
}
}
}
/* USE SIMPLER CODE INSTEAD */
const targetCity = 'New York';
const countryWithCity = countries.find((country) => {
return country.cities.some((city) => {
return city.name === targetCity;
});
});
console.log(`${targetCity} found in ${countryWithCity.name}`);
Following standard formatting rules makes your code more readable by making it consistent. Use consistent whitespace, indentation, and line breaks. Also, make sure to format your code according to the standards of the programming language you are using. For example:
/* DO NOT USE */
function printDetails(firstName,lastName,age,jobTitle){
console.log("Name: "+ firstName + " " + lastName);
console.log("Age: " + age);
console.log("Job Title: " + jobTitle);
}
/* USE STANDARD FORMATTING INSTEAD */
function printDetails(firstName, lastName, age, jobTitle) {
console.log(`Name: ${firstName} ${lastName}`);
console.log(`Age: ${age}`);
console.log(`Job Title: ${jobTitle}`);
}
Comments are an important part of clean code. They help other developers understand your code and provide context for future modifications. Comment any code that is not immediately obvious or where you have made a design decision that is not immediately clear. However, be careful not to use comments as a substitute for clear and self-explanatory code. Do not add redundant comments that repeat what the code is doing:
/* DO NOT USE */
// Adds two numbers
function add(a, b) {
return a + b;
}
/* MAYBE USEFUL INSTEAD */
// Calculates the sum of two numbers
function add(a, b) {
return a + b;
}
Testing your code is essential to writing clean and maintainable code. By testing your code, you can make sure it behaves as expected and doesn't have any bugs. Writing tests also helps other developers understand how your code works and how it is supposed to behave. Make sure to test your code for edge cases and exceptions, and automate as much of your testing as possible. For example:
// EXAMPLE OF TESTING
function convertKnotsToMPH(knots) {
return knots * 1.15078;
}
// Test cases for convertKnotsToMPH()
describe('convertKnotsToMPH()', () => {
it('should convert 10 knots to 11.5078 MPH', () => {
expect(convertKnotsToMPH(10)).toBeCloseTo(11.5078, 2);
});
it('should convert 30 knots to 34.5234 MPH', () => {
expect(convertKnotsToMPH(30)).toBeCloseTo(34.5234, 2);
});
});
Mastering the art of clean code is an essential skill for any software engineer. Following the tips above will help you write more maintainable and efficient code that is easier to read and understand. Remember to keep your code simple, well-organized, and thoroughly tested. By doing so, you'll not only impress your colleagues and managers, but you'll also be able to build software that is faster, more reliable, and more enjoyable to work with.