Все записи

/add, [601]

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

Самое сложное — научить человека мыслить алгоритмически. «Мыслить алгоритмически» означает понимать, какие операции являются атомарными, простейшими, и уметь представлять процесс в виде последовательности этих операций. Простой пример: как найти максимальный элемент в последовательности? Если человек сможет формализовать этот процесс («запомним первый элемент, начнём перебирать остальные по одному, если увидим, что какой-то элемент больше того, что мы запомнили — запомним этот новый элемент вместо старого») — первый и самый главный шаг сделан. Если человек не умеет делать этого, идти дальше нельзя.

После того, как первый шаг пройден, можно перейти к следующему, а именно, к записи алгоритмов на языке программирования. Вопрос о том, какой язык должен быть первым, весьма и весьма сложен. Я последние три года склоняюсь к тому, что первым (и единственным на первое время) языком должен быть C, но против этой точки зрения выступает чрезмерная для начинающих сложность: практически сразу нужно говорить об указателях, хотя бы для того, чтобы объяснить функцию scanf() и нормально объяснить, что такое массивы. Сама идея косвенной адресации, как ни странно, вызывает огромное количество проблем у начинающих, но способа обойти рассказ об указателях в самом начале я не знаю. Конечно, можно сказать, что амперсанд в scanf() нужно ставить, «потому что так надо, потом вы это поймёте», но это получится какой-то детсад, а не обучение программированию.

Предположим, что человек научился писать функцию main() и знает основные конструкции языка: if, while, for и т.п. Следующей проблемой является отладка кода. Как пишут код начинающие? Пишется пол-экрана текста, запускается. Если компиляция прошла успешно, то либо выдаётся неверный результат, либо, ещё хуже, ошибка времени выполнения. Что же происходит дальше? А дальше студент открывает файл с кодом и начинает искать ошибку «методом пристального вглядывания». Иногда даже находит.

Вообще говоря, для оптимизации процесса отладки давно придумали дебаггеры. Сейчас я скажу вещь, которая многим покажется кощунственной: я не считаю, что отладке при помощи специальных средств надо учить сразу и в обязательном порядке. Причина проста: отладка кода дебаггером — это чертовски сложно. Чего стоит хотя бы запоминание, что означает каждая из пяти используемых горячих клавиш или, ещё хуже, команд gdb. Итак, попробуем обойтись без помощи отладчика. Нет, конечно, интересующимся товарищам мы покажем, что такое F10 и F11, но не всем и не в обязательном порядке. Большинство студентов должно пойти другим путём.

Что же у нас остаётся? У нас остаётся функция printf(), которой обычно вполне достаточно для того, чтобы отлаживать программы, написанные начинающим студентом. К проверке программы при помощи отладочных выводов студентов надо безжалостно приучать. Логика — примерно как при использовании assert(), но проще: «Что делает этот цикл? Считает длину строки? То есть, переменная n после цикла равна длине строки? Давай её здесь выведем. Ой, получилось –5764365? Подумай, почему. Ага, забыли обнулить её перед циклом...» Так и только так.

Идеальными учебными программами для начинающих являются стандартные алгоритмы: поиск, сортировки и прочие. Если человек осмыслит и напишет пирамидальную сортировку, он уж точно поймёт и запомнит, какие индексы у элементов массива int A[N] и чем чревато обращение к элементу за пределами массива. Хотелось бы уметь придумывать задачи так, чтобы они были интересными сами по себе. Я стараюсь, но не уверен, что получается то, что нужно.

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