Clean Code: 12 Practices That Make Your Code Easy to Read, Change and Maintain
Twelve practical clean code practices: meaningful names, small functions, single responsibility, DRY, clear error handling, comments that matter, consistent formatting, tests, refactoring and code reviews.
- November 10Last updated
- 5min read
- 22sections
- 4trusted sources

On this page
- 1. Use meaningful names
- 2. Keep functions small and focused
- 3. Single responsibility
- 4. Don't repeat yourself (DRY), sensibly
- 5. Avoid magic numbers and strings
- 6. Handle errors explicitly
- 7. Write comments that explain why, not what
- 8. Consistent formatting
- 9. Keep nesting shallow
- 10. Write tests for important behavior
- 11. Refactor continuously, in small steps
- 12. Use version control and code reviews
- Why clean code matters for business owners
- Before and after: a refactoring example
- Code smells to watch for
- Clean code in a team
- Clean code and AI tools
- A practical checklist before you commit
- Example: naming in practice
- Testing pyramid
- Glossary
- Frequently asked questions
- Write code for humans first: clear names and small, focused functions.
- One responsibility per function, class and module.
- Handle errors explicitly and fail with clear messages.
- Tests and small refactors keep code healthy as it grows.
- Consistent formatting and code reviews make a team's code feel like one person wrote it.
Code is read far more often than it's written. You'll reread your own code months later, a teammate will extend it, and a future developer may inherit the whole project. Clean code is code that someone else, or future you, can understand and change safely without fear. For business owners, it's the difference between a product that can keep growing and one that becomes too expensive to touch.
These twelve practices apply to any language, with short examples you can use immediately.
1. Use meaningful names
Names should say what something is or does. d tells you nothing; daysUntilRenewal tells you everything.
// unclear
const d = 7;
function calc(a, b) { return a * b * 0.15; }
// clear
const RENEWAL_REMINDER_DAYS = 7;
function calculateVat(price, quantity) { return price * quantity * 0.15; }2. Keep functions small and focused
A function should do one thing well. If you need "and" to describe it ("validates the form and sends the email and logs the result"), split it.
3. Single responsibility
Each module or class should have one reason to change. Mixing database code, business rules and UI in one place makes every change risky.
4. Don't repeat yourself (DRY), sensibly
Duplicate logic means duplicate bugs. Extract shared logic into functions, but don't over-abstract code that only looks similar by coincidence.
5. Avoid magic numbers and strings
Replace unexplained values with named constants: MAX_LOGIN_ATTEMPTS = 5 rather than a bare 5 hidden in a condition.
6. Handle errors explicitly
Don't swallow errors silently. Validate inputs early, return clear error messages, and log enough context to debug.
def get_user(user_id):
if not user_id:
raise ValueError("user_id is required")
user = db.find_user(user_id)
if user is None:
raise LookupError(f"User {user_id} not found")
return user7. Write comments that explain why, not what
Good code explains *what* it does through names. Comments should explain *why*: a business rule, a workaround or a non-obvious decision.
8. Consistent formatting
Use an automatic formatter and linter (Prettier, ESLint, Black, ktlint) so style debates disappear and diffs stay small.
9. Keep nesting shallow
Deep if nesting is hard to follow. Use early returns to handle edge cases first.
function canCheckout(cart, user) {
if (!user) return false;
if (cart.items.length === 0) return false;
if (!user.hasVerifiedPhone) return false;
return true;
}10. Write tests for important behavior
Tests let you change code with confidence. Start with the logic that would hurt most if it broke: prices, permissions, payments and data validation.
11. Refactor continuously, in small steps
Leave code a little cleaner than you found it. Small refactors with tests are safe; big rewrites are risky.
12. Use version control and code reviews
Commit small, meaningful changes with clear messages, and have someone review code before it's merged. See Git and GitHub for beginners.
Why clean code matters for business owners
| Messy code | Clean code |
|---|---|
| Every change takes longer and breaks something else | Changes are predictable and faster |
| Only the original developer understands it | Any competent developer can continue |
| Bugs hide in duplicated logic | Logic lives in one place |
| Rewrites become inevitable | The product can evolve for years |
When you hire a developer, ask how they structure code, test it and document it. It's a strong signal of long-term cost. See How to choose a developer.
Before and after: a refactoring example
// Before
function p(o) {
if (o.t == 1) { return o.a * 1.15; }
else { return o.a; }
}// After
const VAT_RATE = 0.15;
function totalWithVat(order) {
if (!order.isTaxable) return order.amount;
return order.amount * (1 + VAT_RATE);
}The logic didn't change, but names, constants and a guard clause make it obvious what the function does and safe to modify.
Code smells to watch for
| Smell | What it looks like | Typical fix |
|---|---|---|
| Long function | Scrolls past the screen, many responsibilities | Extract smaller functions |
| Long parameter list | Five or more arguments | Pass an object, group related values |
| Duplicated logic | The same rule in several files | Extract a shared function or module |
| Deep nesting | Many levels of if/else | Early returns, guard clauses |
| God object | One class knows everything | Split by responsibility |
| Comments explaining confusing code | "This is tricky because..." | Rename and simplify instead |
Clean code in a team
- Agree on a style guide and automate it with a formatter and linter.
- Keep pull requests small so reviews are thorough.
- Review for clarity and correctness, not personal taste.
- Write a short README and keep setup steps current.
- Leave the code a little better than you found it.
Clean code and AI tools
AI assistants can generate code quickly, but they don't remove the need for clean code. Read every suggestion, rename unclear variables, remove unnecessary parts, and add tests. Treat AI output like code from a new team member: helpful, but reviewed.
A practical checklist before you commit
- Do names explain intent?
- Does each function do one thing?
- Are errors handled clearly?
- Is there duplicated logic I can remove?
- Are there tests for important behavior?
- Would a new developer understand this in five minutes?
Example: naming in practice
| Unclear | Clear |
|---|---|
d | deliveryDate |
getData() | fetchActiveOrders() |
flag | isPaymentConfirmed |
list2 | pendingInvoices |
handle() | sendBookingReminder() |
Good names remove the need for many comments and make code reviews faster.
Testing pyramid
Write many fast unit tests for logic, fewer integration tests for how parts work together, and a small number of end-to-end tests for critical user journeys like sign-up and checkout.
Glossary
| Term | Meaning |
|---|---|
| Refactoring | Improving code structure without changing behaviour |
| Technical debt | Future cost of shortcuts taken today |
| Linter | Tool that flags style and possible bugs |
| Code review | Teammates checking code before it's merged |
| DRY | Don't Repeat Yourself |
| SRP | Single Responsibility Principle |
Frequently asked questions
Does clean code make development slower?
Slightly at first, but much faster over the life of a project, because changes and fixes become cheaper.
Should every function have a comment?
No. Prefer clear names; add comments for intent, business rules and non-obvious decisions.
Which book should I read on clean code?
"Clean Code" by Robert C. Martin and "Refactoring" by Martin Fowler are classics; apply their ideas pragmatically to your language and team.
Is AI-generated code clean?
Not automatically. Review it like any other code for naming, structure, edge cases and security.
Does clean code make programs slower?
Rarely in any noticeable way. Readable code is easier to optimize where it actually matters.
How do I convince my team to write cleaner code?
Start with automated formatting and linting, small pull requests and agreed conventions. Lead by example in reviews.
Is clean code only for large projects?
No. Small projects grow, and clean habits are easiest to build from the start.

Web & App Development
Websites and apps built with clean, documented code that any developer can maintain.
Keep reading
Web Design & DevelopmentGit and GitHub for Beginners: A Practical Guide From Your First Command to Publishing Your Project
Learn Git and GitHub step by step: what version control is, installing Git, essential commands, branches, merging, pull requests, .gitignore, publishing with GitHub Pages and good habits.
5 min read
Web Design & DevelopmentHow to Learn Programming From Zero: A Practical Roadmap for Complete Beginners
A practical roadmap to learn programming from scratch: choosing a path, fundamentals, the first 12 weeks, projects, Git, problem solving, using AI tools wisely, building a portfolio and getting your first work.
5 min read
Web Design & DevelopmentWhat Is a REST API? A Simple Explanation for Beginners With Practical Examples
REST APIs explained simply: clients and servers, resources and endpoints, HTTP methods, status codes, JSON, authentication, versioning, pagination, security and how apps and websites use APIs.
5 min read