You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.5 KiB
4.5 KiB
Clean Code Principles
Category: development
Purpose: Core coding standards and best practices for writing clean, maintainable code
Used by: frontend-specialist, devops-specialist, opencoder
Overview
Clean code is code that is easy to read, understand, and maintain. It follows consistent patterns, uses meaningful names, and is well-organized. This guide provides principles and patterns for writing clean code across all languages.
Core Principles
1. Meaningful Names
Use intention-revealing names:
- Variable names should reveal intent
- Function names should describe what they do
- Class names should describe what they represent
Examples:
// Bad
const d = new Date();
const x = getUserData();
// Good
const currentDate = new Date();
const activeUserProfile = getUserData();
2. Functions Should Do One Thing
Single Responsibility:
- Each function should have one clear purpose
- Functions should be small (ideally < 20 lines)
- Extract complex logic into separate functions
Example:
// Bad
function processUser(user) {
validateUser(user);
saveToDatabase(user);
sendEmail(user);
logActivity(user);
}
// Good
function processUser(user) {
const validatedUser = validateUser(user);
const savedUser = saveUserToDatabase(validatedUser);
notifyUser(savedUser);
return savedUser;
}
3. Avoid Deep Nesting
Keep nesting shallow:
- Use early returns
- Extract nested logic into functions
- Prefer guard clauses
Example:
// Bad
function processOrder(order) {
if (order) {
if (order.items.length > 0) {
if (order.total > 0) {
// process order
}
}
}
}
// Good
function processOrder(order) {
if (!order) return;
if (order.items.length === 0) return;
if (order.total <= 0) return;
// process order
}
4. DRY (Don't Repeat Yourself)
Eliminate duplication:
- Extract common logic into reusable functions
- Use composition over inheritance
- Create utility functions for repeated patterns
5. Error Handling
Handle errors explicitly:
- Use try-catch for expected errors
- Provide meaningful error messages
- Don't ignore errors silently
Example:
// Bad
function fetchData() {
try {
return api.getData();
} catch (e) {
return null;
}
}
// Good
async function fetchData() {
try {
return await api.getData();
} catch (error) {
logger.error('Failed to fetch data', { error });
throw new DataFetchError('Unable to retrieve data', { cause: error });
}
}
Best Practices
- Write self-documenting code - Code should explain itself through clear naming and structure
- Keep functions pure when possible - Avoid side effects, return new values instead of mutating
- Use consistent formatting - Follow language-specific style guides (Prettier, ESLint, etc.)
- Write tests first - TDD helps design better APIs and catch issues early
- Refactor regularly - Improve code structure as you learn more about the domain
- Comment why, not what - Code shows what, comments explain why
- Use type systems - TypeScript, type hints, or static analysis tools
- Favor composition - Build complex behavior from simple, reusable pieces
Anti-Patterns
- ❌ Magic numbers - Use named constants instead of hardcoded values
- ❌ God objects - Classes that do too much or know too much
- ❌ Premature optimization - Optimize for readability first, performance second
- ❌ Clever code - Simple and clear beats clever and complex
- ❌ Long parameter lists - Use objects or configuration patterns instead
- ❌ Boolean flags - Often indicate a function doing multiple things
- ❌ Mutable global state - Leads to unpredictable behavior and bugs
Language-Specific Guidelines
JavaScript/TypeScript
- Use
constby default,letwhen needed, nevervar - Prefer arrow functions for callbacks
- Use async/await over raw promises
- Destructure objects and arrays for clarity
Python
- Follow PEP 8 style guide
- Use list comprehensions for simple transformations
- Prefer context managers (
withstatements) - Use type hints for function signatures
Go
- Follow effective Go guidelines
- Use defer for cleanup
- Handle errors explicitly
- Keep interfaces small
Rust
- Embrace ownership and borrowing
- Use pattern matching
- Prefer iterators over loops
- Handle errors with Result types
References
- Clean Code by Robert C. Martin
- The Pragmatic Programmer by Hunt & Thomas
- Refactoring by Martin Fowler