JavaScript Clean Code: руководство для начинающих разработчиков

от автора

Мы часто сталкиваемся с тем, что многочисленные ресурсы и руководства по JavaScript предлагают свой уникальный подход к кодированию. И хотя они дают ценные знания, порой они также могут создавать проблемы с пониманием кода из-за непоследовательных соглашений об именовании и неясных структур.

Это руководство посвящено написанию чистого и удобного кода на JavaScript и TypeScript. Мы рассмотрим лучшие практики работы с функциями, переменными и методами, чтобы ваш код был не только эффективным, но и понятным как вам, так и другим разработчикам. Статья будет полезна для новичков, которые хотят улучшить свои навыки кодирования.

Имена переменных

Одним из ключевых принципов написания чистого и удобного кода является использование осмысленных имен переменных и функций. Читаемость кода имеет решающее значение для командной работы и для дальнейшего обращения к вашему коду в будущем. Использование описательных имен, которые точно передают назначение и функциональность переменных и функций, является важным шагом к достижению этой цели.

Избегайте соблазна использовать однобуквенные имена переменных или загадочные сокращения, которые могут затруднить чтение и понимание вашего кода. При выборе имен для переменных всегда стремитесь к ясности и информативности.

Давайте рассмотрим эту концепцию на примере JavaScript и TypeScript:

// Плохой подход var c; var d; var cd; var u;  // Хороший подход let counter = 0; let date = null; let currentDate = null; let user = "";

Булевы (или логические) переменные

При работе с логическими переменными в JavaScript и TypeScript важно поддерживать ясность в коде. Вместо использования одиночных букв или неоднозначных слов, постарайтесь называть логические переменные в виде вопросов или утверждений, которые чётко передают их назначение. TypeScript добавляет к JavaScript мощный уровень статической типизации, что ещё больше повышает читаемость и поддерживаемость кода.

Вот пример того, как писать чистые и понятные логические переменные на TypeScript:

var v=false; var w=false; var c=false; var l=false;  // Наилучший подход в данном случае let isValid: boolean = false; let isWritable: boolean = false; let isCleared: boolean = false; let isLoading: boolean = false;

Числовые переменные

При работе с числовыми переменными в коде JavaScript и TypeScript важно использовать осмысленные и описательные имена переменных. Эта практика улучшает читаемость и сопровождение кода, облегчая вам и вашей команде понимание, почему назначены эти переменные. Вместо использования вызывающих вопросы имён, таких как bMax, bMin и bTot, выбирайте имена, которые чётко передают их смысл. Кроме того, используйте систему типов TypeScript для обеспечения типобезопасности — это помогает выявлять потенциальные ошибки на этапе разработки.

Ниже улучшенный пример на TypeScript:

var bMax=false; var bMin=false; var bTot=false;  // Наилучший подход в данном случае let booksMaximum: number = 50; let booksMinimum: number = 1; let booksTotal: number = 51;

Имена массивов 

При работе с массивами или списками в JavaScript и TypeScript также важно выбирать осмысленные и описательные имена для ваших переменных. Используйте стиль написания camelCase для наименования и давайте понятные имена, которые указывают на назначение массива. Вот как можно улучшить код:

// Плохой подход к именованию и отсутствие информации о типе var f = ["Mango", "Papaya", "Apple", "Banana"]; var c = ["Mazda", "Toyota", "Nissan", "Ford"]; var m = ["Fish", "Pork", "Beef", "Chicken"];  // Наилучший подход к случае массивов или списков  let fruits: string[] = ["Mango", "Papaya", "Apple", "Banana"]; let carBrands: string[] = ["Mazda", "Toyota", "Nissan", "Ford"]; let meatsType: string[] = ["Fish", "Pork", "Beef", "Chicken"];

Функции должны быть короткими и целенаправленными 

Один из основных принципов написания чистого и поддерживаемого кода на JavaScript и TypeScript заключается в том, чтобы ваши функции были лаконичными и сосредоточенными на одной задаче. Для этого разбивайте большие функции на более мелкие, модульные компоненты, каждая из которых выполняет одну чётко определённую задачу. Такой подход улучшает модульность кода, облегчая его тестирование и поддержку.

Рассмотрим пример, демонстрирующий, как преобразовать функцию JavaScript в TypeScript, следуя принципу «коротких и целенаправленных» функций.

До рефакторинга (JavaScript):

function calculateOrderTotal(order) {   let total = 0;   for (const item of order.items) {     total += item.price * item.quantity;   }    if (order.promoCode) {     total -= total * 0.1;   }    if (total > 1000) {     total -= 100;   }    return total; }

После рефакторинга (TypeScript):

