Skip to content
Назад к блогу
Руководства

camelCase vs snake_case vs kebab-case — соглашения именования 2026

camelCase vs snake_case vs kebab-case 2026 — 6 стилей case, матрица решений для 7 языков, правила акронимов, URL SEO и 6 ловушек конвертации.

14 мин чтения

camelCase vs snake_case vs kebab-case: гид 2026 по соглашениям именования

userID или userId? user_profile или userProfile? URL через - или через _? Эти мелкие вопросы по пять раз на дню срывают PR-ревью с курса. Ответ — не «личные предпочтения»: у каждого популярного языка и у каждого веб-стандарта есть устоявшееся правило, и как только все они оказываются на одной странице, шум исчезает до нуля.

В этом гиде разбираются шесть стилей case, с которыми вы реально встретитесь в коде (camelCase, PascalCase, snake_case, kebab-case, CONSTANT_CASE, dot.case / path/case / Header-Case), матрица решений для семи языков, спор parseUrl против parseURL с реальными данными GitHub, SEO-аргументы в пользу kebab-case в URL и шесть ловушек, которые подстерегают при автоматической конвертации между case. Если хочется увидеть все 15 вариантов case для любой строки сразу, Конвертер регистра формирует их вживую в браузере.

Шесть стилей case на одной странице

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

Стиль caseПримерТипичное применениеПроисхождение / популяризатор
camelCaseuserProfileImageПеременные и методы JS, TS, Java, SwiftSmalltalk → Java
PascalCaseUserProfileImageКлассы, компоненты React/Vue, типы TSЯзык Pascal
snake_caseuser_profile_imagePython, Ruby, Rust, столбцы SQLC / ранний Unix
kebab-caseuser-profile-imageCSS-классы, URL-слаги, HTML-атрибутыLisp / современный веб
CONSTANT_CASEUSER_PROFILE_IMAGEEnv-переменные, верхнеуровневые константы, макросыМакросы C / Unix env
dot.caseuser.profile.imageJava-пакеты, пути MongoDB, ключи TOMLСоглашение неймспейсов
path/caseuser/profile/imageURL-пути, файловая система, ref-ы GitUnix-пути
Header-CaseUser-Profile-ImageИмена заголовков HTTP/1.1 (каноничные)RFC 2616

Восемь строк на шесть «настоящих» стилей: dot.case, path/case и Header-Case разделяют один и тот же токенизатор с разными разделителями, поэтому большинство библиотек работы с case считают их одним семейством.

Каждый стиль подробнее

camelCase: дефолт JS/Java

camelCase придумали в Smalltalk, но именно Java вывел его в индустриальный мейнстрим. Правила оформления кода Java от Sun образца 1995 года сделали firstName, getUserProfile и xmlParser стандартом, и каждый язык, который хотел выглядеть «как Java» — JavaScript, ActionScript, Swift, Kotlin, Dart — унаследовал ту же форму.

Правило: первое слово полностью строчное, каждое последующее — с заглавной буквы, разделители полностью убираются. Никаких подчёркиваний, никаких дефисов, никаких пробелов. Само название «camelCase» отсылает к горбатому силуэту заглавных букв, торчащих над морем строчных.

Два пограничных случая, которые часто путают: бренды со строчной буквы (iPhone, eBay, iOS) — когда такое название появляется в коде, не нужно силой капитализировать i; пишите так, как пишет сам бренд, и смиритесь с чуть-чуть странно выглядящим идентификатором. И акронимы — о них подробно ниже.

PascalCase: классы и компоненты

PascalCase — это просто camelCase с заглавной первой буквой. Некоторые гайды поэтому так и называют его — «UpperCamelCase». Язык Pascal использовал такую запись в 1970-х, и название закрепилось.

