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

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

Почему важно называть правильно?

  • Читаемость: Хорошие имена делают ваш код интуитивно понятным и сокращают кривую обучения для других.

  • Поддерживаемость: Легче перестраивать или отлаживать хорошо названный код.

  • Сотрудничество: Ясные названия улучшают коммуникацию в команде и продуктивность.

  • Масштабируемость: Осмысленные имена помогают сделать крупные проекты управляемыми.

Различные стили соглашений о наименованиях

Различные стили соглашений о наименованиях являются ключевыми для улучшения читаемости кода и его поддерживаемости в различных языках программирования.

Стили, такие как camelCase, PascalCase, snake_case и kebab-case, разработаны для конкретных контекстов и практик.

camelCase широко используется для переменных и функций, в то время как PascalCase предпочтителен для классов. snake_case является популярным в Python из-за ясности, а kebab-case преобладает в CSS для стилизации элементов HTML.

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

Стиль Пример Обычное использование
camelCase userName Переменные, функции, свойства объектов
PascalCase UserName Классы, компоненты, конструкторы
kebab-case primary-button Классы CSS, идентификаторы HTML, имена файлов
snake_case user_name Переменные, названия функций в Python
SCREAMING_SNAKE_CASE MAX_CONNECTIONS Константы
dot.case config.file.path Конфигурации, ключи
Train-Case Primary-Button Заголовки редко используются
Венгерская нотация bIsActive Устаревший код
ЗАГЛАВНЫЕ БУКВЫ с пробелами ДЕТАЛИ УЧЕТНОЙ ЗАПИСИ ПОЛЬЗОВАТЕЛЯ Редкие, в основном для документации старого стиля
Плоский регистр имя_пользователя Минималистичный, имена файлов, идентификаторы

Как выбрать правильный стиль

  1. Специфично для языка: Следуйте соглашениям вашего языка программирования или фреймворка. Например:

    • JavaScript: camelCase для переменных и функций, PascalCase для компонентов.

    • Python: snake_case для переменных и функций.

    • CSS/HTML: kebab-case для имен классов и идентификаторов.

  2. Стандарты команды или проекта: Последовательность имеет значение. Используйте согласованный стиль для вашей команды/проекта.

  3. Специфика назначения: Используйте стили именования, которые лучше всего представляют именуемую сущность (например, константы в SCREAMING_SNAKE_CASE).

Общие рекомендации по именованию

Прежде чем переходить к конкретным соглашениям об именовании классов, переменных и функций, давайте рассмотрим некоторые универсальные принципы:

  1. Будьте описательными и краткими: Имена должны передавать назначение или роль переменной/функции и т.д.:

     // Плохо
     let x = 10;
    
     // Хорошо
     let maxUsersAllowed = 10;
    
  2. Избегайте криптических сокращений, которые могут быть сложными для других разработчиков (или даже для вашего будущего “я”):

     // Плохо
     let usrNm = "John";
    
     // Хорошо
     let userName = "John";
    
  3. Используйте последовательные соглашения об именовании: Выберите стиль именования (camelCase, PascalCase, kebab-case, snake_case) и придерживайтесь его на протяжении всего проекта.

  4. Избегайте зарезервированных ключевых слов или запутанных имен:

     // Плохо
     let let = 5;
    
     // Хорошо
     let имяПеременной = 5;
    

Хорошо, теперь, когда мы рассмотрели основы, давайте углубимся в некоторые полезные соглашения об именовании.

Как создать хорошие имена классов

Имена классов определяют визуальное или структурное поведение элементов в вашем приложении. Четкое написание имен классов обеспечивает легкость понимания и обслуживания вашего HTML и CSS.

1. Используйте описательные имена

Имена классов должны описывать назначение элемента, а не его внешний вид.

<!-- Плохо -->
<div class="red-button"></div>

<!-- Хорошо -->
<div class="primary-button"></div>

2. Следуйте методологии BEM (Блок-Элемент-Модификатор)

BEM — это популярное соглашение для написания масштабируемого и поддерживаемого CSS. Оно разделяет компоненты на:

  • Блок: Представляет компонент (например, карточка).

  • Элемент: Представляет дочерние элементы блока (например, карточка__заголовок).

  • Модификатор: Представляет вариации блока или элемента (например, карточка__заголовок--выделенный).

Пример:

<div class="card">
  <h1 class="card__title card__title--highlighted">Welcome</h1>
  <p class="card__description">This is a card component.</p>
</div>

3. Используйте kebab-case