interface Order {   items: Array<{ price: number; quantity: number }>;   promoCode?: string; }  function calculateOrderTotal(order: Order): number {   const subtotal = calculateSubtotal(order.items);   const discountedTotal = applyPromoCode(subtotal, order.promoCode);   return applyDiscountIfApplicable(discountedTotal); }  function calculateSubtotal(items: Array<{ price: number; quantity: number }>): number {   return items.reduce((acc, item) => acc + item.price * item.quantity, 0); }  function applyPromoCode(subtotal: number, promoCode?: string): number {   if (promoCode) {     return subtotal - subtotal * 0.1;   }   return subtotal; }  function applyDiscountIfApplicable(total: number): number {   if (total > 1000) {     return total - 100;   }   return total; }

Не забывайте комментировать код

Использование комментариев для объяснения смысла кода — важная практика поддержания чистого и понятного кода. Комментарии в правильных местах могут внести ясность как для вас, так и для других разработчиков, которые будут работать с вашим кодом в будущем. Комментарии должны описывать цель кода, его ожидаемое поведение и любую значимую информацию, которая может быть не очевидна из самого кода.

Вот пример на TypeScript, иллюстрирующий использование комментариев:

// Определение пользовательского типа для структуры объектов массива type MyObject = {   id: number;   name: string; };  /**  * Сортируеем массив MyObject по свойству 'id' в порядке возрастания.  *  * @param array - Массив, который необходимо отсортировать.  * @returns Новый массив с объектами, отсортированными по 'id'.  */ function sortObjectsById(array: MyObject[]): MyObject[] {   return array.slice().sort((a, b) => a.id - b.id); }  const arrDevelopers = [   { id: 3, name: "Jorgel", language: "PHP" },   { id: 0, name: "Eleazar", language: "Python" },   { id: 1, name: "Hector", language: "Java" },   { id: 2, name: "Alvison", language: "Golang" },   { id: 4, name: "Bill", language: "JavaScript" }, ];  sortObjectsById(arrDevelopers)

Используйте пробелы

Правильное использование разрывов строк, отступов и пустых строк улучшает читаемость и делает его более визуально приятным. Сгруппируйте связанные строки кода вместе и отделите их от других блоков кода с помощью пустых строк. Давайте рассмотрим пример на языке TypeScript:

function calculateTotalPrice(items: Item[]): number {     let totalPrice = 0;      for (const item of items) {         totalPrice += item.price * item.quantity;     }      return totalPrice; }  class Item {     constructor(public name: string, public price: number, public quantity: number) {} }  const shoppingCart: Item[] = [     new Item("Laptop", 1000, 2),     new Item("Mouse", 30, 3),     new Item("Keyboard", 50, 1), ];  const total = calculateTotalPrice(shoppingCart);  console.log(`Total price: $${total}`);

Избегайте использования вложенных условных операторов

Используйте шаблоны раннего возврата или защитные условия (guard clauses), для улучшения читаемости кода и снижения его сложности. Вместо множества вложенных операторов if-else создавайте функции или методы, которые возвращают результат, как только выполняется условие. Такой подход улучшает организацию кода и упрощает его понимание для разработчиков.

Вот пример на TypeScript, демонстрирующий использование ранних возвратов:

