Clean Code
La documentación sobre Clean Code se basa en una serie de principios y prácticas que ayudan a escribir código más legible, mantenible y escalable. El concepto fue popularizado por el libro “Clean Code” de Robert C. Martin, también conocido como “Uncle Bob”.
Principios Clave de Clean Code
1. Nombres Significativos
El código debe ser fácilmente comprensible por otros desarrolladores (o por ti mismo en el futuro). Los nombres de variables, funciones y clases deben describir claramente su propósito.
Mal ejemplo:
let d; // ¿Qué significa "d"?Buen ejemplo:
let userRegistrationDate; // El propósito es claro2. Funciones Pequeñas y Simples
Las funciones deben hacer una sola cosa y hacerlo bien. Si una función tiene múltiples responsabilidades, es más difícil de leer y mantener.
Mal ejemplo:
function processOrder(order) { validateOrder(order); chargeCreditCard(order); updateInventory(order); sendConfirmationEmail(order);}Buen ejemplo:
function processOrder(order) { validateOrder(order); charge(order); updateInventory(order); notifyCustomer(order);}
function charge(order) { chargeCreditCard(order);}
function notifyCustomer(order) { sendConfirmationEmail(order);}3. Evita Comentarios Innecesarios
El código debería explicarse por sí mismo. Si necesitas demasiados comentarios, el código puede estar mal escrito o los nombres de las funciones/variables no son lo suficientemente descriptivos.
Mal ejemplo:
// Verifica si el usuario está logueadoif (user.isLoggedIn()) { // Envía un email de confirmación sendEmail(user);}Buen ejemplo:
if (user.isLoggedIn()) { sendConfirmationEmail(user);}4. Evita Códigos Duplicados
El código duplicado hace que sea más difícil de mantener y actualizar. Utiliza funciones reutilizables.
Mal ejemplo:
function getUserFullName(user) { return user.firstName + " " + user.lastName;}
function getCustomerFullName(customer) { return customer.firstName + " " + customer.lastName;}Buen ejemplo:
function getFullName(person) { return person.firstName + " " + person.lastName;}5. Mantén los Métodos con Pocos Parámetros
Las funciones con muchos parámetros son difíciles de leer y pueden generar errores. Intenta reducir el número de parámetros o agruparlos en objetos.
Mal ejemplo:
function createUser(firstName, lastName, email, age, address) { // Crear el usuario}Buen ejemplo:
function createUser(user) { // Crear el usuario}
let user = { firstName: "John", lastName: "Doe", email: "john.doe@example.com", age: 30, address: "123 Main St",};6. Usa Variables y Constantes en Lugar de Números Mágicos
Los números “mágicos” en el código son valores numéricos cuyo significado no es claro. Es mejor asignar esos valores a constantes con nombres descriptivos.
Mal ejemplo:
if (age > 65) { console.log("Senior");}Buen ejemplo:
const SENIOR_AGE = 65;if (age > SENIOR_AGE) { console.log("Senior");}7. No Reutilices Variables para Propósitos Diferentes
Reutilizar variables con propósitos diferentes puede confundir a quien lee el código.
Mal ejemplo:
let temp = 10; // temp se usa para la temperaturatemp = "John"; // ahora se usa para el nombre del usuarioBuen ejemplo:
let temperature = 10;let userName = "John";8. Usa Objetos en Lugar de Booleanos como Parámetros
Si una función necesita un parámetro booleano para controlar el flujo, es mejor pasar un objeto que contenga todos los valores relevantes.
Mal ejemplo:
function showUserProfile(isAdmin) { if (isAdmin) { // Mostrar perfil de admin } else { // Mostrar perfil de usuario }}Buen ejemplo:
function showUserProfile(user) { if (user.isAdmin) { // Mostrar perfil de admin } else { // Mostrar perfil de usuario }}9. Manejo Correcto de Errores
En lugar de capturar errores en todo el código, intenta manejarlos en los puntos específicos donde ocurren y con mensajes significativos.
Mal ejemplo:
try { // Mucho código aquí...} catch (error) { console.log("Something went wrong");}Buen ejemplo:
try { processPayment();} catch (error) { console.log("Error processing payment: " + error.message);}10. Sigue el Principio de Responsabilidad Única (SRP)
Cada clase o módulo debe tener una única razón para cambiar. Es decir, debe ser responsable de una sola cosa.
Mal ejemplo:
class UserService { createUser() { // Lógica de creación de usuario }
sendWelcomeEmail() { // Lógica de enviar email de bienvenida }
logUserCreation() { // Lógica para registrar en logs }}Buen ejemplo:
class UserService { createUser() { // Lógica de creación de usuario }}
class EmailService { sendWelcomeEmail() { // Lógica de enviar email de bienvenida }}
class LogService { logUserCreation() { // Lógica para registrar en logs }}Diagrama de Flujo para Refactorización Clean Code
Supongamos que tienes que refactorizar una función que se encarga de procesar una orden y tiene varias responsabilidades mezcladas. Aquí un diagrama de flujo para dividirlo en varias funciones:
- Identificar las responsabilidades: Procesar la orden, validar los datos, actualizar el inventario y enviar notificaciones.
- Crear funciones específicas para cada responsabilidad:
validateOrder(),chargeCustomer(),updateInventory(),sendConfirmationEmail(). - Encapsular en una función principal:
processOrder()llamará a cada una de estas funciones.
graph TD; A[processOrder] --> B[validateOrder] A --> C[chargeCustomer] A --> D[updateInventory] A --> E[sendConfirmationEmail]