
Слепая дегустация для кода
Статья была полезной?
Привет, Хабр. Я Полина, продакт и главный редактор медиаплатформы «Своё Вино» от Россельхозбанка. Помните, не так давно мы обсуждали, что общего у вина и ИТ? На платформе «Своё вино» мы с редакцией обычно анализируем терруары, стили и винтажи, но в этот раз попробуем посмотреть на языки программирования с той же точки зрения. Давайте попробуем угадать язык по пяти строкам кода и разобраться, по каким «ароматам» и «танинам» наш мозг быстро различает их.

Если вы когда-либо выбирали вино по этикетке и затем анализировали, совпал ли вкус с ожиданиями, значит вы уже знакомы с тем, как функционирует наш мозг: он фиксируется на деталях и восстанавливает общую картину. Когда мы смотрим на код, происходит нечто аналогичное: вместо бутылки перед нами становится открытый репозиторий.
Существует особое удовольствие и свой шарм в слепой дегустации вина. Когда этикетка скрыта, остаются только цвет, аромат и текстура. Это самая честная дегустация: вы полагаетесь лишь на базовые «нравится»/«не нравится», «вкусно»/«невкусно». Мозг опытного дегустатора в это время лихорадочно сопоставляет: это Бургундия или Пьемонт, классика или Новый Свет? В конце концов, это красное или белое? (На самом деле, если дегустировать некоторые вина в чёрных бокалах, определить, белые они или красные, оказывается крайне сложно).
С кодом происходит примерно то же самое. Дайте разработчику 5-7 строк, и он часто может определить язык, поскольку у каждого языка есть свой стиль, своя «органолептика» — синтаксис, ритм, плотность, любимые конструкции. Мы считываем их почти интуитивно.
В этой статье мы попробуем провести слепую дегустацию кода: поиграем в угадайку, разберем, по каким маркерам мозг распознает стиль, и аккуратно сравним языки с различными стилями вина.
Начнём с простых примеров, где «букет» языка ощущается уже через секунды.
def normalize(text):
words = text.lower().split()
return [w.strip(".,!?") for w in words if w]Согласитесь, Python распознается почти мгновенно. Почему?
В нем минимальный шум: отсутствуют точки с запятой и фигурные скобки, он читается как псевдокод, почти как предложение на английском, а list comprehension придаёт плавность и ощущение целостности.
Если проводить аналогию с вином, это что-то вроде Пино Нуара из Бургундии: визуально и даже по консистенции вино легкое, но с глубиной и интересными нюансами, все держится на балансе, а не на серьезной выдержке в дубе.
Продолжаем!
public static List<String> normalize(String text) {
List<String> result = new ArrayList<>();
for (String word : text.toLowerCase().split(" ")) {
result.add(word.trim());
}
return result;
}Это, конечно же, Java. Его мы ощущаем по «телу» кода. Явные типы в сигнатуре и локальных переменных, строгая, почти архитектурная структура, много каркасных элементов, которые поддерживают систему даже в простом примере.
Это уже не Бургундия, а скорее классический Бордо: структурный, предсказуемый, рассчитанный на долгую жизнь и развитие в производстве.
const normalize = text =>
text
.toLowerCase()
.split(" ")
.map(w => w.trim())
.filter(Boolean);JavaScript мы легко узнаем по стрелочным функциям, цепочкам методов, гибкости записи, которая воспринимается как в одной строке, так и в виде сложной цепочки.
Это вина Нового Света: яркие, сочные, ароматные, иногда чуть эклектичные и даже слегка вызывающие. Этот язык позволяет создавать как аккуратные, выдержанные купажи, так и довольно эксцентричные смеси, итог всегда зависит от выбора разработчика.
func normalize(text string) []string {
words := strings.Fields(strings.ToLower(text))
return words
}Go — это чистота и прагматизм: минимум абстракций, четкие конструкции func, строгие типы, лаконичность и почти инженерный минимализм, никакой лишней информации.
В винной аналогии это сухой рислинг: чистый, строгий, с хорошо определённой кислотностью. Он не пытается впечатлить сложным букетом, а просто честно выполняет свою задачу.
Интереснее всего не угадать язык, а сам процесс распознавания. На что мы опираемся, когда посмотрим на незнакомый фрагмент?
Синтаксический аромат языков программирования
Первый аромат кода — это синтаксис:
фигурные скобки или отступы;
ключевые слова (def, fn, func, public);
типизация в сигнатурах или её отсутствие;
форма комментариев.
Мы мгновенно распознаем язык по нескольким компонентам, как сомелье определяет стиль по первому вдоху: Python прозрачный, Java плотная, JavaScript ароматный и темпераментный, Go — строгий и честный.
Текстура и тело кода: факторы восприятия
При чтении мозгу важен не только синтаксис, но и текстура:
линейный или вложенный код;
декларативный или императивный подход;
плотность: много кода на одну концепцию или немного.
Некоторые языки воспринимаются как танины: одни шелковые и бархатистые, другие — сложные и структурированные. Это аналогично тому, как вино может иметь легкое или плотное тело, маслянистое или нет, с выдержкой в стали, дубе или глине.
Ритм и поток кода: ощущения от программирования
Код тоже обладает ритмом. В некоторых местах вы читаете легко, будто знакомый рассказ, а в других — как технический регламент, где мысль может теряться. Python больше про повествование, Java про строгое следование правилам, JavaScript про импровизацию. С опытом вы начинаете ощущать этот ритм так же уверенно, как отличаете игристое вино от выдержанного красного к стейкам.
Попробуем устроить маленькую слепую дегустацию. Не подглядывайте в ответы сразу, дайте мозгу поработать.
Задача 1
def compute(values):
total = 0
for v in values:
if v is None:
continue
total += v
return total or NoneВарианты:
A: JavaScript
B: Python
C: Ruby
D: Go
Ответ: B: Python. Маркеры: def для определения функции, отступы вместо фигурных скобок, None вместо null или nil. Это похоже на тонкий аромат сорта: даже если вы не помните все детали, общие черты можно различить.
Задача 2
result := make([]int, 0, len(values))
for _, v := range values {
if v%2 == 0 {
result = append(result, v)
}
}
return resultВарианты:
A: Go
B: Rust
C: TypeScript
D: C#
Ответ:A: Go. Мозг фиксирует: короткое объявление :=, цикл for с range, использование append и слайсы []int. Код сухой, ясный, без лишнего декора. Все как в классическом виноделии.
Задача 3
let normalize input =
input
|> String.lowercase_ascii
|> String.split_on_char ' '
|> List.filter (fun s -> s <> "")Варианты:
A: Elixir
B: F#
C: OCaml
D: Scala
Ответ: C: OCaml. Маркеры: let для определения функции, оператор конвейера |>, модульные функции String.*, List.* и fun для лямбд. Функциональный стиль, но без перегруженности, как аккуратное, структурное вино из долины Луары.
Задача 4
public async Task<IEnumerable<User>> LoadUsersAsync(CancellationToken token)
{
var users = await _repository.GetAllAsync(token);
return users
.Where(u => u.IsActive)
.OrderBy(u => u.LastName)
.ThenBy(u => u.FirstName);
}Варианты:
A: Java
B: C#
C: TypeScript
D: Kotlin
Ответ:B: C#. Признаки: сочетание async/await в сигнатуре и теле, Task> вместо Future> и т.д., LINQ-стиль с методами Where, OrderBy, ThenBy. Java и Kotlin выглядят иначе, TypeScript не использует Task<>. Это выдержанный, структурный подход к корпоративному коду в бордосском стиле.
Задача 5
fn normalize(input: &str) -> Vec<&str> {
input
.to_lowercase()
.split_whitespace()
.collect()
}Варианты:
A: Rust
B: Swift
C: Kotlin
D: Haskell
Ответ:A: Rust. Маркеры: fn в объявлении, заимствование &str и Vec, цепочка методов с финальным .collect(). Сочетание строгой типизации и выразительной последовательности операций создаёт ощущение вина с долгой выдержкой: сначала трудно, потом начинаешь улавливать всё больше нюансов и ароматики. Вино раскрывается в бокале.
Чтобы собрать все сравнения в один пазл, давайте взглянем на мини-погреб языков и винных стилей. Кому-то ближе легкие и прозрачные вина, кому-то плотные и структурные.
Язык программирования | Образ вина | Характер стиля кода |
Python | Пино Нуар из Бургундии | Легкий на вид, нюансный, сбалансированный |
Java | Классический Бордо | Структурный, предсказуемый, имеет потенциал к выдержке |
JavaScript | Моносортовые вина и купажи Нового Света | Яркий, гибкий, от утончённого до слегка хаотичного |
Go | Сухой рислинг из Мозеля | Чистый, строгий, без лишнего декора |
Rust | Вино с долгой выдержкой | Требует опыта, но дает много глубины и слоистости |
Как и в вине, у языков есть свои «вины-винтажи».
Старый PHP, с обилием HTML, вперемешку с логикой, — как полусладкое из 2000-х, с которого многие начинали знакомство с вином. Раньше это казалось идеальным, но теперь вкусы стали более требовательными: хочется меньше сладости и больше структуры.
Python 2 с функцией print без скобок — это ностальгический винтаж из домашней коллекции. У кого-то стоят на полке пару бутылок на память, кто-то с теплотой вспоминает, но его уже нет в актуальной винной карте (production).
Ранний JavaScript era тотального var и callback-пирамид — как ёмкость для сусла, где смешали все подряд. Формально это вино, но второй бокал берёшь с большой осторожностью и после пары крепких рефакторингов.
С опытом меняется как вкус к вину, так и к языкам программирования: сначала хочется «сладкого» синтаксического сахара и минимума типизации, потом возникает потребность в сухости: строгие типы, явные контракты, предсказуемость, и в итоге приходит понимание, что различные стили нужны для разных задач.
Если хотите продолжения, можем отдельно разобрать «натуральные вина» в мире программирования: DSL, экспериментальные языки, esolang и прочие экзотики. А пока можете оставить в комментариях свои пять строк для слепой дегустации. Посмотрим, насколько хорошо у нас натренирована интуиция для определения языков программирования.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…