function calculatePrice(quantity: number, price: number, discountApplied: boolean): number {     if (quantity <= 0) {         return 0; // Защитное условие для обработки невалидного ввода     }      let total = quantity * price;      if (discountApplied) {         total *= 0.9; // Применение скидки 10%      }      return total; }

Избегайте глобальных переменных 

Один из ключевых принципов написания чистого и поддерживаемого кода на JavaScript и TypeScript — это уменьшение использования глобальных переменных. Злоупотребление глобальными переменными может привести к таким нежелательным последствиям, как конфликты имён, непредвиденные побочные эффекты и усложнение кода. Чтобы избежать этих проблем, используйте замыкания или модульные паттерны для инкапсуляции кода и предотвращения загрязнения глобального пространства имён.

Вот пример, демонстрирующий, как избежать глобальных переменных, инкапсулируя функциональность в модуле TypeScript:

// Вместо глобальных переменных инкапсулируйте свой код в модуль namespace MyModule {   // Приватная переменная, доступная только в пределах модуля   let counter = 0;    // Публичная функция для взаимодействия с модулем   export function incrementCounter(): void {     counter++;   }    // Публичная функция для получения значения счетчика   export function getCounterValue(): number {     return counter;   } }  // Использование функций модуля MyModule.incrementCounter(); console.log(MyModule.getCounterValue()); // Вывод: 1

Используйте const и let вместо var 

При объявлении переменных в JavaScript или TypeScript лучше всего использовать const и let, а не var. Этот выбор улучшает читаемость кода, обеспечивает блочную структуру и снижает риск случайного переназначения переменных. Использование const для значений, которые не будут меняться, и let для переменных, которые нужно переназначить, поможет создавать более чистый и предсказуемый код. Вот пример на языке TypeScript:

// Использование const для констант const pi = 3.14; const appName = "MyApp";  // Использование let для переменных let counter = 0; let username = "JohnDoe";  // Попытка переназначить константу приведет к ошибке компиляции // pi = 3.14159; // Error: Cannot assign to 'pi' because it is a constant.  // Переназначение переменной вполне допустимо counter = 1; username = "JaneDoe";

Используйте шаблонные строки

Одной из важных практик написания чистого и поддерживаемого кода в JavaScript и TypeScript является использование шаблонных строк для интерполяции строк. Шаблонные строки обеспечивают краткий и удобный способ встраивания переменных и выражений в строки, избавляя от необходимости конкатенации или сложных манипуляций со строками. Шаблонные строки заключаются в обратные кавычки и могут содержать заполнители для переменных или выражений, заключенных в «${}»

Вот пример на EcmaScript:

// Определение имени и фамилии const firstName = "John"; const lastName = "Doe";  // Создание полного имени с использованием шаблонного литерала const fullName = `My name is ${firstName} ${lastName}.`;  // Вывод полного имени в консоль console.log(fullName);

Используйте стрелочные функции

При работе с простыми функциями обратного вызова (коллбэками) в JavaScript и TypeScript рекомендуется использовать стрелочные функции. Стрелочные функции предоставляют более лаконичный и удобочитаемый синтаксис по сравнению с традиционными функциональными выражениями. Они автоматически привязываются к окружающему контексту, что помогает уменьшить многословие кода. Вот пример на TypeScript, иллюстрирующий это:

// Традиционное функциональное выражение const add = function (a: number, b: number): number {   return a + b; };  // Стрелочная функция для той же задачи const add = (a: number, b: number): number => a + b;

Используйте деструктуризацию объектов

В JavaScript и TypeScript чистота и поддерживаемость кода во многом зависят от деструктуризации объектов. Этот приём упрощает доступ к свойствам, улучшает читаемость кода и снижает его избыточность, особенно при работе с вложенными объектами. Вместо индивидуального обращения к каждому свойству, деструктуризация позволяет извлекать необходимые свойства, что способствует более чистому и интуитивно понятному коду.

Пример на TypeScript, иллюстрирующий эту концепцию:

// Пример пользовательского объекта const user = {   id: 1,   name: 'John Doe',   email: 'john@example.com',   address: {     street: '123 Main St',     city: 'Anytown',     zipCode: '12345',   }, };  // Без деструктуризации const userName = user.name; const userCity = user.address.city;  // С деструктуризацией const { name, address: { city } } = user;  console.log(`User Name: ${name}`); console.log(`User City: ${city}`);

Имена функций 

При наименовании функций в JavaScript и TypeScript используйте понятные комбинации глагол-существительное, чтобы эффективно передать их назначение, делая код более понятным для разработчиков. Например, если у вас есть функция, которая вычисляет общую стоимость товаров в корзине, хорошее название для такой функции может быть calculateTotalPrice:

function calculateTotalPrice(items: Item[]): number {   // Логика расчета общей цены }

Бонус: оптимизируйте свой код, используя режим EcmaScript и стрелочные функции. Вот несколько примеров:

const paymentUpdatedMessage = 'Payment has been updated!'; function payment(){ console.log(paymentUpdatedMessage); }   // Лучший подход при использовании обычного JS и ES6 function updatePayment(){ console.log(paymentUpdatedMessage); }  // Лучший подход с использованием EcmaScript const updatePayment = () => console.log(paymentUpdatedMessage); }

Заключение

В этом руководстве по JavaScript и TypeScript мы рассмотрели лучшие практики для того, чтобы ваш код оставался эффективным, масштабируемым и подходящим для командной работы. Постоянное применение таких принципов, как DRY, KISS, SOLID, а также фокус на осмысленных названиях и документации повысят качество вашего кода и сэкономит время, делая вас ценным членом команды.


Всех тех, кто использует или планирует использовать JavaScript для написания автотестов, приглашаем на открытый урок, посвященный оптимизации автоматизации тестирования с применением Page Object в JavaScript.

На этом занятии мы погрузимся в мир Page Object и рассмотрим, как эта популярная практика может значительно улучшить процесс автоматизации тестирования в JavaScript. Мы изучим основные концепции Page Object, принципы его использования, а также рассмотрим методы оптимизации автоматизированных тестов с помощью Page Object.

Записаться на урок можно по ссылке.


ссылка на оригинал статьи https://habr.com/ru/articles/841866/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *