«Напишите функцию Python, которая принимает положительное целое число и возвращает массив простых множителей этого целого числа».

def prime_factors(n):
    i = 2
    factors = []
    while i * i <= n:
        if n % i:
            i += 1
        else:
            n //= i
            factors.append(i)
    if n > 1:
        factors.append(n)

    return factors

ChatGPT написал эту программу. Обратите внимание, что при поиске факторов программа останавливается на квадратном корне из N, а не на самом N. Впечатляющий.

Для некоторых это открытое приглашение к плагиату и катастрофа для образования в области компьютерных наук (и образования в целом). Единственное решение, по-видимому, состоит в том, чтобы заставить учащихся выполнять свою работу в классе, где мы можем бдительно и недоверчиво наблюдать за ними. Мы могли бы также потребовать, чтобы они писали свой код карандашом и бумагой, и сделать все уроки программирования такими же жалкими и безрадостными, как AP.

Чтобы получать удовольствие от программирования, нужно уметь делать перерывы, бегать, играть с собакой, есть с друзьями, думать о других вещах. А затем, когда ответ придет к вам, как раз когда вы засыпаете, вы должны быть в состоянии вскочить с кровати и написать код. Если мы не собираемся этого допускать, мы могли бы также отказаться от идеи преподавания программирования в виде оцениваемого курса за кредит. (Что на самом деле имеет некоторые достоинства.)

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

Вышеупомянутая задача программирования — найти простые множители положительного целого числа — это первая программа, которую я написал. Это было задание от мистера Пэрриса, моего учителя математики в 10-м классе. Я написал его на Бейсике на школьном PDP-11. И мне это понравилось. Я не могу сказать вам, как долго я просидел у терминала, потому что я был поглощен… вневременным состоянием «потока» Чиксентмихайи… когда я прорабатывал логику. Я уверен, что редактировал и запускал программу десятки раз, прежде чем она заработала.

Несмотря на влияние, которое это задание оказало на меня, я больше не программировал до окончания колледжа. Но в конце концов я вернулся в свою школу, чтобы преподавать информатику (в той же компьютерной лаборатории, где терминалы PDP-11 были заменены компьютерами Mac), и одним из моих первых заданий была программа основных факторов. Большинство курсов по программированию, которые я видел, не переходят сразу к этому. Они заставляют учеников написать «Hello, World!» и другие однострочные упражнения по синтаксису, такие как добавление чисел, использование слов с заглавными буквами, вставка и удаление чисел из массивов и другие неконтекстуализированные задачи, которые можно было бы выполнить быстрее с карандашом и бумагой.

Я не верю в это. Цель программирования компьютеров состоит в том, чтобы делать то, что невозможно без них, и просто скучно писать программы, которые делают тривиальные вещи. С первого дня цель должна состоять в том, чтобы заставить процессор выполнять какую-то настоящую работу.

Достойные задания по программированию

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

Я никогда не видел, чтобы ученик заработал с Prime Factors и не начал вводить все большие и большие числа, чтобы посмотреть, что произойдет. Неизбежно, если они вводят очень большое простое число и ничего не происходит, они думают, что их программа каким-то образом содержит ошибки.

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

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

Но они делают это в контексте Школьной игры, которую они практиковали и освоили с дошкольного возраста: взрослые говорят вам, что делать, они говорят вам, как это делать, а затем вознаграждают вас за выполнение того, что они просили.

Программирование другое. Программирование — это не следование инструкциям, а написание инструкций. Речь идет о «знании того, что делать, когда вы не знаете, что делать». И по моему опыту, большинство студентов, особенно те, кто лучше всех освоил Игру, борются с этим.

Не все из них, конечно. У меня были ученики, которые, как и я, занялись программированием и делали удивительные вещи. Но эти дети, вероятно, все равно собирались научиться программировать; все, что я сделал, это дал им первый толчок. Дети, которым я хотел помочь, были теми, кто не воспринимал это естественным образом, кто боролся на каждом этапе пути. Я хочу подарить этим детям возможность программировать.

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

