Перейти к основному содержимому

Правила именования

См. также: Сегменты - где размещать различные типы файлов.

Именование файлов и директорий

MUST: Директории и файлы именуются в lower-kebab-case

✅ Хорошо
user-profile/
use-get-user-data.ts
avatar-upload.tsx
article-list.module.css

❌ Плохо
UserProfile/
useGetUserData.ts
AvatarUpload.tsx
articleList.module.css

MUST: Компоненты именуются в UpperCamelCase (PascalCase)

✅ Хорошо
export function UserProfile() { }
export function ProgressIndicator() { }

❌ Плохо
export function userProfile() { }
export function progress_indicator() { }

A/HC/LC Pattern для функций и переменных

MUST: Все имена функций и переменных строятся по единому паттерну:

prefix? + action (A) + high context (HC) + low context? (LC)

Визуальная схема паттерна

Таблица паттернов именования

ЭлементИспользованиеПримерыКогда применять
Prefix (P)Логические значения и предикатыis, has, should, canДля boolean переменных и проверок
Action (A)Действие/глаголget, set, fetch, handle, createОбязательно для функций
High Context (HC)Основная сущностьUser, Article, Order, CommentВсегда
Low Context (LC)Уточнение/деталиList, Count, Error, DraftКогда нужна конкретизация

Префиксы (Prefix)

MUST: Использовать префиксы для boolean переменных и функций-предикатов:

ПрефиксЗначениеПримерыКогда использовать
isОписывает характеристику или состояниеisAuthorized, isPending, isValidТекущее состояние или свойство
hasУказывает на наличие чего-либоhasAccess, hasError, hasChildrenПроверка наличия свойства/данных
shouldУсловие для действия или рендераshouldShowActions, shouldRedirectЛогическое условие для решения
canВозможность выполнения действияcanDeletePost, canEditArticleПроверка разрешений/возможностей

Примеры:

// ✅ Хорошо - is для состояния
const isAuthorized = Boolean(token);
const [isPending, setIsPending] = useState(false);
const isValidEmail = email.includes('@');

// ✅ Хорошо - has для наличия
const hasAccess = permissions.includes('admin');
const hasUnreadMessages = messages.some(m => !m.read);

// ✅ Хорошо - should для условий
const shouldShowActions = isAuthorized && hasAccess;
const shouldRedirect = !user && !isLoading;

// ✅ Хорошо - can для возможностей
const canDeletePost = user.id === post.authorId || user.role === 'admin';
const canEditArticle = isOwner && !article.published;

// ❌ Плохо - неправильный префикс
const authorizedUser = Boolean(token); // Используйте isAuthorized
const accessGranted = hasPermission(); // Используйте hasAccess

Действия (Actions)

MUST: Глагольная часть имени должна описывать, что делает функция:

ActionЗначениеПримерыКогда использовать
getПолучение/доступ к даннымgetUser, getDraftFromStoreСинхронное получение из памяти/стора
setОбновление значенияsetTitle, setUserRoleИзменение состояния/переменной
fetchПолучение данных извнеfetchUserProfile, fetchArticlesАсинхронный запрос к API/БД
handleОбработка события/ошибкиhandleClick, handleErrorEvent handlers, обработчики ошибок
createСоздание новой сущностиcreateArticle, createUserСоздание нового объекта/записи
updateОбновление существующей сущностиupdateArticle, updateProfileИзменение существующих данных
deleteУдалениеdeleteComment, deleteUserУдаление данных
validateПроверка валидностиvalidateEmail, validateFormВалидация данных
formatФорматированиеformatDate, formatCurrencyПреобразование для отображения

Примеры:

// ✅ get - синхронное получение
const getDraftFromStore = () => store.getState().draft;
const getUserName = (user: User) => user.name;

// ✅ set - обновление состояния
const setTitle = (title: string) => setState({ title });
const setUserRole = (role: Role) => user.role = role;

// ✅ fetch - асинхронный запрос
const fetchUserProfile = async (id: string) => await api.get(`/users/${id}`);
const fetchArticles = () => queryClient.fetchQuery('articles');

// ✅ handle - обработчики
const handleSubmit = (e: FormEvent) => { /* ... */ };
const handleUserNotFound = (error: Error) => { /* ... */ };

// ✅ create/update/delete
const createArticle = async (data: ArticleData) => await api.post('/articles', data);
const updateArticle = async (id: string, data: Partial<Article>) => { /* ... */ };
const deleteComment = async (id: string) => await api.delete(`/comments/${id}`);

// ❌ Плохо - неправильный action
const retrieveUser = () => { }; // Используйте getUser или fetchUser
const modifyArticle = () => { }; // Используйте updateArticle
const removeComment = () => { }; // Используйте deleteComment

Контекст (High Context + Low Context)

High Context (HC) - основная предметная область:

  • User, Article, Order, Comment, Profile, Post
  • Всегда используется, отражает бизнес-сущность

Low Context (LC) - уточнение, вторичные детали:

  • List, Count, Error, Message, Draft, Settings
  • Добавляется при необходимости конкретизации

Структура:

action + HighContext + LowContext?

Примеры:

// ✅ Action + HC
const getUser = (id: string) => users.find(u => u.id === id);
const fetchArticle = async (slug: string) => api.get(`/articles/${slug}`);

