GRAIN — обзор

Last updated: 2026-08-18Стандарт кода APERTURESyndicate — имена, контракты, форма. То, что переживает любой форматтер и читается как почерк.

GRAIN 1.1

Стандарт кода APERTURESyndicate. Зерно плёнки — то, по чему узнают носитель, не глядя на подпись.

GRAIN не про отступы и кавычки: это работа форматтера, и она не оставляет следа. GRAIN — про имена, контракты и форму: то, что остаётся после любого форматтера и читается как почерк. Код, написанный по GRAIN, узнаётся в чужом репозитории с одного экрана.

Три принципа

1. Закрытые словари вместо вкуса. Глаголы, единицы измерения, префиксы, роли файлов — конечные списки. Не «пиши понятно», а «вот 33 глагола, других нет». Спор о названии функции длится ровно столько, сколько занимает чтение таблицы.

2. Имя — часть контракта. findTrack и getTrack — разные обещания, а не синонимы. Прочитав имя, ты знаешь: может ли вернуться null, ходит ли функция в сеть, порождает ли событие, в чём измеряется число. Это снимает половину поводов открыть тело функции.

3. Форма — следствие ответственности, а не вкуса. Функция длинная не потому, что «так вышло», а потому что делает две вещи. Ограничения на вложенность, число аргументов и длину — не эстетика, а сигнализация: превысил — раздели.

Уровни

Стандарт принимается не целиком за один день. L1 и L2 отличаются объёмом правил, L3 — машинной гарантией.

L1
Читаемость
Глагол из словаря · единица у числа · префикс у булевых · тегированные комментарии · никаких utils · мёртвый код удаляется
Личный проект, первая неделя
L2
Контракты
Всё ядро: find/get, роли файлов, форма функции, модель отказов, границы и направление зависимостей
Командная работа, код живёт дольше года
L3
Дисциплина
Правила L2 плюс проверка в CI, блокирующий pre-commit, полное покрытие, ни одного обхода в истории
Продукт в проде, чужие люди читают код

Уровень объявляется в конфигурации проекта и подтверждается машиной: заявить L2 и не проходить L2 нельзя — чекер не выдаст бейдж.

bash
bun grain --all --badge
[![GRAIN L2](https://docs.aperturesyndicate.com/badge/grain-l2.svg)](https://docs.aperturesyndicate.com/ru/grain/overview)

Пять правил, с которых начинают

Если читать дальше некогда — вот L1 целиком.

Как обычно
function handleTrackData(data) {
  const timeout = 900
  // increment counter
  const flag = data.views > 0
}
По GRAIN
function publishTrack(draft) {
  const refreshTtlSec = 900
  // why: счётчик обновляется до сохранения — иначе гонка с воркером
  const hasViews = draft.viewCount > 0
}
  1. Функция начинается с глагола из словаря. handle, process, manage, check, init, update запрещены — они не сообщают действия.
  2. Число несёт единицу измерения. refreshTtlSec, priceCents, sizeBytes. Число без единицы — это класс продакшн-багов, а не вопрос вкуса.
  3. Булево начинается с is / has / can / should / was / will / must.
  4. Комментарий отвечает «почему» и несёт тег: why:, perf:, safety:, spec:, ref:. Пересказ кода удаляется.
  5. Ни одного файла или каталога с именем utils, helpers, common, misc. У «утилит» есть законное место — *.pure.ts рядом со своим доменом.

Что дальше

СтраницаО чём
Разбор эндпоинтаОдин обработчик до и после, 13 нарушений с ценой каждого
Глаголы и именаПолный словарь из 33 глаголов, единицы, булевы, запрещённые слова
Форма, границы, отказыВоронка, пределы, где живут время и случайность, две модели отказа
Файлы и комментарииДесять ролей файлов, каталоги по доменам, пять тегов
Анти-отпечатокПочему сгенерированный код узнаётся, и что стандарт не регламентирует
ВнедрениеЛинтер, чекер, pre-commit, уровни, бейдж

Машинный источник истины — файл grain.synx: те же словари, но как данные. Правило, которого нет в нём, не проверяется машиной; правило, которого нет в этих документах, не имеет смысла. Меняются оба вместе или ни один.

GRAIN — обзор | AS Docs