Краткий пересказ моего сегодняшнего выступления на кухне за чаем по поводу преподавания программирования.
Самое сложное — научить человека мыслить алгоритмически. «Мыслить алгоритмически» означает понимать, какие операции являются атомарными, простейшими, и уметь представлять процесс в виде последовательности этих операций. Простой пример: как найти максимальный элемент в последовательности? Если человек сможет формализовать этот процесс («запомним первый элемент, начнём перебирать остальные по одному, если увидим, что какой-то элемент больше того, что мы запомнили — запомним этот новый элемент вместо старого») — первый и самый главный шаг сделан. Если человек не умеет делать этого, идти дальше нельзя.
После того, как первый шаг пройден, можно перейти к следующему, а именно, к записи алгоритмов на языке
программирования. Вопрос о том, какой язык должен быть первым, весьма и весьма сложен. Я последние
три года склоняюсь к тому, что первым (и единственным на первое время) языком должен быть C, но против
этой точки зрения выступает чрезмерная для начинающих сложность: практически сразу нужно говорить об
указателях, хотя бы для того, чтобы объяснить функцию scanf()
и нормально объяснить, что
такое массивы. Сама идея косвенной адресации, как ни странно, вызывает огромное количество проблем
у начинающих, но способа обойти рассказ об указателях в самом начале я не знаю. Конечно, можно сказать,
что амперсанд в scanf()
нужно ставить, «потому что так надо, потом вы это поймёте»,
но это получится какой-то детсад, а не обучение программированию.
Предположим, что человек научился писать функцию main()
и знает основные конструкции
языка: if
, while
, for
и т.п. Следующей проблемой является
отладка кода. Как пишут код начинающие? Пишется пол-экрана текста, запускается. Если компиляция
прошла успешно, то либо выдаётся неверный результат, либо, ещё хуже, ошибка времени выполнения.
Что же происходит дальше? А дальше студент открывает файл с кодом и начинает искать ошибку
«методом пристального вглядывания». Иногда даже находит.
Вообще говоря, для оптимизации процесса отладки давно придумали дебаггеры. Сейчас я скажу вещь, которая
многим покажется кощунственной: я не считаю, что отладке при помощи специальных средств надо учить
сразу и в обязательном порядке. Причина проста: отладка кода дебаггером — это чертовски
сложно. Чего стоит хотя бы запоминание, что означает каждая из пяти используемых горячих клавиш или,
ещё хуже, команд gdb
. Итак, попробуем обойтись без помощи отладчика. Нет, конечно,
интересующимся товарищам мы покажем, что такое F10 и F11, но не всем и не в обязательном порядке.
Большинство студентов должно пойти другим путём.
Что же у нас остаётся? У нас остаётся функция printf()
, которой обычно вполне достаточно для
того, чтобы отлаживать программы, написанные начинающим студентом. К проверке программы при помощи
отладочных выводов студентов надо безжалостно приучать. Логика — примерно как при использовании
assert()
, но проще: «Что делает этот цикл? Считает длину строки? То есть, переменная
n
после цикла равна длине строки? Давай её здесь выведем. Ой, получилось –5764365? Подумай,
почему. Ага, забыли обнулить её перед циклом...» Так и только так.
Идеальными учебными программами для начинающих являются стандартные алгоритмы: поиск, сортировки и прочие.
Если человек осмыслит и напишет пирамидальную сортировку, он уж точно поймёт и запомнит, какие
индексы у элементов массива int A[N]
и чем чревато обращение к элементу за пределами
массива. Хотелось бы уметь придумывать задачи так, чтобы они были интересными сами по себе. Я стараюсь,
но не уверен, что получается то, что нужно.
Ну и наконец — вопрос, который меня последнее время интересует. Очень хочу попробовать поучить кого-нибудь программированию, начав на функциональном языке. На том же Лиспе, например. Просто интересно посмотреть, как потом просвещённый человек будет писать код на императивном языке. Просто интересно, да.