Имена классов CSS традиционно пишутся в kebab-case для лучшей читаемости.

<!-- Плохо -->
<div class="primaryButton"></div>

<!-- Хорошо -->
<div class="primary-button"></div>

Как создавать хорошие имена переменных

Переменные содержат данные и должны иметь осмысленные имена, описывающие то, что они представляют.

1. Используйте существительные для переменных

Переменные обычно являются существительными, потому что они представляют сущности или данные.

// Плохо
let a = "John";

// Хорошо
let userName = "John";

2. Используйте префиксы для добавления контекста

Добавление префиксов помогает уточнить тип или назначение переменной:

  • Булевы: is, has, can

  • Числа: max, min, total

  • Массивы: Используйте множественное число (например, users, items).

Пример:

let isUserLoggedIn = true;
const maxUploadLimit = 5; // МБ
const usersList = ["John", "Jane"];

3. Избегайте Общих Имен

Избегайте имен типа data, value или item, если они необходимы.

// Плохо
let data = 42;

// Хорошо
let userAge = 42;

Как Создавать Хорошие Имена Функций

Функции выполняют действия, поэтому их имена должны отражать операцию или процесс, который они выполняют.

1. Используйте Глаголы для Функций

Функции ориентированы на действие, поэтому их имена должны начинаться с глагола:

// Плохо
function userData() {
  // ...
}

// Хорошо
function fetchUserData() {
  // ...
}

2. Будьте Конкретными в Описании Функциональности

Имена функций должны указывать на то, что они делают.

// Плохо
function handle() {
  // ...
}

// Хорошо
function handleFormSubmit() {
  // ...
}

3. Используйте префиксы для намерений

  • Для обработчиков событий: handle, on

  • Для утилит: calculate, convert, format

  • Для операций получения данных: fetch, get, load

  • Для установщиков и получателей: set, get

Пример:

function handleButtonClick() {
  console.log("Button clicked!");
}

function calculateDiscount(price, discountPercentage) {
  return price * (discountPercentage / 100);
}

Как определить, подходит ли имя для переменной, функции или класса

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

1. Представляет ли оно цель?

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

Как оценить:

Спросите себя: “Когда я читаю это имя, могу ли я сразу понять его цель?”

Пример:

  • userAge лучше, чем a, потому что userAge говорит вам, что представляет переменная, тогда как a слишком неопределенно.

2. Достаточно ли это специфично?

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

Как оценить:

Спросите: “Это имя специфично для того, что эта переменная, функция или класс представляет в моем приложении?”

Пример:

  • calculateTaxAmount() лучше, чем calculate(), потому что ясно, что функция рассчитывает.

3. Следует ли ему последовательной конвенции именования?

Последовательность в конвенциях именования имеет жизненно важное значение. Когда все члены команды следуют одним и тем же конвенциям, код становится легче понимать и навигировать.

Как оценить:

Спросите: “Соответствует ли это имя соглашениям об именовании, используемым в остальной части проекта?” Следуйте руководящим принципам проекта, таким как:

  • camelCase для переменных и функций (например, userAge)

  • PascalCase для классов (например, UserProfile)

  • UPPERCASE_SNAKE_CASE для констант (например, MAX_USERS)

Пример:

  • Если ваша команда использует camelCase, userData лучше, чем UserData.

4. Избегает ли это неоднозначности?

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

Как оценить:

Спросите: “Может ли кто-то, незнакомый с кодовой базой, неправильно интерпретировать, к чему относится это имя?”

Пример:

  • Вместо того чтобы называть булеву переменную isValid, используйте isUserLoggedIn или isEmailVerified, чтобы сделать яснее, что проверяется.

5. Легко ли это читать и произносить?

Хотя это не строго необходимо, удобство чтения и произношения может улучшить общую читаемость и поддерживаемость вашего кода.

Как оценить:

Спросите: “Легко ли читать это вслух, и могу ли я понять с первого взгляда?”

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

Пример:

  • maxRetries лучше, чем maximumNumberOfAttemptsToReconnect.

6. Избегает ли повторений?

Избегайте повторений в названиях. Не повторяйте информацию, которая уже подразумевается или описывается контекстом.

Как оценить:

Спросите: “Повторяю ли информацию, которая уже ясна из окружающего контекста?”

Пример:

  • Если у вас есть класс с названием User, то название метода userGetData() является избыточным. Вместо этого используйте getData().

7. Является ли самодокументирующимся?

Лучшие названия сами себя документируют. Хорошие названия уменьшают необходимость в дополнительных комментариях или объяснениях.

