Clean Code Principles Every Developer Should Follow
Clean code is code that is easy to read, understand, and maintain. Here are the principles that will make you a better developer.
Meaningful Names
Variables
// Bad
const d = new Date();
const arr = users.filter(u => u.a > 18);
// Good
const currentDate = new Date();
const adultUsers = users.filter(user => user.age > 18);Functions
// Bad
function process(data) { ... }
function handle(x, y) { ... }
// Good
function validateUserInput(formData) { ... }
function calculateTotalPrice(items, discount) { ... }Booleans
// Bad
const flag = true;
const val = user.active;
// Good
const isLoading = true;
const hasPermission = user.isAdmin;
const canEdit = document.isOwner && !document.isLocked;Functions
Keep Functions Small
// Bad - Does too many things
function processUser(user) {
// Validate user
if (!user.name || !user.email) throw new Error('Invalid');
// Format data
user.name = user.name.trim();
user.email = user.email.toLowerCase();
// Save to database
database.save(user);
// Send email
emailService.send(user.email, 'Welcome!');
// Log activity
logger.log('User created', user.id);
}
// Good - Single responsibility
function validateUser(user) {
if (!user.name || !user.email) {
throw new Error('Name and email are required');
}
}
function formatUserData(user) {
return {
...user,
name: user.name.trim(),
email: user.email.toLowerCase(),
};
}
async function createUser(userData) {
validateUser(userData);
const formattedUser = formatUserData(userData);
const user = await database.save(formattedUser);
await emailService.sendWelcome(user.email);
logger.info('User created', { userId: user.id });
return user;
}Limit Parameters
// Bad
function createUser(name, email, age, address, phone, role) { ... }
// Good
interface CreateUserParams {
name: string;
email: string;
age?: number;
address?: string;
phone?: string;
role?: string;
}
function createUser(params: CreateUserParams) { ... }Avoid Side Effects
// Bad - Mutates input
function addItem(cart, item) {
cart.items.push(item);
return cart;
}
// Good - Returns new object
function addItem(cart, item) {
return {
...cart,
items: [...cart.items, item],
};
}Avoid Magic Numbers
// Bad
if (user.age >= 18) { ... }
if (password.length < 8) { ... }
setTimeout(callback, 86400000);
// Good
const LEGAL_AGE = 18;
const MIN_PASSWORD_LENGTH = 8;
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
if (user.age >= LEGAL_AGE) { ... }
if (password.length < MIN_PASSWORD_LENGTH) { ... }
setTimeout(callback, ONE_DAY_MS);Early Returns
// Bad - Nested conditions
function getDiscount(user) {
let discount = 0;
if (user) {
if (user.isPremium) {
if (user.yearsActive > 2) {
discount = 20;
} else {
discount = 10;
}
}
}
return discount;
}
// Good - Guard clauses
function getDiscount(user) {
if (!user) return 0;
if (!user.isPremium) return 0;
if (user.yearsActive > 2) return 20;
return 10;
}Comments
Avoid Obvious Comments
// Bad
// Loop through users
users.forEach(user => { ... });
// Increment counter
counter++;
// Good - Explain why, not what
// Filter inactive users to prevent sending emails to abandoned accounts
const activeUsers = users.filter(user => user.lastLogin > thirtyDaysAgo);Use Self-Documenting Code
// Bad
// Check if user can access admin panel
if (user.role === 'admin' || user.role === 'superadmin') { ... }
// Good
const canAccessAdminPanel = (user) =>
['admin', 'superadmin'].includes(user.role);
if (canAccessAdminPanel(user)) { ... }Error Handling
// Bad
function getUser(id) {
try {
return database.find(id);
} catch (e) {
console.log(e);
return null;
}
}
// Good
class UserNotFoundError extends Error {
constructor(userId: string) {
super(`User not found: ${userId}`);
this.name = 'UserNotFoundError';
}
}
async function getUser(id: string) {
const user = await database.find(id);
if (!user) {
throw new UserNotFoundError(id);
}
return user;
}DRY (Don't Repeat Yourself)
// Bad - Repetition
const adminEmails = users
.filter(u => u.role === 'admin')
.map(u => u.email);
const editorEmails = users
.filter(u => u.role === 'editor')
.map(u => u.email);
// Good - Abstraction
const getEmailsByRole = (users, role) =>
users.filter(u => u.role === role).map(u => u.email);
const adminEmails = getEmailsByRole(users, 'admin');
const editorEmails = getEmailsByRole(users, 'editor');SOLID Principles Summary
- Single Responsibility - One reason to change
- Open/Closed - Open for extension, closed for modification
- Liskov Substitution - Subtypes replaceable for base types
- Interface Segregation - Small, specific interfaces
- Dependency Inversion - Depend on abstractions
Code Review Checklist
- Is the code easy to understand?
- Are names meaningful and consistent?
- Are functions small and focused?
- Is there unnecessary duplication?
- Are edge cases handled?
- Is error handling appropriate?
- Are there any magic numbers/strings?
- Is the code testable?
Clean code is not about being clever—it's about being clear. Write code that your future self will thank you for!