Введение

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

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

Переменные и функции

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

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

Разберем по частям

Переменные

Разделим названия переменных на три части: 

  • Предмет 

  • Признак Предмета

  • Атрибут Предмета

Предмет — основная сущность, к которой относится переменная.

Признак Предмета — это характеристика, которая отличает данный Предмет от других объектов того же типа.

Атрибут Предмета — это составляющая или часть предмета.

Последовательность этих частей всегда следующая:

Признак Предмета > Предмет > Атрибут Предмета 

Примеры: 

Имя переменной

Признак

Предмет

Атрибут

user

user

Пользователь

activeUser

active

user

Активный пользователь

userId

user

Id

Id пользователя

activeUserId

active

user

Id

Id активного пользователя

Функции

Разделим названия функций на три части:

  • Действие 

  • Предмет (полный)

  • Контекст Действия

Действие — это обязательная часть названия функции, которая указывает на то, что именно эта функция делает.

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

Контекст Действия — это опциональная часть названия функции, которая уточняет дополнительные условия или характеристики выполнения действия.

Последовательность этих частей всегда следующая:

Действие > Предмет (полный) > Контекст Действия

Почему последовательность именно такая?

Действие в начале названия сразу дает понять, что это функция, а не переменная.

Такой порядок облегчает восприятие, так как код читается в логической последовательности: Что делать? > С чем? > В каком контексте? 

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

Примеры:

Имя функции

Действие

Предмет (полный)

Контекст действия

getUser

get

User

Получи пользователя

getActiveUser

get

ActiveUser

Получи активного пользователя

getUserName

get

UserName

Получи имя пользователя

getActiveUserName

get

ActiveUserName

Получи имя активного пользователя

getUserById

get

User

ById

Получи пользователя по Id

getActiveUserById

get

ActiveUser

ById

Получи активного пользователя по Id

getUserNameById

get

UserName

ById

Получи имя пользователя по Id

getActiveUserNameById

get

ActiveUserName

ById

Получи имя активного пользователя по Id

Части речи

Предмет

Предмет — это существительное, во множественном или единственном числе.

Признак Предмета

Признак Предмета может быть выражен прилагательным или причастием.

Примеры:

Имя переменной

Признак Предмета

activeUser

active

Активный пользователь

pendingOrder

pending

Находящийся в обработке заказ

premiumProduct

premium

Премиальный товар

Атрибут Предмета

Атрибут Предмета может быть выражен через существительное или комбинацию нескольких существительных.

Примеры:

Имя переменной

Атрибут Предмета

orderDeliveryDate

Date

Дата доставки заказа

userProfilePicture

Picture

Изображения профиля пользователя

paymentTransactionId

Id

Id транзакции определенного платежа

Действие

Действие — это глагол в повелительном наклонении.

Поместить глагол в форму повелительного наклонения в английском языке очень легко. Нужно просто взять инфинитив (его базовую форм) без частицы to. 

Примеры:

  • Go! (Иди!)

  • Stop! (Остановись!)

  • Read! (Читай!)

Запомнить, что глагол должен быть в повелительном наклонении можно проведя вот такую аналогию.

class Spellbook {
    // Описание заклинания: откройЗамокПоАйди!
    openLockById(id) {
        console.log(`Произношу заклинание для замка с id: ${id}`);
        console.log(`Замок с Id: ${id} распахивается с щелчком!`);
    }

    // Описание заклинания: киньФаерболлПоXYZ!
    throwFireballByXYZ(x, y, z) {
        console.log(`Собираю энергию для огненного шара...`);
        console.log(`Огненный шар летит к координатам (${x}, ${y}, ${z}), сжигая всё на своём пути!`);
    }
}

const spellbook = new Spellbook();
// Вызовы заклинаний
spellbook.openLockById(7); // откройЗамокПоАйди 7
spellbook.throwFireballByXYZ(10, 20, 30); // киньФаерболлПоXYZ  10 20 30

В то время как на самом деле вы пишете что-то вроде такого.

class BoardManager {
    // Описание функции: откройДоступКДокументуПоАйди!
    unlockDocumentAccessById(id) {
        console.log(`Ищу документ с id: ${id}`);
        console.log(`Документ с id: ${id} в публичном доступе.`);
    }

    // Описание функции: отправьУведомлениеПоГеолокации!
    sendNotificationByLocation(latitude, longitude) {
        console.log(`Ищу пользователей в геолокации (${latitude}, ${longitude})...`);
        console.log(`Отправляю уведомление всем пользователям на координатах (${latitude}, ${longitude})!`);
    }
}

const boardManager = new BoardManager();
// Вызовы функций
boardManager.unlockDocumentAccessById(7); // откройДоступКДокументуПоАйди 7
boardManager.sendNotificationByLocation(55.7558, 37.6173); // отправьУведомлениеПоГеолокации 55.7558, 37.6173

Контекст Действия

Контекст Действия может быть выражен двумя основными способами: сочетанием существительного с предлогом или условным выражением.

Существительное с предлогом

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

