Programowanie 9 min czytania

camelCase, snake_case, kebab-case: który styl gdzie stosować

Styl nazewnictwa wynika z miejsca, w którym nazwa jest używana. Siedem konwencji z przykładami, ściąga w tabeli i zasady nazywania tokenów oraz komponentów w design systemie.

Zespół Squares Firma projektowo-wdrożeniowa, Wrocław

Styl nazewnictwa wybiera się według miejsca, w którym nazwa jest używana, a nie według upodobań. camelCase służy zmiennym i funkcjom w JavaScripcie, PascalCase klasom i komponentom, kebab-case adresom URL, plikom i klasom CSS, snake_case Pythonowi i bazom danych, a SCREAMING_SNAKE_CASE stałym i zmiennym środowiskowym. Ważniejsza od wyboru jest konsekwencja: jedna reguła na jedno miejsce w całym projekcie.

Tę samą frazę „user profile name” da się zapisać na siedem sposobów:

  • userProfileName (camelCase)
  • UserProfileName (PascalCase)
  • user-profile-name (kebab-case)
  • user_profile_name (snake_case)
  • USER_PROFILE_NAME (SCREAMING_SNAKE_CASE)
  • User-Profile-Name (Train-Case)
  • user.profile.name (dot.case)

Dlaczego konwencje nazewnictwa w kodzie mają znaczenie?

Nazwa zapisana zgodnie z konwencją niesie dodatkową informację. UserProfileCard sugeruje komponent, klasę albo typ. userProfileCard wygląda jak zmienna lub funkcja. USER_PROFILE_CARD od razu wskazuje stałą.

Koszt braku konwencji rośnie razem z projektem. Gdy jedna osoba pisze userProfile, druga user_profile, a trzecia tworzy plik user-profile.tsx, każdy zapis z osobna jest poprawny, ale zespół traci czas na szukanie plików, poprawki w przeglądach kodu i spory o rzeczy, które powinna rozstrzygać jedna strona dokumentacji. Kod czyta się wielokrotnie częściej, niż pisze, więc ta strata powtarza się przy każdej zmianie.

camelCase

Pierwsze słowo zaczyna się małą literą, każde kolejne wielką: userName, getUserProfile, isUserLoggedIn. Nazwa pochodzi od skojarzenia z garbami wielbłąda.

To domyślny zapis zmiennych, funkcji, metod, parametrów i właściwości obiektów w JavaScripcie, TypeScripcie, Javie i Kotlinie.

const userName = "Anna";

function getUserProfile() { return { name: userName }; }

camelCase sprawdza się tam, gdzie nazwa jest częścią logiki programu: jest zwięzły i nie wymaga separatorów. Nie pasuje do adresów URL, nazw plików i klas CSS. Zamiast userProfilePage.html lepiej zapisać user-profile-page.html.

PascalCase

Od camelCase różni się jednym: pierwsze słowo też zaczyna się wielką literą. Przykłady: UserProfile, PaymentService, OrderHistoryPage.

Tym stylem zapisuje się większe struktury w kodzie: klasy, komponenty, typy, interfejsy, enumy i modele danych.

class UserAccount { constructor(public userName: string) {} }

type UserProfile = { id: number; name: string };

W React to nie jest kwestia stylu. Według dokumentacji React nazwa komponentu musi zaczynać się wielką literą, inaczej komponent nie zadziała: zapis <section> React traktuje jako znacznik HTML, a <Profile /> jako komponent. Funkcja userProfileCard użyta jako komponent to więc błąd, a nie odstępstwo od konwencji.

PascalCase nie służy zwykłym zmiennym lokalnym. const UserName = "Anna"; wprowadza w błąd, poprawny zapis to const userName = "Anna";.

kebab-case

Same małe litery, słowa oddzielone łącznikami: user-profile, main-navigation, blog-post-card.

To zapis adresów URL, slugów, nazw plików i klas CSS:

  • adres: /blog/jak-nazywac-zmienne-w-kodzie
  • plik: user-profile-page.html
  • klasa CSS: .user-profile-card { padding: 16px; }

W adresach URL przemawia za nim także wyszukiwarka. Google w wytycznych o strukturze adresów zaleca łączniki zamiast podkreślników, bo ułatwiają użytkownikom i wyszukiwarkom rozpoznanie pojęć w adresie. /blog/style-nazewnictwa-w-programowaniu czyta się bez wysiłku, /blog/styleNazewnictwaWProgramowaniu już nie.

