Я занимаюсь собеседованиями бэкенд-разработчиков уже более десяти лет.

У некоторых было впечатляющее резюме. Некоторые работали в компаниях с громкими именами. У некоторых жирным шрифтом было написано «Опыт работы 10+ лет».

И всё же… на собеседовании многие из них проваливались. Не из-за синтаксиса. Не из-за фреймворков. А из-за фундаментальных бэкенд-концепций, которые они якобы «отлично» знали.

Эта статья — не для того, чтобы кого-то оскорбить. Ее цель — показать разрыв между годами стажа и реальным пониманием.

Потому что, проинтервьюировав десятки кандидатов на должность старшего бэкенд-разработчика, я заметил четкую закономерность.

Одни и те же 12 концепций неизменно отделяют настоящих старших разработчиков от тех, кто только числится в этой должности.

1. Потокобезопасность: все о ней знает, мало кто понимает

Когда я спрашиваю: «Этот код потокобезопасен?», большинство ответов начинаются так: «Да, потому что мы использовали ключевое слово synchronized».

И здесь-то и начинается проблема.

Что их подводит?

Они думают, что потокобезопасность = ключевое слово synchronized. Настоящее понимание означает знание:

  • что такое разделяемое изменяемое состояние;
  • почему возникают условия гонки;
  • как возникают проблемы видимости даже без условий гонки;
  • почему одной атомарности недостаточно.

Я задаю уточняющие вопросы:

  • Что произойдет без синхронизации на многоядерных процессорах?
  • Зачем нужно ключевое слово volatile?
  • Когда ключевое слово synchronized не требуется?

Обычно в ответ — молчание.

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

2. Индексы в базе данных: используются ежедневно, понимаются редко

Почти все говорят: «Индексы повышают производительность».

Но ответы становятся расплывчатыми, когда я спрашиваю:

  • Как именно?
  • Что происходит внутри?
  • Когда индекс замедляет работу?

Что их подводит?

Они не понимают:

  • для чего используются B-деревья и хэш-индексы;
  • почему важна селективность индекса;
  • почему слишком много индексов замедляет запись;
  • почему индекс может вообще не использоваться.

Некоторые даже убеждены: «Добавление индексов всегда повышает производительность».

Это мышление разработчика-новичка.

Старшие разработчики понимают компромиссы, а не только преимущества.

3. Транзакции: одного ACID недостаточно

Большинство кандидатов могут перечислить принципы ACID: atomicity (атомарность), consistency (согласованность), isolation (изолированность), durability (долговечность).

Но обычно на этом их знания заканчиваются.

Что их подводит?

Они не могут объяснить:

  • Как на самом деле работают уровни изоляции?
  • Разницу между READ COMMITTED и REPEATABLE READ.
  • Почему возникают фантомные чтения?
  • Как MVCC (Multiversion Concurrency Control  — многоверсионное управление конкурентным доступом) решает многие из этих проблем?

Однажды я спросил: «Почему уровень изоляции READ COMMITTED все равно допускает неповторяющееся чтение?»

В комнате повисла тишина.

Вызубрить ACID — не значит понимать, как работают транзакции.

4. REST: все создают API, но не все проектируют их правильно

Почти каждый бэкенд-разработчик работает с REST API.

Но многие проваливают простой вопрос: «Что делает API по-настоящему RESTful?»

RESTful  — соответствующий архитектурному стилю REST (representational state transfer — передача состояния представления).

Что их подводит?

Они думают, что REST — это просто:

  • HTTP + JSON.

Они забывают о ключевых принципах:

  • правильном использовании HTTP-методов;
  • идемпотентности; 
  • статус-кодах;
  • URL’ах, ориентированных на ресурсы;
  • отсутствии фиксации состояния (statelessness).

Когда кто-то использует POST для всего подряд и всегда возвращает 200 OK — это явный признак проблемы.

Старшие разработчики проектируют API, а не просто реализуют конечные точки.

5. Кэширование — самый опасный инструмент для повышения производительности

Кэширование — мощный инструмент.

И именно поэтому он опасен.

Многие кандидаты говорят: «Мы добавили Redis и решили проблему производительности».

Что их подводит?

Они игнорируют:

  • недействительность кэша (когда данные становятся неактуальными);
  • согласованность данных между кэшем и источником;
  • проблемы устаревших данных;
  • проблемы «давки» в кэше (одновременного массового построения одного и того же результата и его записи в кэш).

Я спрашиваю: «Что происходит, когда кэшированные данные устаревают?»

Большинство ответов: «Мы очищаем кэш».

Это не стратегия. Это наивный подход.

Старшие разработчики знают: в информатике есть только две сложные вещи: недействительность кэша и присвоение имен.

