Чем дольше я работаю с ПРОД-системами, тем сильнее разделяю две способности: хорошо реализовывать решение и хорошо принимать инженерные решения.
Можно прекрасно знать язык, фреймворк, уметь быстро разбираться в чужом коде, писать хорошие тесты и делать аккуратные ПРы - и при этом регулярно принимать решения, которые через полгода начинают создавать проблемы всей системе.
Причем локально код может быть совершенно нормальным.
Возьмем простой пример.
Внешний сервис периодически отвечает по таймауту. Разработчик добавляет ретрай с бэкофом. Код хороший, библиотека подходящая, тесты зеленые.
Но инженерный вопрос начинается чуть раньше:
а можно ли эту операцию вообще безопасно повторять?
Если внешний сервис успел выполнить операцию, а потерялся только ответ, ретрай может выполнить ее второй раз.
И тогда проблема вообще не в реализации ретрая.
Проблема в том, что мы неправильно поняли семантику операции.
То же самое происходит постоянно.
Можно идеально реализовать кэш - и получить устаревшие данные там, где пользователь ожидает актуальное состояние.
Можно красиво вынести работу в Kafka - и внезапно превратить понятную синхронную ошибку в пятнадцатиминутное отставание данных, которое никто не мониторит.
Можно сделать корректную транзакцию - но держать ее открытой во время сетевого вызова и однажды положить пул соединенийl.
Можно поднять Prometheus, Grafana - и все равно не иметь возможности ответить на вопрос: получил ли пользователь правильный результат?
Во всех этих случаях разработчик мог хорошо выполнить свою работу.
Но инженерная задача была шире самой реализации.
Поэтому мне все меньше нравится оценивать сильного специалиста по тому, насколько сложный код он способен написать.
Код - только один из артефактов инженерного решения.
Гораздо интереснее, какие вопросы человек задает до того, как начинает писать код.
• Что произойдет при частичном отказе?
• Какую гарантию мы действительно даем?
• Что будет при конкурентном выполнении?
• Где находится источник истины?
• Что произойдет, если зависимость станет отвечать в десять раз медленнее?
• Можно ли это решение безопасно изменить через два года?
• Как мы узнаем в ПРОДе, что оно перестало выполнять свое предназначение?
И что особенно важно - какие последствия нашего локального решения появятся за пределами компонента, который мы сейчас меняем.
Наверное, поэтому хороший инженер для меня - это не человек, который обязательно знает больше технологий.
Это человек, который умеет смотреть на изменение не как на набор классов, таблиц и ендпоинтов, а как на изменение поведения всей системы.
И здесь, кстати, ИИ ничего принципиально не меняет. Он просто делает эту разницу заметнее.
Получить качественно написанную реализацию становится все дешевле.
А понять, какую реализацию вообще можно считать правильной, по-прежнему сложно.
Поэтому одна из самых ценных инженерных привычек сейчас - после вопроса:
"Как это реализовать?"
научиться автоматически задавать второй:
Что после этого изменится в системе и что может пойти не так?"
Вот где, на мой взгляд, разработка заканчивается как просто производство кода и начинается инженерия.