GRAIN 1.1
Стандарт кода APERTURESyndicate. Зерно плёнки — то, по чему узнают носитель, не глядя на подпись.
GRAIN не про отступы и кавычки: это работа форматтера, и она не оставляет следа. GRAIN — про имена, контракты и форму: то, что остаётся после любого форматтера и читается как почерк. Код, написанный по GRAIN, узнаётся в чужом репозитории с одного экрана.
Три принципа
1. Закрытые словари вместо вкуса. Глаголы, единицы измерения, префиксы, роли файлов — конечные списки. Не «пиши понятно», а «вот 33 глагола, других нет». Спор о названии функции длится ровно столько, сколько занимает чтение таблицы.
2. Имя — часть контракта. findTrack и getTrack — разные обещания, а не синонимы. Прочитав имя, ты знаешь: может ли вернуться null, ходит ли функция в сеть, порождает ли событие, в чём измеряется число. Это снимает половину поводов открыть тело функции.
3. Форма — следствие ответственности, а не вкуса. Функция длинная не потому, что «так вышло», а потому что делает две вещи. Ограничения на вложенность, число аргументов и длину — не эстетика, а сигнализация: превысил — раздели.
Уровни
Стандарт принимается не целиком за один день. L1 и L2 отличаются объёмом правил, L3 — машинной гарантией.
Уровень объявляется в конфигурации проекта и подтверждается машиной: заявить L2 и не проходить L2 нельзя — чекер не выдаст бейдж.
bun grain --all --badge[](https://docs.aperturesyndicate.com/ru/grain/overview)Пять правил, с которых начинают
Если читать дальше некогда — вот L1 целиком.
function handleTrackData(data) {
const timeout = 900
// increment counter
const flag = data.views > 0
}function publishTrack(draft) {
const refreshTtlSec = 900
// why: счётчик обновляется до сохранения — иначе гонка с воркером
const hasViews = draft.viewCount > 0
}- Функция начинается с глагола из словаря.
handle,process,manage,check,init,updateзапрещены — они не сообщают действия. - Число несёт единицу измерения.
refreshTtlSec,priceCents,sizeBytes. Число без единицы — это класс продакшн-багов, а не вопрос вкуса. - Булево начинается с
is/has/can/should/was/will/must. - Комментарий отвечает «почему» и несёт тег:
why:,perf:,safety:,spec:,ref:. Пересказ кода удаляется. - Ни одного файла или каталога с именем
utils,helpers,common,misc. У «утилит» есть законное место —*.pure.tsрядом со своим доменом.
Что дальше
| Страница | О чём |
|---|---|
| Разбор эндпоинта | Один обработчик до и после, 13 нарушений с ценой каждого |
| Глаголы и имена | Полный словарь из 33 глаголов, единицы, булевы, запрещённые слова |
| Форма, границы, отказы | Воронка, пределы, где живут время и случайность, две модели отказа |
| Файлы и комментарии | Десять ролей файлов, каталоги по доменам, пять тегов |
| Анти-отпечаток | Почему сгенерированный код узнаётся, и что стандарт не регламентирует |
| Внедрение | Линтер, чекер, pre-commit, уровни, бейдж |
Машинный источник истины — файл grain.synx: те же словари, но как данные. Правило, которого нет в нём, не проверяется машиной; правило, которого нет в этих документах, не имеет смысла. Меняются оба вместе или ни один.