Но у этой веры есть коварный побочный эффект, заключающийся в том, что мы склонны отказываться от других. У меня был коллега, который в первый день занятий использовал сложные логические головоломки, чтобы отсеять непригодных. Если цель состоит в том, чтобы подтолкнуть студентов к получению докторской степени в области компьютерных наук, то, возможно, есть аргумент в пользу того, чтобы избавить других от многих страданий. Но я не думаю, что именно поэтому мы должны учить программированию или почему люди должны учиться программировать.

Искусство программирования заключается не только в изучении синтаксиса определенного языка. Это установка на эксперименты, детективную работу и готовность двигаться вперед, даже если мы не уверены в правильности пути. Это установка не только на то, чтобы получить правильный ответ и двигаться дальше, но и на неустанное стремление к совершенствованию даже после того, как у нас есть ответ.

То, что делают программисты… замечают, когда что-то не так, задаются вопросом о причинах, экспериментируют с решениями… полезно в любой области. Это правда, что можно обойтись и даже добиться успеха, следуя инструкциям: предприятия вкладывают огромные ресурсы в то, чтобы организация могла продолжать работать, даже если большинство ее сотрудников просто следуют инструкциям. Но будь вы упаковщиком коробок с Amazon, финансистом с Уолл-стрит, скульптором, солдатом или кем-то еще, если вы разовьете в себе привычку спрашивать «почему», верить, что сможете найти ответ, и знать, что делать, даже если не знаете, что делать. Если вы не знаете, что делать, у вас больше шансов не только преуспеть в своей работе, но и получить от нее большее удовлетворение.

Вот почему я считаю, что каждый должен научиться программировать.

Однако в то же время мы все еще не можем решить проблему, заключающуюся в том, что для многих людей программирование просто…сложно. Действительно трудно. Это требует своего рода мышления и решения проблем, которые мы почти никогда не делаем, от чего школьная и рабочая среда была создана, чтобы защитить нас, возможно, чтобы мы не потерпели неудачу. Начиная с начальной школы, мы учим их тому, что главный признак совершенства — это получение правильного ответа с первой попытки. В программировании это не работает.

Первый реальный ключ к лучшему способу преподавания программирования, который я получил, хотя прошло двадцать лет, прежде чем я даже понял, что это такой важный ключ, пришел от студентки по имени Меган. Однажды в классе Меган попросила о помощи, и, прежде чем я успел даже сесть, она твердо сказала: «Я собираюсь описать проблему, и я хочу, чтобы вы молчали и ничего не говорили. Тогда я задам вам один вопрос, и я хочу, чтобы вы ответили на этот вопрос и ни на что другое».

Я сел, и она начала свое объяснение. Внезапно она прервала себя: «Ой, подождите! Я понял! Уходите! Уходи!», буквально отталкивая меня руками.

Я рассказывал эту историю годами, потому что Меган была потрясающей. Я гордился ее упорством и желанием решать проблемы самостоятельно, с минимальной помощью. «У вас есть только один шанс на всю жизнь для каждой головоломки, так что не теряйте его, спрашивая ответ», — говорил я своим ученикам.

Но два десятилетия спустя, имея больше доказательств для анализа, я понял более глубокий смысл этого обмена мнениями, который заключался в том, что Меган нашла свое собственное решение, просто четко объяснив проблему. Я очень медленно соображал, когда увидел этот паттерн… ирония судьбы для человека, который гордится распознаванием паттернов… но когда я, наконец, заметил его, я слегка изменил свое учение. Раньше, когда студент просил о помощи, мой подход заключался в том, чтобы выяснить для себя, что не так с его кодом, а затем задавать наводящие вопросы до тех пор, пока он не увидит его. Иногда мои намеки становились настолько точечными, что учащиеся никогда не находили их сами, и возможность обучения терялась.

