Сложные простые задачи по программированию

Читать в полной версии →

У каждого из нас есть представления о том, как должно происходить обучение. Они основываются на нашем прошлом опыте, рассказах других людей и неких идеальных образах. Зачастую эти представления не совпадают с тем, как на самом деле работает механизм становления хорошего разработчика. Студенту может казаться, что его учат неправильно или грузят ненужными знаниями. Подобные ситуации случались с каждым в школе и в университете. Они встречаются и у нас на Хекслете. В этой статье я объясню некоторые теоретические основы процесса обучения, которые позволят по-другому взглянуть на происходящее вокруг. Это поможет качественнее учиться и проще справляться с трудностями.

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

В организации практических заданий существует две крайности. Первая — давать задания, которые решаются почти точным повторением кода из теории урока. Вторая — давать задания, которые требуют глубокого самостоятельного погружения в тему. Эти две крайности сами по себе встречаются редко, как правило конкретное задание находится где-то между. В одних школах ближе к одному краю, в других — к другому. Какой подход лучше? Где баланс?

Подписывайтесь на канал Кирилла Мокевнина в Telegram — чтобы узнать больше о программировании и профессиональном пути разработчика

У программирования есть одна отличительная черта, которая выделяет его среди привычных нам областей деятельности. Возьмём для примера повара. Хорошие повара много знают про продукты, про способы приготовления, хранения, про обеспечение нужных условий (гигиена, санитарные правила). Они эффективно орудуют ножом и выполняют любое действие во много раз быстрее, чем мы с вами. При этом большинство поваров — люди, которые используют готовые рецепты для приготовления чего-либо. И лишь небольшая их часть способна создавать новые блюда самостоятельно. Да и потребности в этом мало. Примерно такая же история и во многих других профессиях, где уровень принятия решений сильно ограничен. В таких местах действуют по заранее заготовленным инструкциям.


В программировании всё не так. Даже на самом базовом уровне программисты подобны поварам, которым нужно создавать свои собственные блюда, ориентируясь на вкусовые желания любителей поесть (заказчиков). Практически любой нетривиальный проект ежедневно сопровождается десятками принятых сложных решений: начиная от проектирования базы данных, заканчивая взаимодействием с системами оплаты (биллинг) и организацией интерфейсов. Всё это требует не только большого количества самых разнообразных знаний, но и способности синтезировать новое, находить простые пути решения сложных задач, справляться с техническими ограничениями, находить трудноотлавливаемые ошибки.

К этому невозможно подготовиться заранее, потратив кучу времени на обучение и набив руку. Почти каждая ситуация, с которой сталкивается программист, уникальна. Да, мы всё же стоим на плечах гигантов и используем готовые библиотеки и фреймворки, но это не освобождает программиста от реализации прикладной логики, которая будет делать то, что нужно именно нашему приложению. И чем больше приложение, тем сложнее реализация. Приходится учитывать огромное количество факторов, общаться со многими людьми и идти на компромиссы.

Читайте также: DevOps — что это такое и почему эти практики меняют мир разработки уже сейчас

В реальной жизни программист большую часть времени делает четыре вещи (если говорить только про кодинг):

Всё это имеет непосредственное отношение к тому, как происходит обучение. Задания, в которых надо повторять за учителем без приложения серьёзных усилий, создают ложное ощущение понимания происходящего. Как правило, после такого обучения у человека не получается ровным счётом ничего. Он чувствует это сам, особенно когда возникает задача сделать что-то самостоятельно и без указки. И, конечно же, такой подход не имеет ничего общего с реальным миром. К реальным проблемам такой человек не готов.

Почему же тогда такой способ довольно популярен? Хотя бы потому, что такое обучение легче продать и так проще удерживать людей (до определённого момента). Пользователи сами подсознательно ожидают, что им всё разжуют, ведь они заплатили деньги (и переубеждать их себе дороже, проще сразу дать ответ на все вопросы).

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

Вспомните школьных учителей. Кто дал больше всех знаний? Как отразилась строгость преподавателя на качестве вашей подготовки?

На Хекслете ежемесячно учатся многие тысячи людей. За годы образовательной деятельности у нас было много времени для анализа того, какие задания работают лучше или хуже, где тот баланс, который, с одной стороны, не убьёт мотивацию, а с другой, заставит человека поработать самостоятельно и научиться. И, кажется, мы его нашли (но ещё не везде внедрили, так как много контента).

