Совет Брайана Кернигана о «хорошем вкусе» показывает, как читаемый код экономит время, уменьшает количество багов и помогает командам работать быстрее, чем хитрые уловки.

Имя Брайана Кернигана встречается там, где многие разработчики даже не задумываются: классические Unix-инструменты, экосистема C и десятилетия текстов, которые научили объяснять программы ясно. Помните ли вы The C Programming Language (с Деннисом Ритчи), The Unix Programming Environment или его эссе и выступления — общая нить та же: настаивание на простых идеях, выраженных аккуратно.
Лучший совет Кернигана не зависит от синтаксиса C или конвенций Unix. Он о том, как читают люди: мы просматриваем структуру, полагаемся на имена, выводим намерение и пугаемся, когда код прячет смысл за трюками. Поэтому «вкус» в читаемости важен и при написании TypeScript, Python, Go, Java или Rust.
Языки меняются. Инструменты улучшаются. Команды всё ещё доставляют фичи под давлением времени, и бóльшая часть кода поддерживается не его первоначальным автором (часто — будущим вами). Ясность — это множитель, который делает всё это выживаемым.
Это не панегирик «геройскому кодингу» и не призыв зубрить старые правила. Это практическое руководство по привычкам, которые делают повседневный код проще для работы:
Влияние Кернигана важно, потому что оно указывает на простую, дружелюбную к команде цель: писать код, который коммуницирует. Когда код читается как ясное объяснение, вы тратите меньше времени на его расшифровку и больше — на улучшение.
«Хороший вкус» в читаемом коде — это не про личный стиль, модные паттерны или сведение решения к наименьшему числу строк. Это привычка выбирать самое простое ясное решение, которое надёжно передаёт намерение.
Решение с хорошим вкусом отвечает базовому вопросу для следующего читателя: что пытается сделать этот код и почему он делает это именно так? Если ответ требует умственных упражнений, скрытых допущений или расшифровки хитростей, код стоит команде времени.
Большую часть времени код читают гораздо чаще, чем пишут. «Хороший вкус» рассматривает чтение как основную деятельность:
Вот почему читаемость — это не только эстетика (отступы, ширина строки или предпочитаемый snake_case). Это в основном про облегчение рассуждений: понятные имена, очевидный поток управления и предсказуемая структура.
Распространённая ошибка — оптимизировать ради краткости вместо ясности. Иногда самый понятный код чуть длиннее, потому что делает шаги явными.
Например, сравните два подхода:
Второй вариант может добавить строк, но снижает когнитивную нагрузку, необходимую для проверки корректности. Он также облегчает изоляцию багов и делает изменения безопаснее.
Хороший вкус — это знание, когда прекратить «улучшать» решение хитростями и вместо этого сделать намерение явным. Если коллега понимает код без экскурса, вы выбрали правильно.
Хитрый код часто кажется выигрышем в моменте: меньше строк, аккуратный трюк, «вау» в диффе. В реальной команде эта хитрость превращается в повторяющийся счёт — оплачиваемый временем на вхождение, временем на ревью и сомнениями каждый раз, когда нужно что-то изменить.
Вхождение замедляется. Новым сотрудникам нужно не только изучить продукт; им приходится осваивать вашу частную диалектную систему сокращений. Если для понимания функции требуется расшифровка хитрых операторов или неявных соглашений, люди будут избегать её изменения или менять её с опаской.
Ревью продолжаются дольше и становятся менее надёжными. Ревьюерам приходится доказывать корректность трюка вместо того, чтобы оценивать, соответствует ли поведение намерению. Хуже того, сложный код труднее мысленно смоделировать — ревьюеры пропускают краевые случаи, которые они заметили бы в простом варианте.
Хитрость накапливается во время:
Некоторые повторяющиеся виновники:
17, 0.618, -1), кодирующие правила, которые никто не запомнит.\u0026\u0026 / ||), полагающиеся на знание тонких правил оценки.Здесь проявляется мысль Кернигана о «вкусе»: ясность — это не про больше строк; это про явное намерение. Если «умная» версия экономит 20 секунд сегодня, но стоит 20 минут каждому будущему читателю, она не умная — она дорогая.
«Вкус» Кернигана часто проявляется в мелких, повторяемых решениях. Не нужен крупный рефакторинг, чтобы сделать код удобнее для жизни — крошечные победы по ясности складываются каждый раз, когда кто-то просматривает файл, ищет поведение или исправляет баг в спешке.
Хорошее имя уменьшает нужду в комментариях и делает ошибки менее вероятными.
Стремитесь к именам, раскрывающим намерение и соответствующим речи вашей команды:
invoiceTotalCents вместо sum;Если имя заставляет вас его расшифровывать, оно делает противоположное своей задаче.
Большая часть чтения — это сканирование. Последовательные пробелы и структура помогают глазу найти главное: границы функций, условные блоки и «happy path».
Несколько практических привычек:
Когда логика становится запутанной, читаемость обычно улучшается, если решения сделать явными.
Сравните два стиля:
// Harder to scan
if (user \u0026\u0026 user.active \u0026\u0026 !user.isBanned \u0026\u0026 (role === 'admin' || role === 'owner')) {
allow();
}
// Clearer
if (!user) return deny('missing user');
if (!user.active) return deny('inactive');
if (user.isBanned) return deny('banned');
if (role !== 'admin' \u0026\u0026 role !== 'owner') return deny('insufficient role');
allow();
Второй вариант длиннее, но читается как чеклист — и его легче расширять без поломок.
Это «малые» решения, но они — ежедневное ремесло поддерживаемого кода: имена, которые остаются честными, форматирование, которое ведёт читателя, и поток управления, не требующий умственных акробатик.
Стиль ясности Кернигана особенно заметен в том, как вы делите работу на функции и модули. Читатель должен уметь просканировать структуру, угадать, что делает каждая часть, и в большинстве случаев быть правым, не вчитываясь в детали.
Стремитесь к функциям, которые делают ровно одну вещь на одном уровне «уменьшения». Когда функция смешивает валидацию, бизнес-логику, форматирование и I/O, читателю приходится держать в голове несколько нитей.
Быстрый тест: если вы пишете комментарий вроде “// теперь делаем X” внутри функции, то X часто хорошая кандидатура на отдельную функцию с понятным именем.
Длинные списки параметров — скрытый налог сложности: каждый вызов превращается в мини-файл конфигурации.
Если несколько параметров всегда путешествуют вместе, аккуратно сгруппируйте их. Объекты опций (или небольшие структуры данных) делают места вызовов самодокументирующимися — если группа логична и вы не сваливаете всё в один «misc» мешок.
Также предпочитайте передачу доменных концептов вместо примитивов. UserId лучше, чем string, а DateRange лучше, чем (start, end), когда у этих значений есть правила.
Модуль — это обещание: «всё, что нужно для этой концепции, здесь; остальное — в другом месте». Держите модули достаточно маленькими, чтобы держать их назначение в голове, и проектируйте границы, минимизирующие побочные эффекты.
Практические привычки, которые помогают:
Когда вам всё-таки нужен общий стейт, называйте его честно и документируйте инварианты. Ясность — не про избегание сложности, а про размещение её там, где читатели ожидают. Для дальнейших советов по сохранению этих границ при изменениях см. /blog/refactoring-as-a-habit.
«Вкус» Кернигана проявляется и в том, как вы комментируете: цель не аннотировать каждую строку, а уменьшить будущие недопонимания. Лучший комментарий тот, который предотвращает неверное предположение — особенно когда код верный, но неожиданный.
Комментарий, который просто пересказывает код («увеличить i»), добавляет шум и приучает игнорировать комментарии. Полезные комментарии объясняют намерение, компромиссы или ограничения, неочевидные из синтаксиса.
# Bad: says what the code already says
retry_count += 1
# Good: explains why the retry is bounded
retry_count += 1 # Avoids throttling bans on repeated failures
Если тянет написать «что»-комментарий, это часто признак того, что код можно улучшить (лучшие имена, меньшая функция, проще поток управления). Пусть факты несёт код; комментарии несут рассуждения.
Ничто не подрывает доверие так быстро, как устаревший комментарий. Если комментарий опционален, он со временем уйдёт в сторону; если он неверен, он становится активным источником ошибок.
Практическая привычка: относитесь к обновлению комментариев как к части изменения, а не как к «хорошему тону». На ревью справедливо спросить: соответствует ли этот комментарий поведению? Если нет — обновите или удалите. «Без комментария» лучше, чем «неверный комментарий».
Встроенные комментарии для локальных сюрпризов. Более широкие пояснения — в докстрингах, README или заметках для разработчиков — особенно для:
Хорошая докстринга объясняет, как правильно использовать функцию и какие ошибки ожидать, без пересказа реализации. Небольшой файл /docs или README сохраняет историю «почему мы сделали именно так» и переживает рефакторинг.
Тихая победа: меньше комментариев, но каждый заработал своё место.
Большая часть кода «нормально» работает на happy path. Истинный тест вкуса — что происходит, когда входы отсутствуют, сервисы таймаутят или пользователь делает что-то неожиданное. Под давлением хитрость склонна скрывать правду. Ясный код делает провал очевидным — и восстановимым.
Сообщения об ошибках — часть продукта и рабочего процесса отладки. Пишите их так, будто следующий человек устал и на дежурстве.
Включайте:
Если у вас есть логирование, добавляйте структурированный контекст (например, requestId, userId или invoiceId), чтобы сообщение было действенным без рытья в не относящихся данных.
Соблазн «покрыть всё» одним хитрым однострочником или универсальным catch-all велик. Хороший вкус — выбирать те крайние случаи, которые важны, и делать их видимыми.
Например, явная ветка для «пустого ввода» или «не найдено» часто читается лучше, чем цепочка трансформаций, которая неявно где-то выдаёт null. Когда особый случай важен — именуйте его и вынесите на первый план.
Смешение форм возврата (иногда объект, иногда строка, иногда false) заставляет держать в уме дерево решений. Предпочитайте паттерны с постоянной формой:
Ясная обработка ошибок снижает сюрпризы — а сюрпризы порождают баги и ночные вызовы.
Ясность — это не только то, что вы имели в виду, когда писали код. Это то, чего следующий человек ожидает, открыв файл в 16:55. Последовательность превращает «чтение кода» в распознавание паттернов — меньше сюрпризов, меньше недопониманий, меньше повторяющихся споров.
Хороший командный стиль — короткий, конкретный и прагматичный. Он не пытается зафиксировать каждое предпочтение; он закрывает повторяющиеся вопросы: соглашения по именованию, структуре файлов, паттернам обработки ошибок и что значит «готово» для тестов.
Реальная ценность — социальная: это прекращает повторяющееся обсуждение в каждом PR. Когда что-то задокументировано, ревью смещается от «мне нравится X» к «мы договорились о X (и вот почему)». Держите руководство живым и доступным — многие команды кладут его в репозиторий (например, /docs/style-guide.md), чтобы оно было рядом с кодом.
Используйте форматтеры и линтеры для всего измеримого и скучного:
Это освобождает людей для работы над смыслом: именами, формой API, граничными случаями и соответствием кода намерению.
Ручные правила всё ещё важны, когда они касаются дизайна — например, «предпочитать ранние return, чтобы снизить вложенность» или «по одному публичному входу на модуль». Инструменты не могут полностью судить о таких вещах.
Иногда сложность оправдана: жёсткие бюджеты производительности, встраиваемые ограничения, конкурентность или платформенные особенности. Соглашение должно быть таким: исключения разрешены, но явны.
Простое правило помогает: документируйте компенсацию в коротком комментарии, добавьте микробенчмарк или измерение, когда ссылаетесь на производительность, и изолируйте сложный код за понятным интерфейсом, чтобы большая часть кодовой базы оставалась читаемой.
Хорошее ревью должно ощущаться не как инспекция, а как короткий, целенаправленный урок «хорошего вкуса». Керниган не говорил, что хитрость — это зло; он говорил, что хитрость дорога, когда другим приходится с ней жить. Ревью — место, где команда может явно оценить эту цену и сознательно выбирать ясность.
Начинайте с вопроса: «Сможет ли коллега понять это с первого раза?» Обычно это значит смотреть на имена, структуру, тесты и поведение до вникания в микрооптимизации.
Если код корректен, но труден для чтения, относитесь к читаемости как к реальному дефекту. Предлагайте переименование переменных, разбиение длинных функций, упрощение потока управления или небольшой тест, демонстрирующий ожидаемое поведение. Ревью, которое фиксирует «работает, но непонятно почему», предотвращает недели будущей путаницы.
Практический порядок проверки, который хорошо работает:
Ревью уходит в сторону, когда обратная связь оформлена как выставление баллов. Вместо «Зачем вы сделали так?» попробуйте:
Вопросы приглашают к сотрудничеству и часто выявляют ограничения, о которых вы не знали. Предложения показывают направление, не намекая на некомпетентность. Именно такой тон распространяет «вкус» по команде.
Если хотите стабильную читаемость, не полагайтесь на настроение ревьюера. Добавьте несколько «чеков на ясность» в шаблон ревью и определение готовности. Держите их короткими и конкретными:
Со временем это превращает ревью из полицейских действий в обучение суждению — именно та повседневная дисциплина, которую пропагандировал Керниган.
Инструменты на базе больших моделей могут быстро сгенерировать рабочий код, но «работает» — не тот уровень, на который указывал Керниган; важно, чтобы код коммуницировал. Если команда применяет vibe-coding workflow (например, фичи через чат и итерации по сгенерированному коду), стоит считать читаемость критерием приёмки.
На платформах вроде Koder.ai, где можно генерировать React‑фронтенды, Go‑бэкенды и Flutter‑мобильные приложения из чат‑промпта (и экспортировать исходники), те же привычки по вкусу применимы:
Скорость ценна тогда, когда результат остаётся простым для человека: проверки, поддержки и расширения.
Ясность — не состояние «достигнуто однажды». Код остаётся читаемым, только если вы постоянно подталкиваете его обратно к простому языку по мере изменения требований. Чувство Кернигана здесь применимо: предпочитайте постепенные понятные улучшения вместо геройских переписок или «умных» однострочников, которые впечатляют сегодня и путают завтра.
Самый безопасный рефакторинг — скучный: крошечные изменения, сохраняющие поведение. Если у вас есть тесты, запускайте их после каждого шага. Если нет — добавьте несколько фокусных проверок вокруг области изменения: временные страховочные ограждения, чтобы улучшить структуру без страха.
Практический ритм:
Малые коммиты также упрощают ревью: коллеги могут оценить намерение, а не искать побочные эффекты.
Не нужно вычищать все хитрости за один заход. Когда вы трогаете код для фичи или фикса, заменяйте хитрые ухищрения понятными эквивалентами:
Так ясность побеждает в реальной команде: по одному улучшенному месту, прямо там, где люди уже работают.
Не всё требует немедленной чистки. Полезное правило: рефакторьте сейчас, когда код активно меняется, часто неправильно понимается или может привести к багам. Запланируйте на потом, когда код стабилен и изолирован.
Делайте долг видимым: оставьте короткий TODO с контекстом или заведите тикет, описывающий проблему («трудно добавить новые способы оплаты; функция делает 5 задач»). Так решение будет осознанным, а не тихим налогом команды.
Если хотите, чтобы «хороший вкус» появлялся стабильно, сделайте его простым для практики. Вот лёгкий чеклист, который можно повторять в планировании, кодинге и ревью — короткий, чтобы запомнить, и конкретный, чтобы действовать.
До: process(data) делает валидацию, парсинг, сохранение и логирование в одном месте.
После: разделить на validateInput, parseOrder, saveOrder, logResult. Главная функция становится читаемым планом.
До: if not valid then return false повторяется пять раз.
После: один секционный guard в начале (или одна функция валидации), возвращающая список проблем.
До: x, tmp, flag2, doThing().
После: retryCount, draftInvoice, isEligibleForRefund, sendReminderEmail().
До: цикл с тремя спрятанными особыми случаями в середине.
После: сначала обработайте особые случаи (или вынесите их в хелперы), затем выполните простой цикл.
Выберите одно улучшение на эту неделю: «ни одной новой аббревиатуры», «happy path первым», «экстрактить по одному хелперу в PR» или «в каждом сообщении об ошибке — шаги для дальнейших действий». Отслеживайте семь дней и сохраняйте то, что действительно облегчило чтение.
Влияние Кернигана скорее про то, что код — это средство коммуникации, чем про C.
Языки и фреймворки меняются, а команды по-прежнему нуждаются в коде, который легко просканировать, понять, проверить и отладить — тем более спустя месяцы и под давлением времени.
«Хороший вкус» — это привычка выбирать самое простое и при этом ясное решение, которое передаёт намерение.
Полезный тест: сможет ли коллега ответить на вопрос «что делает этот код и почему он сделан именно так?» без раскодирования трюков или опоры на скрытые допущения.
Потому что код читают гораздо чаще, чем пишут.
Оптимизация для читателей сокращает время на вхождение в проект, снижает трения в ревью и уменьшает риск неверных изменений — особенно когда поддерживает «будущий ты», у которого меньше контекста.
«Налог за хитрость» проявляется как:
Если хитрая версия экономит секунды сейчас, но добавляет минуты при каждом касании, это чистые потери.
Частые виновники:
Такие приёмы скрывают промежуточное состояние и упрощают промахи на ревью.
Когда они снижают когнитивную нагрузку.
Явно оформленные шаги с именованными переменными (например, validate → normalize → compute) упрощают проверку корректности, делают отладку проще и облегчают будущие изменения — даже если строки кода увеличиваются.
Стремитесь к:
invoiceTotalCents лучше, чем sum)Если имя нужно расшифровывать, оно не выполняет свою работу; имя должно сокращать необходимость в комментариях.
Предпочитайте простые и явные ветвления и держите «счастливый путь» на виду.
Полезные тактики:
Комментируйте почему, а не что.
Полезные комментарии объясняют намерение, компромиссы или ограничения, которые не очевидны из синтаксиса. Избегайте очевидных «что»-комментариев и относитесь к обновлению комментариев как к части правки — устаревший комментарий хуже отсутствия.
Инструменты для механики, люди для смысла.
Используйте форматтеры и линтеры для измеримых правил (форматирование, порядок импортов, очевидные ошибки), а человеческие ревью — для вопросов значения: имен, формы API, граничных случаев.
Лёгкое style guide помогает ограничить повторяющиеся дебаты. Исключения (производительность, платформенные ограничения) должны быть явными: документируйте компромисс и изолируйте сложность за чистым интерфейсом.