kebab-case nie nadaje się na nazwy zmiennych. W JavaScripcie łącznik jest operatorem odejmowania, więc const user-profile = "Anna"; kończy się błędem składni.

snake_case

Małe litery i podkreślniki między słowami: user_profile, get_user_profile, is_user_logged_in.

W Pythonie to standard zapisany w PEP 8: nazwy funkcji i zmiennych pisze się małymi literami, a słowa oddziela podkreślnikami. Klasy w Pythonie zapisuje się w PascalCase, który PEP 8 nazywa konwencją CapWords.

user_name = "Anna"

def get_user_profile(): return {"name": user_name}

snake_case dominuje też w bazach danych. Kolumny first_name, last_name i created_at w tabeli user_profiles są czytelne i nie wymagają cudzysłowów w zapytaniach SQL.

W JavaScripcie i TypeScripcie snake_case pojawia się głównie w danych przychodzących z API albo z bazy, na przykład z systemu headless CMS. Dobrą praktyką jest zamiana nazw na camelCase na granicy systemu, w jednym miejscu, zamiast mieszania obu stylów w całym kodzie.

SCREAMING_SNAKE_CASE

snake_case zapisany wielkimi literami: MAX_USER_COUNT, API_BASE_URL, DEFAULT_LANGUAGE.

Służy stałym, zmiennym środowiskowym i wartościom konfiguracyjnym. PEP 8 opisuje stałe tak samo: wielkie litery z podkreślnikami.

  • stała w kodzie: const MAX_RETRY_COUNT = 3;
  • zmienna środowiskowa: DATABASE_URL=postgres://localhost:5432/app
  • zmienna środowiskowa: NODE_ENV=production

Wielkie litery działają tylko wtedy, gdy są rzadkie. Jeśli każda zmienna, łącznie z USER_NAME i USER_EMAIL, jest zapisana w ten sposób, zapis przestaje cokolwiek komunikować.

Train-Case

kebab-case, w którym każde słowo zaczyna się wielką literą: Content-Type, Accept-Language, Cache-Control, User-Agent.

Najbardziej znane zastosowanie to nagłówki HTTP. Poza nimi styl jest rzadki i nie nadaje się na nazwy zmiennych, funkcji ani klas, z tego samego powodu co kebab-case: łącznik zostanie odczytany jako odejmowanie.

dot.case

Słowa oddzielone kropkami: auth.login.error, app.theme.color, settings.language.default.

Pasuje tam, gdzie nazwa ma strukturę hierarchiczną: w kluczach tłumaczeń, konfiguracji, nazwach metryk i zdarzeń analitycznych. Klucz auth.login.error czyta się jako obszar, ekran i komunikat.

W większości języków kropka ma znaczenie składniowe, więc dot.case nie może być nazwą zmiennej. const user.profile.name = "Anna"; jest błędem, poprawny odpowiednik to obiekt zagnieżdżony.

path/case

Słowa oddzielone ukośnikami: src/components/user-profile-card.tsx, api/users/profile. To zapis folderów, routingu i endpointów API, czyli sposób wskazania lokalizacji, a nie styl nazywania zmiennych. Poszczególne segmenty ścieżki najczęściej zapisuje się w kebab-case.

Title Case i Sentence case

Te dwa style dotyczą tekstów w interfejsie, a nie kodu. W Title Case każde ważne słowo zaczyna się wielką literą: Create New Account. W Sentence case wielką literą zaczyna się tylko pierwsze słowo: Create new account.

Decyzja należy do projektanta treści interfejsu i powinna być zapisana razem z konwencjami kodu, bo dotyczy każdego przycisku, etykiety i komunikatu. W polskiej wersji produktu wyboru nie ma: polska pisownia nie zna zapisu tytułowego, więc „Utwórz nowe konto” jest jedyną poprawną formą.

Który styl stosować w którym miejscu?

Pytanie wyjściowe brzmi: gdzie ta nazwa będzie używana. Odpowiedź wyznacza styl.