Как оценить:

Спросите: “Полностью ли это название описывает переменную, функцию или класс без необходимости комментария для объяснения его назначения?”

Пример:

  • calculateTotalPrice самоочевидно, поэтому нет необходимости в дополнительном комментарии вроде “Эта функция вычисляет общую стоимость после скидки.”

8. Контекстуально и актуально для домена?

Название должно соответствовать контексту вашего проекта и его домена. Например, соглашения об именах для веб-приложения могут отличаться от тех, что для мобильного приложения или модели машинного обучения.

Как оценить:

Спросите: “Соответствует ли это название домену и контексту моего проекта?”

Если вы работаете в конкретном домене (например, финансы, здравоохранение, игры), используйте термины, хорошо узнаваемые в этом домене.

Пример:

  • В игровом приложении healthPoints более подходящее, чем hp, так как отражает свой смысл.

9. Будет ли это актуально в будущем?

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

Как оценить:

Спросите: “Будет ли это название иметь смысл, если функциональность изменится или проект вырастет?”

Пример:

  • userInfo может устареть, если изменится структура данных. Лучше использовать userProfile, если ожидается добавление новых полей.

10. Избегает ли это магических чисел и захардкоженных значений?

Магические числа (числа с неясным значением) следует избегать в пользу именованных констант.

Как оценить:

Спросите: “Представляет ли это имя смысловую константу или это просто сырое число?”

Пример:

  • Вместо использования 1000 используйте константу, например, MAX_FILE_SIZE, чтобы объяснить значение числа.

Практические примеры

Пример CSS

Следующий пример CSS демонстрирует, как применять соглашения об именовании BEM (Block-Element-Modifier) для поддержания структурированной и масштабируемой иерархии классов в вашем таблице стилей:

<!-- HTML -->
<div class="navbar">
  <ul class="navbar__list">
    <li class="navbar__item navbar__item--active">Home</li>
    <li class="navbar__item">About</li>
    <li class="navbar__item">Contact</li>
  </ul>
</div>
/* CSS */
.navbar {
  background-color: #333;
  padding: 10px;
}

.navbar__list {
  list-style: none;
}

.navbar__item {
  display: inline-block;
  padding: 10px;
}

.navbar__item--active {
  color: orange;
}

Вот что происходит в этом коде:

  • Именование BEM: navbar является Блоком, представляющим основной навигационный компонент.

  • navbar__list является Элементом, дочерним элементом блока, представляющим список элементов навигации.

  • navbar__item – еще один Элемент, представляющий отдельные элементы списка.
  • navbar__item--active – это модификатор, используемый для выделения активного элемента меню.
    Такой подход облегчает понимание взаимосвязей и ролей внутри HTML и CSS, поддерживая модульные и многократно используемые стили.

Пример на JavaScript

Этот пример на JavaScript показывает, как использовать значимые и последовательные соглашения об именах для переменных и функций, чтобы сделать код самодокументируемым:

// Переменные
let isUserLoggedIn = false;
const maxAllowedItems = 10;

// Функции
function fetchUserDetails(userId) {
  // Получение данных пользователя из API
}

function calculateTotalPrice(cartItems) {
  return cartItems.reduce((total, item) => total + item.price, 0);
}

Вот что происходит в коде:

  • Переменные:

    • isUserLoggedIn: Булева переменная, названная так, чтобы четко указать ее назначение. Префикс is помогает определить ее как булеву.

    • maxAllowedItems: Константа с заглавным префиксом max, показывающая, что это ограничение, делая ее намерение ясным.

  • Функции:

    • fetchUserDetails(userId): Название отражает назначение функции, а именно извлечение деталей пользователя. Параметр userId описателен и избегает двусмысленности.

    • calculateTotalPrice(cartItems): Название функции явно указывает на выполняемое действие. Параметр cartItems контекстуально соответствует области электронной коммерции.

Почему это хорошо: Эти соглашения обеспечивают читаемость и интуитивность кода, снижая когнитивную нагрузку для других разработчиков, работающих над тем же проектом.

Вывод

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

Попробуйте следовать этим основным принципам:

  • Используйте описательные, краткие названия.

  • Соблюдайте последовательные соглашения, такие как BEM для имен классов и camelCase для переменных и функций.

  • Используйте префиксы для добавления контекста и ясности.

Эти и другие советы, о которых мы говорили здесь, сделают ваш код удовольствием для работы, будь то через несколько месяцев или при совместной работе в команде. Начните применять эти советы сегодня и наблюдайте, как качество вашего кода возрастает.