Зачем учить алгоритмы?
Когда разработчик учится решать алгоритмические задачи? Чаще всего, это происходит или в самом начале пути, или при подготовке к собеседованию. В начале пути задача на выбор оптимальной структуры данных, разработку и оценку сложности алгоритма помогает изменить мыслительные привычки — перейти от выражения мыслей на естественном языке с массой неточностей к однозначному изложению на языке программирования. Алгоритмическая задача позволяет не перегружать разработчика деталями какой-то предметной области и сосредоточиться на обработке данных. Идеальный тренажер мышления без привязки к бизнес смыслам с их неточностями и противоречиями.
Насчет подготовки к собеседованиям популярны 2 позиции. Одни говорят, что после собеседования алгоритмы почти никогда не применяются годами, а человек, легко решающий алгоритмические задачи, ничем не лучше других в решении бизнес задач.
Другие считают, что алгоритмы это база, без которой у разработчика нет навыков решения сложных проблем. А секцию алгоритмов при найме считают идеальной проверкой всех ключевых умений программиста.
В этой статье хочу поделиться своим взглядом на вопрос, зачем стоит или не стоит прокачивать знание алгоритмов. Попробую взвешенно посмотреть на алгоритмическую задачу, как способ проверки нужных в практической работе навыков.
Разберу несколько навыков. По каждому поставлю оценку по шкале от 0 до 3. 0 — задача не проверяет навык. 1 — скорее не проверяет. 2 — скорее проверяет. 3 — проверяет.
Сбор требований
При решении алгоритмической задачи важно быть внимательным к деталям требований. Нередко ключ к оптимальному решению — какое-то ограничение входных данных или приведенный пример данных.
Но такая проверка работы с требованиями оторвана от практики. Во-первых, нет связи с предметной областью, из которой могут прийти нечеткие или противоречивые требования. Во-вторых, обычно не указано распределение значений входных данных, как будто оно равномерное. Поэтому, оценка — 1.
Проектирование
На мой взгляд, ключевой этап в решении таски на алгоритмы. Конечно, тут нет никаких архитектурных паттернов, но для этого есть секция системного дизайна. На секции алгоритмов проверяется, как разработчик перебирает возможные решения задачи, в какой момент останавливается, как учитывает подсказки. Проверяется, как перебираются и комбинируются типовые приемы обработки данных. Проверяется понимание работы основных структур данных. Ну и, конечно, сравнение разных вариантов решения по временной и пространственной сложности. Оценка — 2. Почему не 3? Мало вариантов решения. В задачах средней сложности часто их 2 или 3. В реальных задачах приходится выбирать из большего множества вариантов.
Организация кода
Что важно при написании небольшого блока кода? Например, дать переменным понятные названия. На алгоритмическом интервью нет времени продумать названия переменных. Ведь, после написания кода его еще нужно в блокноте протестировать, учесть замечания интервьюера. Стоит заложить время на возможный фикс ошибок. Может быть, впереди еще задачи или две. Думать про имена переменных некогда. Тем более, в реальных задачах качество имени оценивается с точки зрения а) контекста кода и б) принятых в команде стандартов кодирования. Умение декомпозировать код на функции? Тоже не проверяется, потому что обычно решение это небольшой блок кода.
Умение упростить небольшой блок кода внутри одной функции? Избежать лишней вложенности, которую трудно читать. Проверять условия в таком порядке, чтобы код было проще читать. Пожалуй, это проверяется через оценку сложности алгоритма. Чем проще код, тем легче посчитать его сложность. Если же алгоритм оптимальный, но написан излишне сложно, то есть риск вообще не суметь посчитать сложность алгоритма. Оценка — 2. Почему 2, а не 1? Если человек может выбрать краткий и легкий для понимания вариант кода, то с именами переменных и декомпозицией методов он, скорее всего, справится. Но это неточно. Поэтому не 3.
Понимание кода
Что такое баг? Это отличие между тем, как разработчик понимает логику кода, и самой логикой. Для разработчика крайне важно уметь определять, когда он не полностью понимает код. Как проверяется понимание кода? Без понимания не получится объяснить, что написанный алгоритм всегда решает поставленную задачу. Без хорошего понимания кода не получится оценить его сложность. Оценка — 3.
Тестирование
Составить качественный набор тесткейсов, чтобы проверить все строки кода, все граничные случаи, потребление памяти и скорость работы — отдельное ремесло. На мой взгляд, это проверяется заданием, где нужно на уже готовый код перечислить сценарии тестирования.
В задаче на алгоритм проверяется скорее умение оперировать числами, значениями переменных в уме. То есть, выполнять функцию отладчика. Не очень то практический навык. Но важен другой момент — проверка памяти, концентрации внимания, скорости мышления. От этого зависит время, за которой человек протестирует написанный в блокноте код.
Умение составлять тест кейсы проверяется, разве что, в части крайних, граничных случаев, которые помогают оценить худшее время работы алгоритма. Моя оценка — 1.
Планирование времени
С одной стороны, проверяется в миниатюре. Если задача решается на собеседовании, то приходится, помимо решения проблемы, держать в голове, что впереди еще написание кода, тестирование, обсуждение, возможно, правки. Может быть, другие задачи. Исходя из этого стоит принимать решение, когда попросить подсказку или оставить в стороне рефакторинг кода. В противном случае, можно много времени провести за обдумыванием разных способов решения и не продемонстрировать вообще никакие свои навыки.
С другой стороны, как умение распределить время в крохотной задаче на полчаса или час соотносится с умением планировать труд на неделю-две? Наверное, никак. Плюс, в реальных задачах планирования хорошая практика — после составления плана взять паузу и еще раз пересмотреть его на свежую голову. Оценка — 0.
Решение проблем в диалоге
Во-первых, конечно, написанный код нужно уметь объяснить. Почему он оптимальный и почему работает во всех случаях, а не только на одном примере.
Во-вторых, если вы прочитали условие задачи и сразу не вспомнили нужный прием решения, то стоит подстраховаться и проговаривать те варианты решения и трудности, которые обдумываете. Это, как раз, моделирование реальной работы, когда вы ищете решение проблемы в диалоге с коллегой. Иногда, чтобы паззл решения сложился, достаточно изложить свои мысли другому человеку. И недостающий элемент паззла находится легко.
Кроме того, подсказка на алгоритмическом интервью помогает вам продемонстрировать свои навыки программирования, когда задача в изначальном виде оказалось неподъемной. В момент подсказки проверяется внимание к деталям и умение переключить контекст внимания. Будет человек упорно добивать начатое решение, которое никак не складывается, или сделает шаг назад и посмотрит на проблему с другой стороны. Оценка — 3.
Умение учиться
Проверяется косвенно. Если человек хорошо решает задачи на алгоритмы, значит, есть интерес к деталям, умение погрузиться в детали, умение разбираться в сложных конструкциях. С таким же успехом, можно на собеседовании спрашивать про внутреннее устройство баз данных или какого-то фреймворка. Но сложно сделать стандартным процесс отбора, так как баз данных и фреймворков очень много, они эволюционируют. Какие-то еще и устаревают. А вот теория алгоритмов обновляется медленно. Плюс, новые алгоритмы не делают старые неактуальными. Алгоритмы — универсальная тема, на которую можно один раз настроить процесс найма и повторять его очень долго. Оценка — 2. Почему не 3? Потому что теорию алгоритмов можно освоить один раз и потом долго не тренировать умение учиться.
Итоги
Навык | Оценка |
Сбор требований | 1 |
Проектирование | 2 |
Организация кода | 2 |
Понимание кода | 3 |
Тестирование | 1 |
Планирование времени | 0 |
Решение проблем в диалоге | 3 |
Умение учиться | 2 |
Все описанные проверки навыков на алгоритмической задачи работают лишь при условии, что у человека есть нужна алгоритмическая подготовка. Прочитаны книги по алгоритмам и натренировано умение видеть в задачах типовые структуры данных и типовые приемы их обработки.
Если такой подготовки нет, то человек может обладать нужными в работе навыками, но, просто, не сможет продемонстрировать их на алгоритмическом собеседовании.
Наверное, можно сравнить со знанием языка. Если специалист не знает язык, то это не обесценивает его, как специалиста. Просто, проверить профессиональные умения сложнее.
Заключение
Лично у меня алгоритмы долгое время были слабой стороной. Какое-то время назад решил закрыть этот пробел в своем образовании. Отчасти, из-за интереса к теме. Отчасти, из-за понимания, что могу захотеть поработать в компании, которая проверяет алгоритмы на собеседованиях. Размышлял о практической пользе прочитанных книг и сотен решенных задач. Так получилась эта статья.
Желаю всем, чтобы интерес к предмету всегда сочетался с пониманием практической пользы. Спасибо, что прочитали мою первую статью.
Приглашаю вас на мой личный канал о программировании.