Чистый код: функции (на Javascript)
Вы устали бороться со сложными, трудными для понимания функциями в кодовой базе? Вы хотите писать функции, которые легче поддерживать, повторно использовать и менее подвержены ошибкам? Если да, то вам нужно узнать о «Чистом коде: Функции». Следуя рекомендациям, изложенным в книге Роберта С. Мартина «Чистый код», вы сможете научиться писать функции, которые легче читать, тестировать и поддерживать. В этом сообщении блога мы рассмотрим ключевые концепции функций чистого кода и предоставим вам практические советы и примеры, которые помогут вам реализовать эти концепции в вашем собственном коде. С нашей помощью вы сможете поднять свои навыки кодирования на новый уровень и писать функции, с которыми приятно работать. Итак, вы готовы узнать о функциях чистого кода? Давайте погрузимся!
Содержание
· Маленькие функции лучше больших
· Функции должны делать одно дело
· Функции должны иметь описательные имена
· Функции должны иметь ограниченное количество аргументов
· Функции не должны иметь побочных эффектов
· Функции не должны полагаться на глобальные переменные
· Функции не должны быть слишком Глубокая вложенность
· Используйте исключения, а не коды ошибок
· Заключение
Маленькие функции лучше, чем большие
Маленькие функции легче читать и понимать, потому что они обычно делают одну вещь и имеют четкую цель. Это также упрощает их тестирование и поддержку, поскольку требуется меньше кода для просмотра или изменения. С другой стороны, большие функции могут быть более сложными и трудными для понимания, что может привести к ошибкам.
// 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;
}
Функция getTotalPrice()берет массив ордеров и возвращает их общую цену, используя функцию reduce()для суммирования цены каждого ордера. Функция getOrderIds()принимает массив заказов и возвращает массив их идентификаторов с помощью map()функции. Функция getOrderCount()принимает массив заказов и возвращает их количество, используя свойство length. Наконец, generateOrderSummary()функция принимает массив заказов и использует три меньшие функции для создания итоговой строки. Функция logOrderSummary()принимает массив заказов и выводит сводную строку на консоль.
Функции должны делать одну вещь
Каждая функция должна иметь четкую и четкую цель. Когда функция выполняет несколько функций, ее становится сложнее понять, протестировать и поддерживать. Разбивая большую задачу на более мелкие функции, мы можем создавать более читаемый и удобный для сопровождения код.
// 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);
}
Функция splitInput()принимает строку и использует split()метод, чтобы разбить ее на массив строк. Функция trimLines()принимает массив строк и использует map()метод для удаления всех пробелов в начале и в конце каждой строки. Функция removeEmptyLines()принимает массив строк и использует filter()метод для удаления любых пустых строк. Функция formatLines()принимает массив строк и использует map()метод для добавления >символа в начало каждой строки. Функция joinLines()принимает массив строк и использует join()метод для их объединения в одну строку, разделенную символами новой строки. Наконец, processUserInput()функция использует меньшие функции для обработки входной строки.
Функции должны иметь описательные имена
Имена функций должны точно описывать то, что делает функция, и должны быть простыми для понимания без необходимости читать реализацию функции. Описательное имя функции может помочь сделать код более понятным и уменьшить потребность в комментариях.
// Function with a vague name
function processData(data) {
// ...
}
// --------------------------------------------------------------
// Refactored with a descriptive name
function processUserData(userData) {
// ...
}
Функции должны иметь ограниченное количество аргументов
Функции, которые принимают большое количество аргументов, сложнее использовать, понимать и тестировать. Старайтесь, чтобы число аргументов не превышало трех или четырех, если это возможно. Один из способов уменьшить количество аргументов — передать их как один объект или структуру данных.
// 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);
Функции не должны иметь побочных эффектов
Побочный эффект возникает, когда функция изменяет любое состояние за пределами своей области. Побочные эффекты могут затруднить тестирование и анализ поведения функции, а также могут привести к неожиданному поведению. Функции должны работать только со своими собственными параметрами и локальными переменными и не должны изменять какое-либо состояние за пределами своей области.
// 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
Функции не должны полагаться на глобальные переменные
Глобальные переменные усложняют понимание и тестирование функций и могут привести к неожиданному поведению. Функции должны работать только со своими собственными параметрами и локальными переменными и не должны полагаться на глобальное состояние. Это также упрощает повторное использование функции в различных контекстах.
// 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
Функции не должны быть слишком глубоко вложены
Глубоко вложенные функции могут быть труднее читать и понимать, а также приводить к сложным структурам управления. Функции должны быть структурированы таким образом, чтобы упростить понимание потока управления без необходимости мысленно отслеживать несколько уровней вложенных функций.
// 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
Используйте исключения, а не коды ошибок
Коды ошибок могут затруднить понимание кода и привести к сложным структурам управления. Исключения обеспечивают более естественный поток управления и упрощают обработку ошибок. Функции должны генерировать исключения, чтобы указать на ошибки или неожиданное поведение, а не возвращать коды ошибок или значения.
// 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
}
Заключение
В заключение, важно следовать рекомендациям при написании функций, чтобы улучшить общее качество нашей кодовой базы. Поступая таким образом, мы можем гарантировать, что наши функции будут не только читаемыми и пригодными для повторного использования, но и поддерживаемыми в долгосрочной перспективе. Это может помочь уменьшить количество багов и ошибок, которые могут возникнуть из-за плохо написанного кода, что может сэкономить время и ресурсы в долгосрочной перспективе.
Стоит отметить, что чистый код — это не только написание работающего кода; речь также идет о написании кода, который можно легко понять, протестировать и модифицировать с течением времени. Поэтому рекомендуется уделить время тщательному рассмотрению изложенных выше передовых практик при написании функций, чтобы оптимизировать качество и удобство сопровождения вашего кода.

![В любом случае, что такое связанный список? [Часть 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