6. Микросервисы — модный тренд, используемый где надо и не надо

Если в резюме соискателей упоминаются микросервисы, я копаю глубже.

Что их подводит?

Они не могут объяснить:

  • Почему система была разделена?
  • Какую проблему решили микросервисы?
  • Какие новые проблемы они создали?

Многие думают, что микросервисы = сервисы меньшего размера.

Они не учитывают:

  • задержки в сети;
  • распределенные сбои;
  • согласованность данных;
  • сложность мониторинга.

Некоторым системам никогда не стоит становиться микросервисами.

Старшие разработчики понимают, когда их не следует использовать.

7. Логирование — не то же самое, что использование print-операторов

Логирование игнорируется многими разработчиками до тех пор, пока не произойдет сбой в производственной среде.

Что их подводит?

Они:

  • пишут слишком много или слишком мало логов;
  • ведут логи без структуры;
  • невольно регистрируют конфиденциальные данные.

Я спрашиваю: «Что делает лог подходящим для производственной среды?»

Лишь единицы упоминают:

  • идентификаторы корреляции;
  • уровни логирования;
  • Контекстную информацию;
  • возможность поиска по логам.

    Старшие разработчики ведут журналы для отладки в 3 часа ночи, а не только для удобства разработки.

8. Управление памятью: сборщик мусора (GC) не всемогущ

Многие бэкенд-разработчики слепо доверяют сборщику мусора.

Что их подводит?

Они верят в то, что GC все уладит.

Они не могут объяснить:

  • утечки памяти в автоматически управляемых языках;
  • разницу между кучей и стеком;
  • как выделение объектов влияет на производительность;
  • почему возникают длительные паузы GC.

Однажды я спросил: «Может ли в Java-приложении возникать утечка памяти?»

Половина кандидатов ответила: «Не может».

Этого ответа уже достаточно, чтобы провалить собеседование.

9. Обработка ошибок: исключения не являются  управляющей конструкцией

На этом отсеиваются многие соискатели.

Что их подводит?

Они:

  • ловят общие исключения;
  • «проглатывают» ошибки (оставляют блок catch пустым);
  • использует исключения для обычной логики.

Когда я спрашиваю: «Что делает эффективным ответ на ошибку?»

Многие затрудняются объяснить:

  • понятность сообщения об ошибках;
  • корректные статус-коды HTTP;
  • четкое разделение ошибок клиента и сервера.

Старшие разработчики рассматривают ошибки как часть проектирования системы, а не как нечто второстепенное.

10. Масштабируемость — не то же самое, что производительность

Многие соискатели путают масштабируемость с производительностью.

Что их подводит?

Они рассуждают так: «Если система быстрая, значит, она масштабируема».

Они не могут объяснить:

  • вертикальное и горизонтальное масштабирование;
  • узкие места;
  • преимущества stateless-архитектуры (без сохранения состояния) для масштабирования;
  • Почему разделяемое состояние (shared state) губит масштабируемость

Я спрашиваю: «Может ли быстрая система выйти из строя под нагрузкой?»

Если соискатель отвечает «нет» — это уже проблема.

11. Безопасность — задача не разработчика

Многие разработчики отодвигают проблему безопасности на второй план.

Что их подводит?

Они полагаются исключительно на «безопасность фреймворка».

Они игнорируют:

  • SQL-инъекции;
  • разницу между аутентификацией и авторизацией;
  • истиечение срока действия токенов;
  • правильное хранение паролей.

Я спрашиваю: «Как бы вы обеспечили безопасность этой конечной точки?»

И получаю ответ: «Spring Security с этим разберется».

Это не ответственность. Это уклонение от решения проблем.

12. Компромиссное мышление — главный отличительный признак старшего разработчика

Это самый важный момент, о котором не догадываются многие соискатели. 

Что их подводит?

Они мыслят категориями абсолютов:

  • «это всегда лучшее”;
  • «это — плохо»;
  • «надо всегда делать только так».

Старшие разработчики мыслят в терминах компромиссов и поиска баланса:

  • скорость или стабильность;
  • простота или гибкость;
  • быстрый выход на рынок или обеспечение долгосрочной поддержки.

Я всегда спрашиваю: «Что бы вы изменили, если бы завтра трафик удвоился?»

Лучшие ответы начинаются со слов: «Это зависит от…»

Это не колебания.

Это опыт.

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Pudari Madhavi: These 12 Backend Concepts Quietly Decide Who Passes Senior Interviews

Предыдущая статьяJava и Spring Boot: 7 трендов, которые изменят бэкенд-разработку в 2026 году
Следующая статьяВозведение числа в квадрат на C++: методы и применение