// ✅ Action + HC + LC (с уточнением)
const getUserList = () => users; // Список пользователей
const getArticleCount = () => articles.length; // Количество
const fetchUserProfile = (id: string) => api.get(`/users/${id}/profile`); // Профиль
const handleArticleError = (error: Error) => { /* ... */ }; // Обработка ошибки

// ✅ Prefix + Action + HC + LC
const isUserListEmpty = users.length === 0;
const shouldShowErrorMessage = hasError && !isLoading;

// ❌ Плохо - слишком общее
const getData = () => { }; // Какие данные?
const fetchInfo = () => { }; // Какая информация?

// ❌ Плохо - избыточное уточнение
const getUserListArrayData = () => { }; // Слишком длинно
const fetchArticleObjectFromAPI = () => { }; // Избыточно

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

Пример 1: Простое получение данных

// ✅ Хорошо
const getUser = (id: string) => users.find(u => u.id === id);
// get (A) + User (HC)

// ✅ Хорошо - с уточнением
const getUserById = (id: string) => users.find(u => u.id === id);
// get (A) + User (HC) + ById (LC)

Пример 2: Проверка состояния

// ✅ Хорошо
const isArticlePublished = article.status === 'published';
// is (P) + Article (HC) + Published (LC)

const canEditArticle = isOwner && !isArticlePublished;
// can (P) + Edit (A) + Article (HC)

Пример 3: Обработчики событий

// ✅ Хорошо - простой обработчик
const handleClick = () => { /* ... */ };
// handle (A) + Click (HC)

// ✅ Хорошо - с контекстом
const handleArticleSubmit = (data: ArticleData) => { /* ... */ };
// handle (A) + Article (HC) + Submit (LC)

// ✅ Хорошо - с полным контекстом
const handleArticleFormSubmit = (e: FormEvent) => { /* ... */ };
// handle (A) + ArticleForm (HC) + Submit (LC)

Пример 4: Сложные примеры с вложенным контекстом

// ✅ Хорошо - вложенная структура
const getUserProfileSettings = (userId: string) => { /* ... */ };
// get (A) + UserProfile (HC) + Settings (LC)

const shouldShowArticleEditButton = isAuthorized && canEditArticle;
// should (P) + Show (A) + ArticleEditButton (HC+LC)

const fetchUserDraftArticles = async (userId: string) => { /* ... */ };
// fetch (A) + User (HC) + DraftArticles (LC)

Контрольный список для проверки имени

Перед коммитом кода проверьте имена по этому списку:

Для функций:

  • Начинается с глагола (action): get, set, fetch, handle, etc.
  • Содержит High Context (сущность): User, Article, Order
  • Low Context добавлен только при необходимости уточнения
  • Имя читается как предложение: getUserProfile() = "get user profile"
  • Длина ≤ 4 слов (prefix + action + HC + LC)

Для переменных:

  • Boolean переменные начинаются с is, has, should, can
  • Имя отражает содержимое: userList, а не data
  • Используется camelCase
  • Избегайте сокращений (кроме общепринятых: id, url, api)

Для констант:

  • UPPER_SNAKE_CASE для глобальных констант: MAX_RETRY_COUNT
  • camelCase для локальных констант: defaultPageSize

Примеры правильных и неправильных имен

// ✅ ПРАВИЛЬНО
const isUserAuthorized = checkAuth(user);
const hasUnreadMessages = messages.filter(m => !m.read).length > 0;
const shouldShowWelcomeModal = isFirstVisit && !hasSeenModal;
const canDeletePost = user.role === 'admin' || post.authorId === user.id;

const getUser = (id: string) => users.find(u => u.id === id);
const getUserList = () => users;
const fetchUserProfile = async (id: string) => api.get(`/users/${id}`);
const handleArticleSubmit = (data: ArticleData) => { /* ... */ };
const createArticle = async (data: CreateArticleDTO) => { /* ... */ };
const updateUserProfile = async (id: string, data: ProfileData) => { /* ... */ };
const deleteComment = async (id: string) => api.delete(`/comments/${id}`);

const formatArticleDate = (date: string) => new Date(date).toLocaleDateString();
const validateEmail = (email: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);

// ❌ НЕПРАВИЛЬНО
const authorized = checkAuth(user); // Используйте isUserAuthorized
const unreadMessages = messages.filter(m => !m.read).length > 0; // Используйте hasUnreadMessages
const showModal = isFirstVisit; // Используйте shouldShowWelcomeModal
const deleteAllowed = user.role === 'admin'; // Используйте canDeletePost

const user = (id: string) => users.find(u => u.id === id); // Используйте getUser
const retrieveUsers = () => users; // Используйте getUserList
const loadProfile = async (id: string) => { }; // Используйте fetchUserProfile
const onSubmit = () => { }; // Используйте handleArticleSubmit
const add = (data: ArticleData) => { }; // Используйте createArticle
const modify = (id: string, data: any) => { }; // Используйте updateUserProfile
const remove = (id: string) => { }; // Используйте deleteComment

const dateFormat = (date: string) => { }; // Используйте formatArticleDate
const emailCheck = (email: string) => { }; // Используйте validateEmail