Мой новый подход заключался в том, чтобы попросить их объяснить, что происходит, но настаивать на абсолютной, недвусмысленной ясности. Никаких местоимений, особенно с двусмысленными антецедентами, никакого использования слова «вещь», никаких расплывчатых объяснений, которые я принимаю, потому что знаю, о чем они думают. Они должны сказать это на самом деле.

Делая это, я заметил две вещи:

  1. Четкое вербальное выражение — это своего рода промежуточная точка или мост между идеями и кодом. Если борющиеся новички могут сначала перевести свои мысли на английский (или, предположительно, любой разговорный язык), им будет намного легче преобразовать эти идеи в компьютерный код.
  2. Для многих учеников даже этот первый шаг очень, очень труден.

Кажется, что многим из этих студентов нужно не больше объяснений синтаксиса, а скорее простая практика организации своих мыслей кратким, ясным языком.

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

Ресурсы

Для всех учителей, заинтересованных в том, чтобы попробовать эту методологию, есть два замечательных (и бесплатных!) ресурса, которые я использую при обучении таким образом:

projecteuler.net содержит сотни задач по математическому программированию, от простых разминок до очень сложных.

Google Colaboratory — это дополнение к Google Диску, основанное на блокнотах Jupyter (которые я изначально использовал), позволяющее учащимся чередовать код с форматированным текстом и графикой, а также делиться своей работой напрямую с учителем. Затем учитель может комментировать прямо в записной книжке, а учащийся может вносить изменения, без отправки нескольких версий по электронной почте.

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

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

В самый первый раз, когда мы попробовали это, я получил заявку от ученицы, которая боролась и явно уже рассказывала себе историю о том, что она «не очень хороша в этом». Ее дневник начинался примерно так:

Я понятия не имею, что делаю, и я совершенно потерян, но мистер Ри говорит, что все, что мне нужно делать, это делать ошибки и писать о них, чтобы получить хорошую оценку, и я могу, по крайней мере, сделать это.

Затем она предприняла нерешительную попытку написать цикл и написала:

Ну, это вообще не работает. Я думал, что все, что мне нужно сделать, это каждый раз добавлять 1 к x, но он говорит, что x не определено. Хм. Может быть, я должен был сказать, что такое x…”

А потом она просто продолжала, несколько раз пренебрежительно комментируя свое понимание и способности, но затем говоря: «О, подождите, может быть…» и добившись небольшого прогресса. Шаг за мучительным шагом она в конце концов добралась до конца. Ее программа сработала; она решила проблему.

Ясно, что мы были на что-то.

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

Однако на моих уроках информатики комментарии в студенческих журналах были, по сути, метакогнитивными размышлениями, но в более органичной, менее искусственной форме. Это было и более своевременно, поскольку было написано во время работы, а не позже в тот же день, и более характерно для их работы.

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

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

Когда я начал использовать этот новый подход, один коллега (большой поклонник AP) сказал, что вы не можете использовать задачи с projecteuler.net, потому что решения этих задач есть по всему Интернету, и студенты могут просто найти ответы в Google. Но даже если кто-то искал ответ на проблему, это не дает ему повествования о своем путешествии. И если кто-то хочет пройти через все трудности, притворяясь решением проблемы, изобретая ошибки и описывая их с правдоподобными подробностями, что ж, это, вероятно, все еще хороший опыт обучения.

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

Но не было необходимости спорить со студентом о том, плагиат он или нет. Неспособность задокументировать свои мысли, большой необъяснимый скачок привели к более низкой оценке, и в зависимости от того, что еще было в их журнале, это могла быть очень низкая или неудовлетворительная оценка. Это случалось редко и никогда дважды от одного и того же ученика.

Что возвращает нас к «проблеме» ChatGPT и почему я считаю, что это не проблема, а возможность. Есть лучший способ преподавать программирование, чем просить студентов сдать отполированные программы, и поскольку этот способ в значительной степени защищен от плагиата, возможно, кризис, вызванный ChatGPT, вдохновит больше учителей попробовать его.