Introduction
Clean code is essential for maintaining and understanding code effectively. It encompasses several principles and guidelines aimed at enhancing code readability and maintainability.
In this lesson we look at some of the most important clean code principles and guidelines that will assist you in writing clean code.
1. Use Meaningful Names
Meaningful names for variables, functions, and classes make your code self-explanatory and easier to understand.
Use Descriptive Names:
Names should accurately reflect the purpose of the variable or function.
Bad Example:
let n; // Unclear what 'n' stands for
Good Example:
let numberOfStudents; // Clearly indicates its purpose
Avoid Disinformation:
Names should not mislead about a variable’s or function’s purpose.
Bad Example:
let customerData; // Vague and potentially misleading
Good Example:
let customerAddressList; // Specific and informative
Booleans:
Your booleans should have is
, has
, or can
prefixes to indicate that they are booleans.
This helps your functions read more like sentences. e.g.
if (isAdmin) {
// ...
}
Bad Example:
let admin; // Unclear what 'admin' represents
Good Example:
let isAdmin; // Clear that this is a boolean
2. Functions
Functions should be concise, focused, and well-named, doing only what their name suggests.
Small & Focused:
Aim for short functions with a single responsibility.
Bad Example:
function processUser(input) {
// Function does too many things such parsing, validating, and saving user data
}
Good Example:
function calculateCircleArea(radius) {
// Clearly focused on calculating the area of a circle
return Math.PI * radius * radius;
}
Descriptive Names:
Function names should clearly indicate their purpose.
Bad Example:
function processData(id) {
// Unclear what type of data or process
}
Good Example:
function deleteUserAccount(userId) {
// Clearly indicates the purpose
}
3. Limit Arguments
Functions should have a limited number of arguments to simplify their use and understanding.
Bad Example:
function setupUser(name, email, age, isAdmin, location) {
// Too many arguments
}
Good Example:
function setupUser({ name, email, age, isAdmin, location }) {
// Using an object to encapsulate parameters
}
4. Comments
Use comments sparingly and only when necessary to clarify complex code segments.
Bad Example:
// This function calculates interest
function calculateInterest(principal, rate) {
// Obvious comments are unnecessary
}
Good Example:
// Calculates interest for non-standard compounding periods
function calculateCustomInterest(principal, rate, periods) {
// Useful for complex or non-obvious functionality
}
5. Formatting
Well-formatted code is crucial for readability. Stick to conventions and ensure consistency.
Consistent Indentation:
Use a standard indentation style throughout your codebase. This should be 2-letter spacing for JavaScript web development. You should be using Prettier to handle your formatting for you.
Bad Example:
if (condition) {
....// Inconsistent indentation
}
Good Example:
if (condition) {
..// Consistent 2-space indentation
}
Organize Code Logically:
Arrange code blocks and functions in a logical, coherent order.
Bad Example:
// Defining a function in the middle of unrelated code
function unrelatedFunction() {
//...
}
// More unrelated code
function relatedFunctionTwo() {
//...
}
Good Example:
// Grouping related functions together
function relatedFunctionOne() {
//...
}
function relatedFunctionTwo() {
//...
}
6. Error Handling
Proper error handling is key to robust and reliable code.
Don’t Ignore Caught Errors:
Ensure errors are either handled or logged for later review.
Bad Example:
try {
// Risky code
} catch (error) {
// Error ignored
}
Good Example:
try {
// Risky code
} catch (error) {
console.error(error); // Error logged or handled
}
7. Avoid Magic Numbers
Replace magic numbers with named constants to make your code more readable and maintainable.
Bad Example:
function calculateDiscount(price) {
return price * 0.15; // What does 0.15 represent?
}
Good Example:
const DISCOUNT_RATE = 0.15;
function calculateDiscount(price) {
return price * DISCOUNT_RATE; // Clear what 0.15 represents
}
8. Avoid Deep Nesting
Deeply nested code is difficult to read and understand. Aim for a flatter structure.
Bad Example:
if (condition1) {
if (condition2) {
if (condition3) {
// Deeply nested code
}
}
}
Good Example:
if (condition1 && condition2 && condition3) {
// Less nested and clearer
}
// Alternative solution is to create a variable
const isConditionsMet = condition1 && condition2 && condition3;
if (isConditionsMet) {
// Less nested and clearer
}
9. Avoid Premature Optimization
Optimize code only when necessary, and avoid sacrificing readability for small performance gains.
10. DRY (Don’t Repeat Yourself)
Eliminate redundant code by using functions or modules to encapsulate reusable code.
Bad Example:
// Repeating code for calculating area
let area1 = Math.PI * radius1 * radius1;
let area2 = Math.PI * radius2 * radius2;
Good Example:
function calculateArea(radius) {
return Math.PI * radius * radius;
}
let area1 = calculateArea(radius1);
let area2 = calculateArea(radius2);
11. Destructure Objects & Arrays
Destructuring objects and arrays provides many benefits, including:
- make your code more concise and readable
- avoid repeating property names
- avoid creating temporary variables
- extract only the data you need from objects and arrays
Bad Example:
const user = {
name: 'John',
age: 30,
location: 'London'
};
const name = user.name;
const age = user.age;
const location = user.location;
Good Example:
const user = {
name: 'John',
age: 30,
location: 'London'
};
const { name, age, location } = user;
References
Hunt, A. and Thomas, D., 2019. The Pragmatic Programmer: Your Journey to Mastery, 20th Anniversary Edition. 2nd ed. Boston: Addison-Wesley.
Martin, R.C., 2008. Clean Code: A Handbook of Agile Software Craftsmanship. 1st ed. Upper Saddle River, NJ: Prentice Hall.