Código Limpio: Funciones (en Javascript)
¿Está cansado de luchar con funciones complejas y difíciles de entender en su base de código? ¿Quiere escribir funciones que sean más fáciles de mantener, reutilizables y menos propensas a errores? Si es así, entonces necesita aprender sobre "Código limpio: funciones". Al seguir las mejores prácticas descritas en el libro "Clean Code" de Robert C. Martin, puede aprender a escribir funciones que sean más fáciles de leer, probar y mantener. En esta publicación de blog, exploraremos los conceptos clave de las funciones de código limpio y le brindaremos consejos prácticos y ejemplos para ayudarlo a implementar estos conceptos en su propio código. Con nuestra ayuda, puede llevar sus habilidades de codificación al siguiente nivel y escribir funciones con las que es un placer trabajar. Entonces, ¿estás listo para aprender sobre las funciones de código limpio? ¡Vamos a sumergirnos!
Tabla de contenidos
· Las funciones pequeñas son mejores que las grandes
· Las funciones deben hacer una cosa
· Las funciones deben tener nombres descriptivos
· Las funciones deben tener un número limitado de argumentos
· Las funciones no deben tener efectos secundarios
· Las funciones no deben depender de variables globales
· Las funciones no deben ser demasiado Profundamente anidado
· Usar excepciones, no códigos de error
· Conclusión
Las funciones pequeñas son mejores que las grandes
Las funciones pequeñas son más fáciles de leer y comprender porque generalmente hacen una cosa y tienen un propósito claro. Esto también los hace más fáciles de probar y mantener porque hay menos código para revisar o modificar. Las funciones grandes, por otro lado, pueden ser más complejas y difíciles de entender, lo que puede generar errores o errores.
// Large function
function processOrders(orders) {
const total = orders.reduce((acc, order) => acc + order.price, 0);
const orderIds = orders.map(order => order.id);
const orderCount = orders.length;
const orderSummary = `You have ${orderCount} orders with IDs ${orderIds.join(', ')} for a total of $${total}.`;
console.log(orderSummary);
return orderSummary;
}
// --------------------------------------------------------------
// Refactored into smaller functions
function getTotalPrice(orders) {
return orders.reduce((acc, order) => acc + order.price, 0);
}
function getOrderIds(orders) {
return orders.map(order => order.id);
}
function getOrderCount(orders) {
return orders.length;
}
function generateOrderSummary(orders) {
const total = getTotalPrice(orders);
const orderIds = getOrderIds(orders);
const orderCount = getOrderCount(orders);
return `You have ${orderCount} orders with IDs ${orderIds.join(', ')} for a total of $${total}.`;
}
function logOrderSummary(orders) {
const orderSummary = generateOrderSummary(orders);
console.log(orderSummary);
return orderSummary;
}
La getTotalPrice()función toma una matriz de pedidos y devuelve su precio total usando la reduce()función para resumir el precio de cada pedido. La getOrderIds()función toma una matriz de pedidos y devuelve una matriz de sus ID usando la map()función. La getOrderCount()función toma una matriz de pedidos y devuelve su recuento mediante el uso de la lengthpropiedad. Finalmente, la generateOrderSummary()función toma una matriz de órdenes y usa las tres funciones más pequeñas para generar una cadena de resumen. La logOrderSummary()función toma una matriz de pedidos y registra la cadena de resumen en la consola.
Las funciones deben hacer una cosa
Cada función debe tener un propósito claro y distinto. Cuando una función hace varias cosas, puede volverse más difícil de entender, probar y mantener. Al dividir una tarea más grande en funciones más pequeñas, podemos crear un código más legible y mantenible.
// Function that performs multiple tasks
function processUserInput(input) {
const inputLines = input.split('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n');
const trimmedLines = inputLines.map(line => line.trim());
const nonEmptyLines = trimmedLines.filter(line => line !== '');
const formattedLines = nonEmptyLines.map(line => `> ${line}`);
return formattedLines.join('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n');
}
// --------------------------------------------------------------
// Refactored into smaller functions
function splitInput(input) {
return input.split('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n');
}
function trimLines(lines) {
return lines.map(line => line.trim());
}
function removeEmptyLines(lines) {
return lines.filter(line => line !== '');
}
function formatLines(lines) {
return lines.map(line => `> ${line}`);
}
function joinLines(lines) {
return lines.join('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n');
}
function processUserInput(input) {
const lines = splitInput(input);
const trimmedLines = trimLines(lines);
const nonEmptyLines = removeEmptyLines(trimmedLines);
const formattedLines = formatLines(nonEmptyLines);
return joinLines(formattedLines);
}
La splitInput()función toma una cadena y usa el split()método para dividirla en una matriz de líneas. La trimLines()función toma una matriz de líneas y usa el map()método para eliminar cualquier espacio en blanco al principio y al final de cada línea. La removeEmptyLines()función toma una matriz de líneas y usa el filter()método para eliminar las líneas vacías. La formatLines()función toma una matriz de líneas y usa el map()método para agregar un >carácter al comienzo de cada línea. La joinLines()función toma una matriz de líneas y usa el join()método para unirlas en una sola cadena, separadas por saltos de línea. Finalmente, la processUserInput()función usa las funciones más pequeñas para procesar la cadena de entrada.
Las funciones deben tener nombres descriptivos
Los nombres de las funciones deben describir con precisión lo que hace la función y deben ser fáciles de entender sin tener que leer la implementación de la función. Un nombre de función descriptivo puede ayudar a que el código se explique por sí mismo y reducir la necesidad de comentarios.
// Function with a vague name
function processData(data) {
// ...
}
// --------------------------------------------------------------
// Refactored with a descriptive name
function processUserData(userData) {
// ...
}
Las funciones deben tener un número limitado de argumentos
Las funciones que toman una gran cantidad de argumentos pueden ser más difíciles de usar, comprender y probar. Trate de mantener el número de argumentos por debajo de tres o cuatro, si es posible. Una forma de reducir el número de argumentos es pasarlos como un único objeto o estructura de datos.
// Function with too many arguments
function createPerson(name, age, address, phone, email) {
// ...
}
// --------------------------------------------------------------
// Refactored to use an object instead
function createPerson(personData) {
// ...
}
// Now, we can pass an object with properties for name, age, address, phone, and email:
const personData = {
name: 'John Doe',
age: 30,
address: '123 Main St',
phone: '555-555-1234',
email: '[email protected]'
};
const person = createPerson(personData);
Las funciones no deberían tener efectos secundarios
Un efecto secundario ocurre cuando una función modifica cualquier estado fuera de su propio alcance. Los efectos secundarios pueden dificultar la prueba y el razonamiento sobre el comportamiento de la función y también pueden provocar un comportamiento inesperado. Las funciones deben operar solo con sus propios parámetros y variables locales y no deben modificar ningún estado fuera de su alcance.
// Example with side effects
let arr = [1, 2, 3];
function popLastElement() {
arr.pop(); // modifies the external state of `arr`
}
popLastElement();
console.log(arr); // Output: [1, 2]
// --------------------------------------------------------------
// Example without side effects
function getLastElement(arr) {
return arr[arr.length - 1]; // returns a new value without modifying the input
}
let arr = [1, 2, 3];
let lastElement = getLastElement(arr);
console.log(lastElement); // Output: 3
Las funciones no deben depender de variables globales
Las variables globales dificultan la comprensión y la prueba de las funciones y pueden provocar un comportamiento inesperado. Las funciones deben operar solo con sus propios parámetros y variables locales y no deben depender del estado global. Esto también facilita la reutilización de la función en diferentes contextos.
// Example relying on global state
let x = 0;
function increment() {
x++;
}
increment();
console.log(x); // Output: 1
// --------------------------------------------------------------
// Example without relying on global state
function increment(x) {
return x + 1;
}
let y = 0;
y = increment(y);
console.log(y); // Output: 1
Las funciones no deben estar demasiado anidadas
Las funciones que están profundamente anidadas pueden ser más difíciles de leer y comprender, además de dar lugar a estructuras de control complejas. Las funciones deben estructurarse de una manera que facilite la comprensión del flujo de control, sin tener que realizar un seguimiento mental de múltiples niveles de funciones anidadas.
// Example with deeply nested functions
function add(a, b) {
function increment(x) {
return x + 1;
}
let c = increment(a);
let d = increment(b);
return c + d;
}
console.log(add(1, 2)); // Output: 5
// --------------------------------------------------------------
// Example with flatter function structure
function increment(x) {
return x + 1;
}
function add(a, b) {
let c = increment(a);
let d = increment(b);
return c + d;
}
console.log(add(1, 2)); // Output: 5
Use excepciones, no códigos de error
Los códigos de error pueden dificultar el razonamiento sobre el código y pueden generar estructuras de control complejas. Las excepciones permiten un flujo de control más natural y un manejo de errores más sencillo. Las funciones deben generar excepciones para indicar errores o comportamientos inesperados, en lugar de devolver códigos o valores de error.
// Example with error code
function divide(a, b) {
if (b === 0) {
return -1; // error code for divide by zero
}
return a / b;
}
let result = divide(4, 0);
if (result === -1) {
console.log("Error: Divide by zero"); // error handling with error code
}
// --------------------------------------------------------------
// Example with exception
function divide(a, b) {
if (b === 0) {
throw new Error("Divide by zero"); // throws an exception
}
return a / b;
}
try {
let result = divide(4, 0);
} catch (e) {
console.log("Error: " + e.message); // error handling with exception
}
Conclusión
En conclusión, es importante seguir las mejores prácticas al escribir funciones para mejorar la calidad general de nuestra base de código. Al hacerlo, podemos asegurarnos de que nuestras funciones no solo sean legibles y reutilizables, sino también mantenibles a largo plazo. Esto puede ayudar a reducir la cantidad de fallas y errores que pueden surgir de un código mal escrito, lo que puede ahorrar tiempo y recursos a largo plazo.
Vale la pena señalar que el código limpio no se trata solo de escribir código que funcione; también se trata de escribir código que pueda entenderse, probarse y modificarse fácilmente con el tiempo. Por lo tanto, se recomienda tomarse el tiempo para considerar cuidadosamente las mejores prácticas descritas anteriormente al escribir funciones, para optimizar la calidad y la mantenibilidad de su código.

![¿Qué es una lista vinculada, de todos modos? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