Главный вывод, который мы сделали: уровень самостоятельности нужно поднимать постепенно (это не то же самое, что уровень сложности). Идеально, если начальное обучение построено максимально просто, в духе «повторяй за мной». Это придаст уверенности и заложит базу. На этом уровне идёт фокус на структуре и синтаксисе. Именно поэтому для совсем новичков мы сделали отдельный проект https://ru.code-basics.com. Короткие уроки, в каждом из которых даётся ровно одна мысль. Например, только вызову функций на Code-basics посвящено больше 6 уроков. Для человека, который только начал учить программирование, вызов f(10) и f(x + 5) — абсолютно разные вещи, которые нужно объяснять последовательно, давая возможность как можно чаще пробовать набирать простой код.

Тут нужно добавить, что обучение чему-то совершенно новому всегда отличается от расширения знаний в области, где уже есть некоторые знания. Так происходит, потому что у новичка в голове нет даже базовых моделей, которые бы помогли ориентироваться в пространстве. Например, когда новичок натыкается на ошибку, он может провести много времени, медитируя над ней, ожидая, что решение само придёт в голову. Опытный же разработчик начинает действовать сразу: он читает текст, вбивает его в гугл, ищет на стековерфлоу, включает режим отладки и добивается ответа не за счёт долгого думания, а за счёт проведения экспериментов и отладки.

На Хекслете уровень сложности заданий и самостоятельности уже начинает расти. С одной стороны, задания усложняются алгоритмически, требуют время на анализ и включение изобретательности. С другой – поощряют читать дополнительную литературу, использовать библиотеки и функции, примеры которых в курсах не разбирались (но в них всегда есть ссылки на документацию). Хотя технически в этих практиках нет ни новых концепций, ни нового синтаксиса. Их решение опирается на пройденную теорию. Именно здесь заканчивается изучение структуры языка и начинается прокачка мышления, формирование правильных моделей разрешения сложных ситуаций.

Дальше, в проектах, мы начинаем включать элементы из реального кодинга: самостоятельная работа с окружением, работа с GitHub, с системами сборки, зависимостями, командной строкой, проектированием архитектуры. Чем дальше по проектам, тем больше это заметно. В конце концов в последних проектах даются темы, которые в теории не разбирались вообще, но наши студенты уже готовы к этому (мы постепенно ведём к тому, что надо уметь работать самостоятельно) и, как правило, справляются хорошо.


Прямо сейчас эта идея полностью реализована в профессии PHP-программист. В JavaScript профессиях обновление произойдёт на днях. UPD: Профессии JavaScript уже обновили.

Этот подход базируется на нескольких важных предположениях:

Наша генеральная цель, помимо конкретных знаний, научить студента самостоятельно справляться с трудностями: гуглить, читать документацию, отлаживать (это целое искусство), смотреть исходники, анализировать тесты. Всё отражается на том, как мы структурируем практику и работаем с пользователями в комьюнити. Менторы Хекслета крайне редко дают прямой ответ на вопрос, так как это не помощь, а наоборот, вред для студента (хотя многие этого не понимают — опять же следствие отношения к школе, как к сервису). Это, кстати, не так просто, многие ожидают прямых ответов и очень раздражаются, когда с ними говорят «загадками». Единственный способ, который может это изменить – подобные статьи, которые объясняют принципы обучения.

Лёгкое (или тяжёлое) ощущение раздражения к учителю — это не просто нормально, но и скорее всего показатель, что всё идёт хорошо (кроме ситуаций, когда сам преподаватель вызывает неприятие в силу личных качеств). Обучение чему-то новому почти всегда болезненный процесс.

Несмотря на все вышесказанное, от ошибок не застрахован никто. Даже несмотря на наш обширный опыт офлайнового обучения, нам понадобилось много лет, перед тем как мы начали понимать эффективные стратегии обучения программированию онлайн. Более того, даже зная их, мы понимаем, что невозможно создать заранее хорошо спроектированный курс. Онлайн-аудитория, в отличие от студенческой скамьи, абсолютно непредсказуема. На ресурсах типа Хекслета учатся совершенно разные люди, имеющие разный опыт, уровень подготовки и отношение к процессу. Именно поэтому для нас так важна обратная связь. Конструктивная обратная связь — единственный способ понять, где мы ошиблись, не объяснили хорошо теорию, сделали упражнение слишком сложным или простым и так далее.

Выводы