Где живёт: имена классов в любом C-семейственном ОО-языке (Java, C#, C++, Kotlin, Swift, TypeScript), имена компонентов React/Vue/Angular, алиасы типов и интерфейсы TypeScript (type UserProfile, interface AuthState), а также имена модулей и файлов в части экосистем (UserService.cs в C#).

Зачем вообще отдельный case для классов? Это чисто визуальный сигнал. Когда читаешь new userProfile() против new UserProfile(), вторая запись сразу читается как тип, а первая — как сорвавшийся вызов функции. Языки, в которых неймспейсы значений и типов перемешаны, опираются именно на регистр для разрешения неоднозначности.

snake_case: Python, Ruby, Rust, SQL

snake_case старше, чем кажется большинству: C и ранний Unix использовали имена в духе errno_h и fopen_s, потому что клавиатуры терминалов PDP-11 делали подчёркивание лёгким, а капитализацию в стиле Pascal — неудобной. Python принял его как официальную конвенцию PEP 8, сообщество Ruby сошлось на нём органически, а Rust сделал его дефолтом на уровне компилятора с линтом, который жалуется, если переменная названа userId, а не user_id.

Правило: всё в нижнем регистре, слова склеиваются подчёркиваниями. user_profile_image, parse_html, max_retries.

Аспект баз данных тут важен и обычно пропускается в туториалах по языкам. Почти каждый SQL ORM — SQLAlchemy, Hibernate, Sequelize, TypeORM, Active Record — по умолчанию использует имена столбцов в snake_case вне зависимости от соглашения языка-хоста. Причина — переносимость: PostgreSQL приводит неэкранированные идентификаторы к нижнему регистру, MySQL на Linux чувствителен к регистру, MySQL на macOS/Windows — нечувствителен, а SQLite относится к именам столбцов как к непрозрачным строкам. snake_case — единственное написание, которое переживает всё это без кавычек.

kebab-case: выбор веба

Веб сошёлся на kebab-case для всего, что видит пользователь: имена CSS-классов (.user-profile-image), URL-слаги (/blog/naming-conventions-guide), пользовательские HTML-атрибуты (data-user-id), имена тегов Web Components (<user-card> — спецификация буквально требует наличия дефиса).

Само название встречается в старых документах примерно в восьми вариантах — «dash-case», «spinal-case», «lisp-case», «skewer-case», «hyphen-case». Все означают одно и то же. Прижилось именно «kebab-case» — из-за старой шутки на Stack Overflow о том, что слова в нём похожи на куски мяса на шампуре.

Одно неочевидное правило: имена HTML- и CSS-классов на практике нечувствительны к регистру, но каноничное написание — строчное. .User-Profile работает в большинстве браузеров, но ломает серверный тулинг, который считает хеш имён классов, и сбивает с толку код-ревьюеров. Держитесь строчных букв.

CONSTANT_CASE: env-переменные и макросы

CONSTANT_CASE (иногда — SCREAMING_SNAKE_CASE в кругу Rust) — универсальный сигнал «это значение не меняется в рантайме». MAX_RETRIES, API_KEY, DEFAULT_TIMEOUT_MS. У каждого языка есть соглашение для этого, и каждый CI, каждый container runtime и каждый shell ожидают переменные окружения именно в таком виде (DATABASE_URL, NODE_ENV, PATH).

Ловушка: ключевое слово const в JavaScript не значит «используй CONSTANT_CASE». const result = await fetch(url) — абсолютно правильный camelCase. Резервируйте CONSTANT_CASE для настоящих семантических констант — значений, которые в C объявили бы через #define, тех, где смена значения в рантайме была бы багом. MAX_RETRIES = 3 подходит. result — нет.

dot.case, path/case, Header-Case

Три родственника, у которых общий токенизатор, но разные разделители.

dot.case представляет иерархические ключи: пакеты Java (com.example.service), пути полей MongoDB (user.profile.image), ключи конфигурации TOML/INI ([database.primary]), Lodash-пути для методов (_.get(obj, 'user.profile.image')). Читая dot.case-строку, вы должны видеть «неймспейс, неймспейс, лист».

path/case представляет буквальные местоположения: URL-пути, пути в файловой системе, ref-ы Git (feature/add-auth). Выбор «точки против слешей» осмыслен — слеши сигнализируют «это что-то реальное где-то лежит», точки сигнализируют «это просто метка».

Header-Case — соглашение HTTP/1.1: Content-Type, Access-Control-Allow-Origin, X-Forwarded-For. Заголовки HTTP/1.1 формально нечувствительны к регистру (RFC 2616), и content-type сработает, но все фреймворки, вся документация и все разработчики ожидают написание в Header-Case. HTTP/2 и HTTP/3 это изменили: RFC 7540 §8.1.2 предписывает строчные имена заголовков на проводе для упрощения сжатия заголовков (HPACK). На практике это невидимо для кода приложения, потому что каждый HTTP/2-клиент и сервер сами нормализуют, но если когда-нибудь смотреть на сырой HTTP/2-фрейм, заголовки будут целиком в строчном kebab-case.

Матрица решений для семи языков

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

ЯзыкПеременнаяФункцияКлассКонстантаИмя файлаСтолбец БД
Python (PEP 8)snake_casesnake_casePascalCaseCONSTANT_CASEsnake_case.pysnake_case
JavaScript/TScamelCasecamelCasePascalCaseCONSTANT_CASEkebab-case.jssnake_case
GocamelCase*PascalCase**PascalCasemixedCase***snake_case.gosnake_case
Rustsnake_casesnake_casePascalCaseSCREAMING_SNAKEsnake_case.rssnake_case
JavacamelCasecamelCasePascalCaseCONSTANT_CASEPascalCase.javasnake_case
C#camelCase†PascalCasePascalCasePascalCasePascalCase.cssnake_case
SQLn/asnake_casen/an/an/asnake_case
  • * Go: строчная первая буква означает unexported (package-private), заглавная — exported (public). Это форсит компилятор.
  • ** Go: экспортируемые функции — PascalCase (http.NewRequest); package-private функции — camelCase (http.parseHeader).
  • *** Go: константы подчиняются тому же правилу exported/unexported капитализации — MaxRetries для экспортируемых, maxRetries для package-private. Go намеренно избегает CONSTANT_CASE.
  • C#: локальные переменные и приватные поля — camelCase (некоторые кодовые базы префиксят поля _: _userName); публичные свойства, методы и типы — PascalCase.

Три слоя, которые проходят сквозь все языки одинаково:

HTML и CSS: имена классов и id — kebab-case (<div class="user-profile-card">). Пользовательские HTML-атрибуты — kebab-case с префиксом data- (data-user-id). Inline CSS-свойства — kebab-case (background-color); их DOM-эквиваленты в JS — camelCase (element.style.backgroundColor).

HTTP: исходящие имена заголовков — Header-Case для HTTP/1.1 ('Content-Type': 'application/json') и строчный kebab-case на проводе HTTP/2. Большинство fetch-библиотек принимают любое написание и нормализуют внутри.

Переменные окружения: CONSTANT_CASE везде — Node, Python, Go, Rust, Bash, Docker, Kubernetes. Соглашение .env-файла такое же: DATABASE_URL=postgres://....

Обработка акронимов: Google vs Microsoft

Это самый спорный вопрос об именовании на ревью кода. Должно быть parseUrl или parseURL? userId или userID? HtmlParser или HTMLParser? XmlHttpRequest или XMLHttpRequest?

Существуют две школы, и за каждой стоит реальный авторитет.

Считать акроним словом (Google, Apple, современный JS): parseUrl, userId, HtmlParser. Google JavaScript Style Guide §5.3 явно рекомендует именно это. Apple Swift API Design Guidelines говорят то же самое. Пакеты lodash и change-case выдают такой вывод по умолчанию. Аргумент — стабильность round-trip: parseUrl чисто токенизируется в parse / url, конвертируется в parse_url и обратно в parseUrl без потери информации. parseURL токенизируется в parse / URL, превращается в parse_u_r_l под наивным токенизатором или в parse_url под акроним-осведомлённым — но затем parse_url уже не может решить, возвращаться ли в parseUrl или в parseURL, потому что полностью строчное написание потеряло сигнал об акрониме.

Сохранять капитализацию акронима (Microsoft, .NET, старый Java): parseURL, userID, HTMLParser, XMLHttpRequest. Microsoft .NET Naming Guidelines ограничивают это правило 2–3-буквенными акронимами (IO, URL, XML) и применяют «считать словом» для более длинных (Html под строгим чтением был бы «сохранить капс», но на практике Microsoft пишет HtmlAgilityPack). Win32 API, .NET BCL и большая часть Java-кода до 2010-х идут этим путём. Англоязычным читателям он кажется более естественным — parseURL читается как «parse U-R-L» — ценой свойства round-trip.

PEP 8 в Python номинально рекомендует «считать словом», но стандартная библиотека Python исторически непоследовательна: http.server.HTTPServer и xml.etree.ElementTree сохраняют акронимы, тогда как json.JSONDecoder делает то же самое. Более новые добавления (pathlib.PurePath, dataclasses) склоняются к «считать словом». Позиция PEP 8 такая: следуйте окружающему коду.

Точечная проверка по публичному корпусу GitHub в начале 2026 года (сэмпл bigquery-public-data.github_repos в BigQuery, отфильтрованный по файлам TypeScript и JavaScript из репозиториев с 1000+ звёзд) показывает соотношение примерно 7:3 для parseUrl против parseURL и 6:4 для userId против userID. Стиль «считать словом» выигрывает в JavaScript. C# остаётся плотно в стиле Microsoft — parseURL доминирует в файлах C#. Python расколот пополам.

Правило решения: (а) следуйте стандартной библиотеке языка, на котором пишете; (б) когда стандартная библиотека непоследовательна, для greenfield-проекта выбирайте «считать словом», потому что он round-trip-ит; (в) запишите выбор в линтер или конфиг стиля и никогда не смешивайте оба подхода в одном проекте. Токенизатор Конвертера регистра следует соглашению «считать словом», чтобы совпадать с lodash и пакетом change-case — вставьте XMLHttpRequest, и на выходе будут xmlHttpRequest, xml_http_request, xml-http-request в качестве camelCase, snake_case и kebab-case.

URL-слаги: почему kebab-case лучше snake_case

Если читать официальную документацию Google Search Central о структуре URL, в ней встречается ровно одна конкретная рекомендация по case: используйте дефисы для разделения слов в URL, не используйте подчёркивания. Причина — токенизация. Поисковый индекс Google разбивает URL по дефисам, но не по подчёркиваниям. https://example.com/buy-running-shoes токенизируется как buy, running, shoes — три индексируемых терма, которые могут совпасть с любым из этих слов запроса. https://example.com/buy_running_shoes токенизируется как единственный терм buy_running_shoes, который совпадает только с этой точной строкой.

На устоявшихся страницах практический эффект для ранжирования невелик (у Google есть другие сигналы), но реален для новых страниц, конкурирующих в плотной выдаче. На равных условиях URL в kebab-case ранжируется выше.

Есть и вторая причина: чувствительность к регистру. URL-пути чувствительны к регистру на Linux-серверах (а это бо́льшая часть веба). /User-Profile и /user-profile — два разных URL, две разные записи в кеше, две разные строки в аналитике. Строчный kebab-case — единственное написание, которое не провоцирует баг «у меня на Mac работает».

Четырёхшаговый рецепт слага, работающий для любого заголовка:

  1. Привести всё к нижнему регистру.
  2. Заменить любые последовательности пробелов и пунктуации одним дефисом.
  3. Срезать ведущие и хвостовые дефисы.
  4. Опционально выбросить стоп-слова (a, an, the, of, for) ради коротких URL — но только если CMS сохраняет исходный заголовок для шапки страницы.

Рабочий пример: "10 Tips for Faster JavaScript: A Complete Guide"10-tips-faster-javascript-complete-guide. Двоеточие и стоп-слова (for, a) уходят; результат — 39 символов, спокойно влезает в «золотую зону» 50–60 символов для SERP. Подробнее про длину URL и её связь с символьными лимитами платформ — Гид по лимитам символов и слов.

Конвертер регистра выдаёт kebab-case-вариант любого заголовка в одну вставку — пригодится, когда массово генерируете слаги для миграции CMS или sitemap.

Шесть ловушек конвертации

Автоматическая конвертация между case выглядит тривиально. На деле — нет. Вот шесть мест, где она ломается.

1. Границы между цифрами и буквами

Чем становится file2x после snake_case-конвертации? Мейнстримное соглашение — lodash, change-case, PEP 8, Конвертер регистра — считает каждый переход «буква↔цифра» границей токена, поэтому file2x разбирается как file / 2 / x и snake_case-ится в file_2_x. parseUTF8 становится parse / utf / 8 и parse_utf_8.

Некоторые старые библиотеки (и часть рукописных re.sub-сниппетов со Stack Overflow) пропускают это правило и выдают file2xfile2x или parseutf8. Расхождение всплывает только при миграции кода между библиотеками, а симптом такой: «половина идентификаторов переименована, половина — нет». Выберите один токенизатор, убедитесь, что он соблюдает правило цифровой границы, и держитесь его.

2. Подряд идущие заглавные буквы

Регулярное выражение для границы акронима — /([A-Z]+)([A-Z][a-z])/ — оно вставляет разрыв между серией заглавных и финальной заглавной, начинающей новое слово. XMLHttpRequest сначала матчится как XML + HttpRequest, затем как Http + Request, давая токены XML / Http / Request.

Обратный путь — там и кусается: XML / Http / Request, заново собранное в PascalCase, превращается в XmlHttpRequest, а не в XMLHttpRequest. Акроним получил title-case. Это стандартное поведение, потому что альтернатива — пытаться помнить, какие токены изначально были акронимами — требует метаданных вне строки, которых у токенизатора нет. Если ваша кодовая база в стиле XMLHttpRequest и вы прогоните проектное переименование через «считать словом»-конвертер, вы молча перепишете каждый акроним. Сначала тестируйте на ветке или используйте токенизатор, который позволяет помечать акронимы явно.

3. Unicode и locale-aware приведение к регистру

'I'.toLowerCase() в JavaScript обычно возвращает 'i'. Запустите тот же вызов с активной турецкой локалью — и получите 'ı' (бесточечное i, U+0131), потому что в турецком есть две разные буквы i, и строчная для заглавной I — это именно бесточечная. Этот единственный баг выкатывали бесчисленные команды на локализациях: формы входа, приводящие имя пользователя к верхнему регистру для сравнения, тихо отрезают любого пользователя с турецкой локалью по имени İrem.

Ещё два минных поля: немецкое ß.toUpperCase() возвращает 'SS' — один символ превращается в два, и любой код, считающий, что приведение к регистру сохраняет длину строки, ошибается. Греческое Σ.toLowerCase() зависит от контекста: σ в середине слова, ς — в конце.

Исправление: используйте toLocaleLowerCase() и toLocaleUpperCase() с явной локалью или — если локаль пользователя неизвестна — передавайте 'en-US', чтобы получить ASCII-совместимое поведение. Конвертер регистра использует Intl-осведомлённые методы, поэтому все три эти входа обрабатываются корректно. Для regex-стороны вопроса в Шпаргалке Regex разобран Unicode-класс букв \p{L}.

4. Загрязнение «умными» кавычками

Вставьте строку из Microsoft Word, Google Docs или macOS Notes в конвертер регистра — и можете утащить с собой невидимых пассажиров: U+2018 / U+2019 / U+201C / U+201D (фигурные кавычки), U+2014 (em-dash), U+00A0 (неразрывный пробел), U+200B (пробел нулевой ширины). Все они в большинстве шрифтов выглядят неотличимо от своих ASCII-эквивалентов, но кодируются иначе. camelCase-идентификатор с U+00A0 внутри в одних языках скомпилируется, в других — нет, а ваш grep по имени переменной молча промахнётся.

Защита: нормализуйте вход перед токенизацией. Однострочник input.normalize('NFKC').replace(/[“”‘’]/g, '"') снимает большинство нарушителей. Либо подход из Гида по сравнению текста — diff подозрительной строки против её визуального ASCII-близнеца и просмотр невидимок в hex-виде.

5. URL не нужно snake_case-ить

https://example.com/api/users, вставленное в snake_case-конвертер, даст https_example_com_api_users. Технически это валидный snake_case-идентификатор; семантически — катастрофа. URL уже находится в своём каноничном case (path/case со строчными kebab-case-сегментами пути), и попытка прогнать весь URL как один идентификатор уничтожает структурную информацию.

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

6. dot.case против обращения к свойству

Строка user.profile.image — это две разные сущности в зависимости от контекста. Как dot.case-идентификатор в TOML-файле — это одно имя из трёх сегментов. Как JavaScript-выражение — это свойство image свойства profile объекта user.

Если скопировать dot.case-строку из конфига и вставить в JavaScript-консоль, рантайм попытается выполнить её как цепочку обращений к свойствам и либо упадёт, либо вернёт что-нибудь неожиданное. И наоборот, код, который строково манипулирует JS-путями свойств ('a.b.c'.split('.')), иногда получает на вход dot.case-идентификаторы извне и относится к ним как к более глубоким путям, чем задумано. Эти две сущности обязаны сидеть в разных неймспейсах.

Соглашение: dot.case-строки остаются внутри данных (конфиги, пути MongoDB, ключи логов); код с одиночными идентификаторами использует camelCase или snake_case; если в коде нужна иерархическая сущность — используйте вложенные объекты и dot-синтаксис обращения к свойствам родного языка.

Рецепты межязыковой миграции

JS camelCase → Python snake_case

Самый быстрый workflow: скопировать JS-идентификатор, вставить в конвертер, скопировать snake_case-вывод. Для кодовой конвертации в массовом режиме:

import { snakeCase } from 'change-case';

snakeCase('parseHTML');         // 'parse_html'
snakeCase('XMLHttpRequest');    // 'xml_http_request'
snakeCase('parseUTF8');         // 'parse_utf_8'
snakeCase('iPhone');            // 'i_phone'

Последний пример — та самая ловушка: iPhone — это бренд, где camelCase-граница вводит в заблуждение. Бренды и горстку исторических идентификаторов после конвертации правьте руками.

SQL snake_case → API-ответы JS/Java

Большинство ORM делают это автоматически. У Sequelize есть underscored: true, у TypeORM — класс SnakeNamingStrategy, у Hibernate — ImplicitNamingStrategyComponentPathImpl. Дефолтный маппинг — user_profile_iduserProfileId.

Что ломается — столбцы с акронимами. Столбец http_status_code чисто round-trip-ит в httpStatusCode, но если ваша кодовая база предпочитает HTTPStatusCode, ORM будет с вами спорить. Либо переименуйте столбец в httpstatuscode_code (некрасиво), либо настройте ORM на сохранение акронимов (редко), либо примите стандартное соглашение.

React PascalCase-компоненты → CSS kebab-case-классы

// UserProfileCard.tsx
export function UserProfileCard({ user }) {
  return <div className="user-profile-card">{user.name}</div>;
}
/* UserProfileCard.module.css */
.user-profile-card { padding: 1rem; }
.user-profile-card__avatar { border-radius: 50%; }
.user-profile-card--featured { background: gold; }

BEM (Block Element Modifier) — самое распространённое CSS-соглашение, парное к React: блок — это имя компонента в kebab-case, элемент — block__element, модификатор — block--modifier. На уровне файлов: UserProfileCard.tsx для компонента, UserProfileCard.module.css для scoped-стилей — оба в PascalCase, совпадая с именем компонента.

Переменные окружения → конфиг приложения

# .env (CONSTANT_CASE)
DATABASE_URL=postgres://localhost/myapp
MAX_RETRIES=3
LOG_LEVEL=info
// Node.js
const dbUrl = process.env.DATABASE_URL;
const maxRetries = parseInt(process.env.MAX_RETRIES, 10);
# Python
import os
db_url = os.environ['DATABASE_URL']
max_retries = int(os.environ['MAX_RETRIES'])

Имя env-переменной остаётся в CONSTANT_CASE; идентификатор на стороне приложения следует соглашению переменных языка. Ключи YAML/TOML-конфига традиционно пишутся в snake_case (database_url, max_retries), хотя они и маппятся на те же CONSTANT_CASE env-переменные в рантайме — фреймворки вроде Spring, dotenv и Pydantic сами берут на себя маппинг между case.

Сравнение библиотек и инструментов

ИнструментЯзыкиПоддерживаемые caseПоведение токенизатора
lodash (_.camelCase и т. д.)JavaScript4 основных + startCaseСчитать акроним словом
Пакет npm change-caseJavaScript/TSВсе 8 программных caseСчитать акроним словом
inflection (Python)PythoncamelCase / snake_caseСчитать акроним словом
Крейт convert_caseRust12+ caseКонфигурируемые акронимы
Go strings + regexGoСамописноеОпределяется проектом
VS Code (встроенный)РедакторТолько UPPER / lower / TitleТолько пробелы
Расширение VS Code «change-case»РедакторВсе 8 программных caseСчитать акроним словом
Конвертер регистраБраузер15 case (7 текстовых + 8 кодовых)Считать акроним словом

Для повседневной работы поставьте change-case (JS) или convert_case (Rust). Для Python пакет inflection — каноничный выбор, но небольшой рукописный regex покрывает 90% случаев. Для разовых конвертаций во время код-ревью или рефакторинга Конвертер регистра показывает все 15 вариантов в одну вставку, чтобы можно было сравнить их одним взглядом. Если попутно нужно посчитать токены или проверить длину идентификатора, эту сторону закрывает Счётчик слов; для проверки самого regex-токенизатора — Тестер Regex с шаблонами из шпаргалки, упомянутой выше.

FAQ

В чём разница между camelCase и PascalCase?

camelCase начинается со строчной буквы (userProfile); PascalCase — с заглавной (UserProfile). Оба пишут каждое последующее слово с заглавной буквы без разделителя. camelCase — соглашение для переменных и функций в большинстве C-семейственных языков; PascalCase — соглашение для классов, типов и React-компонентов.

Почему Python использует snake_case, а JavaScript — camelCase?

Python (1991) унаследовал snake_case от C и языка ABC, а затем PEP 8 закрепил его как стандарт сообщества. JavaScript (1995) скопировал camelCase-стиль Java, а Java унаследовал camelCase у Smalltalk. И то и другое — историческая инерция. Технически ни одно из соглашений не лучше — исследования читаемости дают примерное равенство, — и согласованность внутри экосистемы важнее самого выбора.

Использовать parseUrl или parseURL для акронимов в camelCase?

parseUrl (считать акроним словом) — современный дефолт, используется Google, Apple, lodash и пакетом change-case. parseURL (сохранять капитализацию акронима) — стиль Microsoft .NET, доминирует в коде на C#. Для нового проекта на JavaScript, TypeScript или Swift выбирайте parseUrl, потому что он чисто round-trip-ит через конвертации в snake_case и kebab-case. Что бы ни выбрали, закодируйте выбор в линтере.

kebab-case лучше snake_case для URL?

Да. Официальная рекомендация Google Search Central — использовать в URL дефисы, а не подчёркивания. Поисковые индексы токенизируют по дефисам, но не по подчёркиваниям: /user-profile индексируется как user + profile, а /user_profile — как единственный терм user_profile. Эффект на ранжирование невелик на страницу, но реален, а строчный kebab-case в URL ещё и избавляет от багов чувствительности к регистру на Linux-серверах.

В каком case писать имена столбцов базы данных?

snake_case. Каждый крупный ORM (SQLAlchemy, Hibernate, Sequelize, TypeORM, Active Record) использует его по умолчанию, и каждый крупный SQL-диалект обрабатывает его одинаково. PostgreSQL приводит неэкранированные идентификаторы к нижнему регистру, MySQL чувствителен к регистру на Linux и нечувствителен на macOS/Windows, SQLite относится к именам как к непрозрачным строкам. Строчный snake_case — единственное написание, которое ведёт себя одинаково везде.

Можно ли смешивать соглашения именования в одном проекте?

Да — и обычно приходится. Типичное веб-приложение использует camelCase для JS-переменных, snake_case для базы данных, kebab-case для CSS-классов и URL, CONSTANT_CASE для env-переменных. Правило такое: «одно соглашение на слой, никогда не смешивать внутри одного слоя». Закодируйте выбор для каждого слоя в линтере или гайде стиля, чтобы PR-ревью перестали тратить на это слова.

Как программно конвертировать между case?

Для JavaScript и TypeScript поставьте change-case или используйте lodash — _.camelCase / _.snakeCase / _.kebabCase. Для Python — пакет inflection или короткий regex (re.sub(r'(?<!^)(?=[A-Z])', '_', s).lower() для PascalCase → snake_case). Для Rust — крейт convert_case. Для разовых интерактивных конвертаций Конвертер регистра показывает все 15 вариантов case для любого входа на одной браузерной странице.

CONSTANT_CASE — только для переменных окружения?

Нет, но env-переменные — самый частый кейс. CONSTANT_CASE — для любого «инварианта рантайма»: MAX_RETRIES, API_BASE_URL, DEFAULT_PAGE_SIZE, значения enum, определения макросов, верхнеуровневые конфигурационные константы. Правило: «будет ли изменение значения в рантайме багом?» — если да, CONSTANT_CASE; если нет, обычное соглашение переменных для языка. const result = await fetch(url) остаётся как есть.

В чём разница между dot.case и path/case?

dot.case использует . как разделитель (user.profile.image) и представляет иерархический ключ внутри данных: пакеты Java, пути полей MongoDB, ключи TOML-конфигов, lodash get/set-пути. path/case использует / (user/profile/image) и представляет реальное расположение: URL-пути, пути файловой системы, ref-ы Git. Выбор «точки против слешей» сигнализирует «метка данных» против «фактического расположения».

Шпаргалка решений на 30 секунд

Три правила, закрывающих 95% вопросов:

  1. Для идентификаторов в коде копируйте стандартную библиотеку своего языка. Python: snake_case для переменных и функций, PascalCase для классов. JavaScript и TypeScript: camelCase для переменных и функций, PascalCase для классов и компонентов. Go: строчная первая буква — package-private, заглавная — экспортируемое. Rust: snake_case для переменных и функций, PascalCase для типов, SCREAMING_SNAKE для констант.

  2. Для сквозных слоёв case фиксирован вне зависимости от языка. URL — kebab-case. CSS-классы — kebab-case. Имена столбцов БД — snake_case. Переменные окружения — CONSTANT_CASE. Заголовки HTTP/1.1 — Header-Case (HTTP/2 нормализует к строчному на проводе).

  3. Запишите выбор в линтер один раз — и прекратите спорить. ESLint, Pylint, Clippy, golangci-lint и Rubocop — у всех есть правила для этого. Выберите соглашение, настройте линтер, и следующее PR-ревью ни одним словом не вспомнит про userID против userId.

Когда всё-таки требуется конвертация между case — для рефакторинга, миграции CMS, маппинга SQL → API — Конвертер регистра выдаёт все 15 вариантов в одну вставку, чтобы можно было скопировать нужный без ручной токенизации входа. По смежной работе с текстом — Счётчик слов, Тестер Regex и Сравнение текста онлайн. Из углублённого чтения — Шпаргалка Regex разбирает паттерны токенизатора, Гид по сравнению текста — сравнения до/после во время миграции, а Гид по лимитам символов и слов — бюджеты длины URL для SEO-слагов.

Похожие статьи

Все статьи