Por qué el «código limpio» no es cuestión de estética, sino de dinero y tiempo
\n\nImagina que abres un proyecto ajeno en JavaScript. Las variables se llaman a, b, x1. Una función de 300 líneas. La anidación de condiciones es como una muñeca rusa. ¿Te suena? Si alguna vez has maldecido a un «autor» así, entonces ya entiendes para qué sirve el código limpio.
El código limpio en JavaScript no es una moda ni un capricho de perfeccionista. Es una herramienta que ahorra horas de depuración, simplifica la incorporación de nuevos desarrolladores y reduce el costo de mantenimiento del proyecto. En este artículo analizaremos reglas y técnicas concretas que te ayudarán a escribir código comprensible no solo para la máquina, sino también para las personas.
\n\nRegla n.º 1: Los nombres de variables y funciones deben hablar por sí solos
\n\nEl error más común de los principiantes es usar nombres cortos y sin significado. Mal ejemplo:
\n\nlet d = new Date();\nlet n = d.getDay();\nlet r = n === 0 || n === 6 ? 'Fin de semana' : 'Día laborable';\nconsole.log(r);\n\n\nBuen ejemplo:
\n\nconst currentDate = new Date();\nconst dayOfWeek = currentDate.getDay();\nconst isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\nconst dayType = isWeekend ? 'Fin de semana' : 'Día laborable';\nconsole.log(dayType);\n\n\nLa diferencia es evidente. En la segunda opción entendemos de inmediato qué hace el código, sin comentarios adicionales. Consejo: usa sustantivos para variables y verbos para funciones. Por ejemplo: getUserData(), calculateTotal(), isValidEmail().
¿Cómo evitar los «números mágicos»?
\n\nLos números mágicos son dígitos cuyo significado no se entiende sin contexto. En su lugar, usa constantes:
\n\n// Mal\nif (user.role === 1) { ... }\n\n// Bien\nconst ROLE_ADMIN = 1;\nif (user.role === ROLE_ADMIN) { ... }\n\n\nRegla n.º 2: Las funciones deben ser pequeñas y hacer solo una cosa
\n\nEl principio de responsabilidad única (Single Responsibility) se aplica no solo a las clases, sino también a las funciones. Si una función hace tres cosas, debe dividirse en tres funciones. Mal ejemplo:
\n\nfunction processOrder(order) {\n // Validación\n if (!order.items || order.items.length === 0) {\n throw new Error('El carrito está vacío');\n }\n // Cálculo de descuento\n let discount = 0;\n if (order.total > 1000) {\n discount = 0.1;\n }\n // Envío de email\n sendEmail(order.email, 'Su pedido ha sido recibido');\n return order.total - order.total * discount;\n}\n\n\nBuen ejemplo (refactorización):
\n\nfunction validateOrder(order) {\n if (!order.items || order.items.length === 0) {\n throw new Error('El carrito está vacío');\n }\n}\n\nfunction calculateDiscount(total) {\n return total > 1000 ? 0.1 : 0;\n}\n\nfunction notifyCustomer(email) {\n sendEmail(email, 'Su pedido ha sido recibido');\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\nEsta estructura permite probar fácilmente cada parte por separado y cambiar la lógica sin afectar el resto del código.
\n\nRegla n.º 3: Evita la anidación profunda
\n\nCuantos más niveles de anidación (if dentro de if dentro de for), más difícil es leer el código. Usa retorno temprano (early return) y cláusulas de guarda (guard clauses).
\n\n// Mal\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 'Anónimo';\n}\n\n// Bien\nfunction getUserDisplayName(user) {\n if (!user || !user.name || user.name.length === 0) {\n return 'Anónimo';\n }\n return use