Why "Clean Code" Is Not About Aesthetics, But About Money and Time
\n\nImagine you open someone else's JavaScript project. Variables are named a, b, x1. A function is 300 lines long. The nesting of conditions is like a Russian doll. Sound familiar? If you've ever cursed such an "author," then you already understand why clean code is needed.
Clean code in JavaScript is not a fashion statement or a perfectionist's whim. It is a tool that saves hours of debugging, simplifies onboarding for newcomers, and reduces the cost of project maintenance. In this article, we will break down specific rules and techniques that will help you write code that is understandable not only to the machine but also to humans.
\n\nRule #1: Variable and Function Names Should Speak for Themselves
\n\nThe most common mistake beginners make is using short, meaningless names. Bad example:
\n\nlet d = new Date();\nlet n = d.getDay();\nlet r = n === 0 || n === 6 ? 'Weekend' : 'Weekday';\nconsole.log(r);\n\n\nGood example:
\n\nconst currentDate = new Date();\nconst dayOfWeek = currentDate.getDay();\nconst isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\nconst dayType = isWeekend ? 'Weekend' : 'Weekday';\nconsole.log(dayType);\n\n\nThe difference is obvious. In the second option, we immediately understand what the code does without additional comments. Tip: use nouns for variables and verbs for functions. For example: getUserData(), calculateTotal(), isValidEmail().
How to Avoid "Magic Numbers"?
\n\nMagic numbers are digits whose meaning is unclear without context. Instead, use constants:
\n\n// Bad\nif (user.role === 1) { ... }\n\n// Good\nconst ROLE_ADMIN = 1;\nif (user.role === ROLE_ADMIN) { ... }\n\n\nRule #2: Functions Should Be Small and Do Only One Thing
\n\nThe Single Responsibility Principle applies not only to classes but also to functions. If a function does three things, it should be split into three functions. Bad example:
\n\nfunction processOrder(order) {\n // Validation\n if (!order.items || order.items.length === 0) {\n throw new Error('Cart is empty');\n }\n // Discount calculation\n let discount = 0;\n if (order.total > 1000) {\n discount = 0.1;\n }\n // Sending email\n sendEmail(order.email, 'Your order has been accepted');\n return order.total - order.total * discount;\n}\n\n\nGood example (refactoring):
\n\nfunction validateOrder(order) {\n if (!order.items || order.items.length === 0) {\n throw new Error('Cart is empty');\n }\n}\n\nfunction calculateDiscount(total) {\n return total > 1000 ? 0.1 : 0;\n}\n\nfunction notifyCustomer(email) {\n sendEmail(email, 'Your order has been accepted');\n}\n\nfunction processOrder(order) {\n validateOrder(order);\n const discount = calculateDiscount(order.total);\n notifyCustomer(order.email);\n return order.total - order.total * discount;\n}\n\n\nThis structure makes it easy to test each part separately and change the logic without affecting the rest of the code.
\n\nRule #3: Avoid Deep Nesting
\n\nThe more levels of nesting (if inside if inside for), the harder the code is to read. Use early return and guard clauses.
\n\n// Bad\nfunction getUserDisplayName(user) {\n if (user) {\n if (user.name) {\n if (user.name.length > 0) {\n return user.name;\n }\n }\n }\n return 'Anonymous';\n}\n\n// Good\nfunction getUserDisplayName(user) {\n if (!user || !user.name || user.name.length === 0) {\n return 'Anonymous';\n }\n return use