MiejsceStylPrzykład
Zmienna i funkcja w JavaScripcie i TypeScripciecamelCasegetUserProfile()
Klasa, typ, komponent ReactPascalCaseUserProfileCard
Zmienna i funkcja w Pythoniesnake_caseget_user_profile()
StałaSCREAMING_SNAKE_CASEMAX_RETRY_COUNT
Zmienna środowiskowaSCREAMING_SNAKE_CASEDATABASE_URL
Adres URL i slugkebab-case/user-profile
Klasa CSSkebab-case.user-profile-card
Tabela i kolumna w SQLsnake_casecreated_at
Klucz tłumaczenia, nazwa zdarzeniadot.caseauth.login.error
Ścieżka pliku, endpointpath/casesrc/components/button
Nagłówek HTTPTrain-CaseContent-Type
Design tokenścieżka z kropkami w źródle, kebab-case w CSScolor.accent.light
Tekst w interfejsieSentence caseCreate new account

Ta sama zasada dotyczy nazw kluczy w formatach danych, takich jak JSON czy format TOON.

Jak nazywać tokeny i komponenty w design systemie?

W design systemie nazwa jest umową między projektantem a programistą, więc konwencja musi obejmować oba narzędzia. Komponent, który w bibliotece projektowej nazywa się „Button Group”, a w kodzie BtnGrp, wymaga tłumaczenia przy każdym przekazaniu projektu. Wspólna nazwa w PascalCase, ButtonGroup, usuwa ten krok. Które elementy nazwać w pierwszej kolejności, podpowiada wpis o komponentach design systemu.

Design tokeny, czyli nazwane wartości kolorów, odstępów i typografii, mają własne ograniczenia. Specyfikacja formatu Design Tokens Community Group rozróżnia wielkość liter i zabrania w nazwach tokenów i grup kropki oraz nawiasów klamrowych, bo te znaki służą do odwołań między tokenami. Ścieżkę tokena buduje się z nazw grup połączonych kropkami: color.accent.light. W CSS ten sam token staje się zmienną w kebab-case: --color-accent-light. Specyfikacja ostrzega też przed nazwami różniącymi się tylko wielkością liter, bo po eksporcie do innego języka dają duplikaty.

O strukturze i poziomach tokenów piszemy we wpisie o tym, czym są design tokeny.

Co się dzieje, gdy style są mieszane?

Najwięcej kosztuje brak reguły, a nie zły wybór. W tym fragmencie każda linia działa, ale razem nie mówią nic o tym, co oznaczają wielkie litery:

  • const user_name = "Anna";
  • const userAge = 28;
  • const UserEmail = "[email protected]";
  • const USER_profile_status = "active";

Po ujednoliceniu do camelCase (userName, userAge, userEmail, userProfileStatus) kod czyta się bez zastanowienia. Reguły dla całego projektu mieszczą się w pięciu liniach: zmienne i funkcje w camelCase, komponenty i klasy w PascalCase, stałe w SCREAMING_SNAKE_CASE, pliki i adresy w kebab-case, baza danych w snake_case.

Taką listę zapisuje się w repozytorium i egzekwuje automatycznie, linterem w edytorze i w potoku wdrożeniowym. Reguła, której pilnuje tylko przegląd kodu, przestaje działać przy pierwszym napiętym terminie.

Wspólne nazwy w projekcie i w kodzie

W Squares konwencję nazw komponentów i tokenów ustalamy na początku pracy nad design systemem, razem z zespołem wdrożeniowym, żeby biblioteka projektowa i kod używały tych samych słów. Te same nazwy trafiają potem do kodu podczas wdrożenia aplikacji. Design system wyceniamy projektowo, od 12 000 zł netto.

Najczęstsze pytania

Czym różni się camelCase od PascalCase?

Jedną literą: w camelCase pierwsze słowo zaczyna się małą literą, w PascalCase wielką. camelCase służy zmiennym, funkcjom, metodom i właściwościom obiektów, a PascalCase większym strukturom: klasom, komponentom, typom i interfejsom. W React nazwa komponentu musi zaczynać się wielką literą, inaczej zostanie potraktowana jako znacznik HTML.

Jaki styl nazewnictwa stosować w adresach URL?

W adresach URL stosuje się kebab-case, czyli same małe litery i słowa oddzielone łącznikami, na przykład /user-profile. Google w wytycznych o strukturze adresów zaleca łączniki zamiast podkreślników, bo ułatwiają użytkownikom i wyszukiwarkom rozpoznanie pojęć w adresie. Ten sam zapis stosuje się w slugach, nazwach plików i klasach CSS.

Źródła

  1. React, Your First Component
  2. PEP 8, Style Guide for Python Code
  3. Google Search Central, URL structure best practices
  4. Design Tokens Community Group, Design Tokens Format Module (wersja robocza)

Zaktualizowano: