Каждые несколько лет инструменты полностью меняются, и каждые несколько лет один и тот же небольшой набор идей снова объясняет, что пошло не так.
Проблема периода полураспада
Технические знания устаревают неравномерно, и эта разница — самое полезное, что организация может понять об обучении своих инженеров.
Знание фреймворков и библиотек устаревает быстро. Приём, привязанный к конкретной версии, часто теряет актуальность за несколько лет, а иногда и раньше. Знание платформ и вендоров устаревает почти так же быстро, а конкретные команды и интерфейсы меняются постоянно.
Под этим лежит слой, который почти не сдвинулся с места. Как компьютер выполняет инструкции. Сколько стоит структура данных. Почему одни алгоритмы масштабируются, а другие нет. Что операционная система делает с памятью и с ожиданием. Как сеть на самом деле доставляет сообщение.
Обучать людей только быстро устаревающему слою — значит переобучать их каждые три года, постоянно.
Это не аргумент против практического обучения. Это аргумент о пропорции. Большая часть корпоративного технического развития щедро тратится на слой с самым коротким сроком жизни и почти ничего не идёт на слой, который делает следующий инструмент осваиваемым за неделю, а не за квартал.
Что охватывает направление
Область: алгоритмы, структуры данных, операционные системы, сети и вычисления.
Четыре области.
Алгоритмы и структуры данных. Сколько стоят операции, какая структура подходит под какой паттерн доступа и как рассуждать о масштабе.
Системы. Процессы, память, планирование, файлы и абстракции, скрывающие железо.
Сети. Как перемещаются данные, что может пойти не так и почему распределённые системы сложны особым образом.
Теория вычислений. Что вычислимо, что практически разрешимо и где проходят жёсткие пределы.
Сложность — единственная идея, которая окупает себя сама
Если организация преподаёт из этого направления только одно понятие, это должно быть оно.
Алгоритмическая сложность описывает, как растёт объём работы алгоритма с ростом входных данных. Это различие не академическое. Это разница между кодом, который работает на тестах, и кодом, который отказывает в продакшене.
Три практических следствия.
Тестовые данные скрывают проблему. Алгоритм, чья работа растёт как квадрат входных данных, выглядит нормально на тысяче записей и становится непригодным на миллионе. Отказ — не баг, появившийся позже. Он был там с первой строки и был невидим на тестовом масштабе.
Вложенный цикл по базе данных — самая частая дорогая ошибка в коммерческом ПО. Запрос внутри цикла, где каждая итерация делает собственный round trip, приемлемо работает на нескольких элементах и рушится на реальном объёме. Этот паттерн встречается постоянно, на любом языке, у людей с многолетним опытом — потому что им никто не показал, как его увидеть.
Выбор правильной структуры обычно даёт больший выигрыш, чем оптимизация кода. Поиск в списке означает перебор каждого элемента. Поиск в хеш-таблице происходит практически мгновенно независимо от размера. Изменить одну строку выгоднее, чем переписать сотню.
Ничего из этого не требует математической изощрённости. Требуется привычка спрашивать, что произойдёт, когда это станет в десять раз больше, а этой привычке можно быстро научить людей, которые уже пишут код.
Что на самом деле делает операционная система
Слой, который большинство практикующих разработчиков считают невидимым, и откуда берётся на удивление большая доля проблем в продакшене.
Память. Как работает выделение памяти, во что обходится сборка мусора и когда она делает паузы, почему локальность памяти влияет на скорость сильнее, чем количество инструкций, и что на самом деле происходит, когда процессу не хватает доступной памяти. Проблемы с памятью — одни из самых трудных производственных сбоев для диагностики без этой картины.
Процессы и потоки. Что означает изоляция, во что обходится переключение контекста и почему добавление потоков сверх определённого предела замедляет систему, а не ускоряет.
Ввод и вывод. Причина, по которой большинство приложений скорее ждут, чем вычисляют. Операции с диском и сетью на порядки медленнее доступа к памяти, поэтому и существуют асинхронные и неблокирующие подходы. Инженеры, не усвоившие это, оптимизируют вычисления в программах, которые всю жизнь проводят в ожидании.
Конкурентность. Гонки данных, взаимные блокировки и тот факт, что операции, выглядящие атомарными в исходном коде, таковыми не являются. Это категория багов, которая проходит все тесты и отказывает в продакшене под нагрузкой, и рассуждать о ней без этой модели невозможно.
Где это находится в домене
Компьютерные науки — первое из восьми направлений в домене ИИ, данных и вычислений Astra Trainer, и оно лежит под всеми остальными. Программная инженерия, наука о данных, облако и DevOps, кибербезопасность и машинное обучение — все опираются на одни и те же вычислительные идеи, и люди, владеющие ими, быстрее осваивают каждый новый слой.
Оно теснее всего связано с программной инженерией, где этот материал применяется в коммерческих условиях, и с ИТ-системами и компьютерными сетями, где слои операционной системы и сети — повседневная работа. Восемь направлений можно посмотреть здесь.
Почему это важно сейчас больше, а не меньше
Распространённое предположение — что инструменты генерации кода делают основы ненужными. Обратный аргумент сильнее, и он строится на том, во что превращается сама работа.
Работа сдвигается от написания к оценке. Проверка чужого кода и решение, корректен ли он, требует больше понимания, чем его создание, а не меньше. Правдоподобно выглядящая функция с неверными характеристиками сложности — именно то, что проходит поверхностное ревью и отказывает на масштабе.
Сгенерированный код уверен в своей производительности так, как не может обосновать. Он не знает ваших объёмов данных, паттернов доступа или бюджета задержки. Кто-то должен это знать.
Отладка остаётся самой сложной частью. Когда система ведёт себя неожиданно в продакшене, вопрос в том, что на самом деле происходит, и ответ на него даёт модель работы машины.
Архитектурные решения не автозаполняются. Выбор между согласованностью и доступностью, решение, что кешировать, суждение о том, где провести границу, — это решения, определяющие, выживет ли система, и все они относятся к основам.
Честная формулировка в том, что эти инструменты поднимают минимальную планку по производству кода и повышают ценность способности его оценивать. Организации, которые прочитали только первую половину, а не вторую, выяснят, какая из них была у них на самом деле.
Роли, поимённо
Инженеры-программисты на любом уровне, поскольку это субстрат.
Системные инженеры и системные программисты.
Инженеры по производительности — отдельная специализация, стабильно дефицитная.
Инженеры распределённых систем.
Инженеры компиляторов и рантаймов.
Инженеры баз данных, где встречаются структуры данных и хранение.
Исследователи безопасности, чья работа зависит от понимания того, что машина реально делает, а не того, что говорит исходный код.
Технические архитекторы, принимающие решения, для которых этот материал даёт основу.
Research-инженеры в системах машинного обучения, где эффективность на масштабе — вся суть проблемы.
Кого можно обучить этому
Самоучки-разработчики и выпускники буткемпов. Самая большая и благодарная группа. У них часто сильные практические навыки, хорошие привычки в инструментах и реальный опыт поставки — с конкретным пробелом именно здесь. Закрыть его — определённая, ограниченная задача, а не общая программа повышения квалификации, и эффект на их потолок огромен.
Аналитики и специалисты по данным. В производительность и масштаб, где запросы и пайплайны, работающие на выборках, отказывают на полных данных именно по этим причинам.
ИТ- и системные администраторы. Уже обладая знанием операционных систем и сетей с операционной стороны, им нужен слой программирования.
Инженеры из других дисциплин. Выпускники математики, физики и инженерных специальностей хорошо конвертируются, поскольку стиль рассуждений переносится.
Специалисты по контролю качества и тестированию. В инженерные роли, обладая сильным чутьём на то, как вещи ломаются.
Инженеры поддержки. В разработку, с реальным знанием того, что ломается в продакшене и почему.
Об основах и найме. Алгоритмические собеседования широко используются и широко критикуются как фильтр найма, и результат на них несовершенно коррелирует с результатом на работе. Это направление существует, чтобы сделать людей лучше в построении и диагностике систем, а не чтобы оптимизировать под формат собеседования. Организациям, использующим этот материал, стоит ясно понимать, какую из этих двух задач они решают, потому что обучение, полезное для одной, не обязательно полезно для другой.
Что важно вынести
Технические знания устаревают с разной скоростью, а большая часть бюджетов на обучение тратится на самый быстро устаревающий слой.
Сложность — самое ценное отдельное понятие, потому что оно предсказывает отказ на масштабе ещё до того, как код написан.
Большинство проблем с производительностью в продакшене — это проблемы памяти, ожидания или конкурентности, и все три живут в слое операционной системы, который большинство разработчиков считают невидимым.
Генерация кода повышает ценность суждения, а суждение здесь означает основы.
И больше всего выигрывают люди, которые уже пишут для вас код, — с пробелом, который конкретен, заметен и быстро закрывается.
Зачем преподавать основы, а не актуальные фреймворки?
Потому что знание фреймворков устаревает за несколько лет, а базовые вычислительные идеи держатся десятилетиями, и люди, владеющие основами, осваивают каждый новый фреймворк в разы быстрее.
Какое понятие полезнее всего одно?
Алгоритмическая сложность. Она объясняет, почему код, проходящий тесты, отказывает на продакшен-объёме, почему запрос внутри цикла рушится на реальных данных и почему выбор правильной структуры данных обычно выгоднее оптимизации кода.
Почему понятия операционной системы важны для прикладных разработчиков?
Потому что большинство проблем с производительностью в продакшене — это проблемы памяти, ввода-вывода или конкурентности. Приложения обычно проводят время в ожидании, а не в вычислениях, и оптимизация вычислений в программе, которая ждёт, ничего не даёт.
Делают ли инструменты генерации кода основы менее важными?
Наоборот, они делают их важнее. Работа сдвигается от написания кода к оценке чужого кода, а сгенерированный код не может знать ваши объёмы данных, паттерны доступа или бюджет задержки.
Кто выигрывает от этого обучения больше всего?
Самоучки-разработчики и выпускники буткемпов, у которых часто есть сильные практические навыки и конкретный, легко закрываемый пробел именно здесь, затем аналитики данных, упирающиеся в проблемы масштаба, и системные администраторы, переходящие в разработку.