Примеры:

Имя функции

Контекст Действия

fetchDataByDateRange

ByDateRange

Данные запрашиваются в пределах указанного диапазона дат.

sendNotificationForUser

ForUser

Уведомление отправляется для определенного пользователя. 

calculateTaxOnAmount

OnAmount

Налог рассчитывается на определенную сумму.

Условное выражение

Условное выражение в контексте действия описывает условия или проверки, при которых действие будет выполнено. 

Примеры:

Имя функции

Контекст Действия

restartServiceIfInactive

IfInactive

Сервис перезапускается только если он неактивен.

clearCacheWhenExpired

WhenExpired

Кэш очищается, когда он устарел.

lockAccountOnFailure

OnFailure

Аккаунт блокируется при неудачной попытке входа.

Исключения

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

  • Односимвольные переменные

  • Промежуточные вычисления

  • Флаги

  • Замыкания и функции обратного вызова

  • Абстрактные концепции

  • Интерфейсы или API-интеграции

  • Стандартные методы и свойства

  • Хуки

Но это уже совсем другая история, поэтому обсудим это более подробно в следующий раз.

Заключение

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

Комментарии (14)


  1. big17
    25.09.2024 10:30
    +1

    Отличная статься, все четко структурировано! Часто именно такого структурирования не хватает новичкам, которые вообще не заморачиваются с корректными наименованиями.


  1. Meth_0d
    25.09.2024 10:30
    +1

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


  1. Sasa987
    25.09.2024 10:30

    Спасибо. Было полезно прочитать.


  1. ayran
    25.09.2024 10:30

    Небесполезно. Годная статья.


  1. jbourne
    25.09.2024 10:30

    Структурно описали :)

    Про нейминг файлов напишите?

    Там есть интересные проблемы: признак ставить как префикс (regular-user.js, хорошо для стиля, нативно) или суффикс (user-regular.js, хорошо для сортировки и групировки вокруг сущности user), структуру папки-файлы, если у меня UserService , то его ложить в структуру юзера или сервисов, ... ?


    1. uknowlina Автор
      25.09.2024 10:30

      Нейминг файлов это супер большая тема для обсуждения, руки чешутся до него тоже добраться :))


  1. supercat1337
    25.09.2024 10:30

    А как относитесь к использованию "типа предмета"? Например, много переменных, но одни из них являются DOM элементами, причем различного класса. Следует ли их выделять из массы? Или константы.


    1. uknowlina Автор
      25.09.2024 10:30

      Интересный вопрос. Вы имеете в виду работу с DOM в контексте нативного JS?
      Я думаю, что в таком случае, "тип предмета" может быть ассоциирован с "признаком предмета", поскольку "тип" это именно тот "признак" по которому вы хотите отделить определенные переменные от других. Например, DOMuserNameInput, DOMsubmitButton.

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

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

      А атрибуты, напротив, от более частного к более общему.

      Например: DOMactiveUserNameInput

      • Предмет -- User

      • Признаки: DOM, active. DOM более общее понятие, чем active, поэтому идет в начале.

      • Атрибуты: Name, Input. Input более общее понятие, чем name, поэтому идет в конце.


      1. supercat1337
        25.09.2024 10:30

        Да, имею в виду нативный JS. Например, есть элемент select, есть textarea, есть button и так далее. В коде, честно скажу, переменная, имеющая ссылку на элемент, прямо просится назваться так, чтобы было понятно, чем она является.

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

        Например, logoutButton, usersAddModal_createButton, usersEditModal_cancelButton, usersAddModal_userNameInput. Если скоуп небольшой, то можно отбрасывать общие сущности типа usersAddModal, оставлять только createButton.


        1. uknowlina Автор
          25.09.2024 10:30
          +1

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


    1. uknowlina Автор
      25.09.2024 10:30

      Насчет констант, обычно название констант пишется в UPPER_SNAKE_CASE, то есть uppercase + snake_case, поэтому в названии константы обозначать, что эта переменная -- константа, нет необходимости.


  1. broderix
    25.09.2024 10:30

    Никто не сказал про ID vs Id ? У самого не хватает аргументов как правильно. getUserId вроде нормально выглядит


    1. supercat1337
      25.09.2024 10:30
      +1

      Чистая вкусовщина по поводу того, как использовать аббревиатуры и сокращения в названиях функций/переменных. В DOM спокойно используются аббревиатуры заглавными буквами, например, innerHTML, insertAdjacentHTML, HTMLElement, DOMContentLoaded. Но мне не нравится когда названия сущностей сливаются.

      Нужен какой-то визуальный разделитель, например, название сущности начинать с заглавной (если она не первая), а остальные строчными. То есть я за вариант getUserId и против getUserID.


    1. kyzyldur
      25.09.2024 10:30
      +1

      Кмк, в ID нет смысла - это не аббревиатура, а просто сокращение. Пользуюсь всегда Id.

      Более того, даже аббревиатуры пишу в camel style: Snils, Xml и т.п. На мой взгляд приятнее смотрится )))