Брет Виктор: обучаемое программирование (2012)

БретВикторобучаемоепрограммирование2012

Вот вопрос с подвохом: Как заставить людей понимать программирование?

Khan Academy недавно запустила онлайн-среду для обучения программированию. Он предлагает набор руководств, основанных на языках JavaScript и Обработки, и имеет среду «живого кодирования», в которой выходные данные программы обновляются по мере ввода программиста.

Поскольку моя работа была процитировал как источник вдохновения для системы Хана, я чувствовал, что должен ответить двумя мыслями об обучении:

  • Программирование – это образ мышления, а не механический навык. Изучение циклов for – это не обучение программированию, как и изучение карандашей – это обучение рисованию.
  • Люди понимают то, что они видят. Если программист не может видеть, что делает программа, он не может ее понять.

Таким образом, цели системы программирования должны быть:

  • для поддержки и поощрения мощного мышления
  • , чтобы программисты могли видеть и понимать выполнение f их программы

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

Алан Перлис писал: «Чтобы понять программу, вы должны стать одновременно машиной и программа. “ Это представление является ошибкой, и именно эта широко распространенная и опасная ошибка заставляет программировать сложное и непонятное искусство. Человек – не машина, и его не следует заставлять думать так же.

Как нам научить людей понимать программирование?

Меняем программирование. Мы превращаем его в то, что понятно людям.

Содержание

Концепция разделения системы между компьютером и головой была получена из мыслей Уилла Райта о игры .

Система программирования состоит из двух частей. «Среда» программирования – это часть, установленная на компьютере. «Язык» программирования – это часть, которая устанавливается в голове программиста.

Это эссе представляет собой набор принципов проектирования для среды и языка, подходящих для обучения.

Среда должна позволять учащемуся:

  • прочтите словарь — Что означают эти слова?
  • следовать за потоком – что происходит, когда?
  • увидеть состояние – что думает компьютер?
  • создать, реагируя – с чего-нибудь начать, потом лепить
  • создать путем абстрагирования – начать с конкретного, затем обобщить

язык должен содержать:

  • идентичность и метафора – как я могу связать компьютерный мир со своим?
  • разложение – как мне разбить свои мысли на кусочки размером с разум?
  • перекомпоновка – как склеить части вместе?
  • читаемость — Что означают эти слова?

В чертах не главное

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

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

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

Вот простая обучающая программа с которыми может столкнуться учащийся:

Для сравнения в приведенных здесь примерах будут использоваться те же языки, что и в системе Khan Academy, JavaScript и обработке.

Прежде чем читатель сможет понять этот код, прежде чем он сможет даже начать понять, как это работает, вот у нее возникнут вопросы:

Руководства Академии Хана побуждают учащихся отвечать на эти вопросы, произвольно изменяя числа. и пытается понять, что они делают.

Мысленный эксперимент. Представьте, что вы купили новую микроволновую печь, достали ее из коробки и обнаружили панель с немаркированными кнопками.

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

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

Сделайте смысл прозрачным

Обучение приготовлению пищи – это не угадывание функциональности кухонной техники. Речь идет о понимании того, как ингредиенты могут быть объединены.

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

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

Вот один пример того, как среда программирования может сделать смысл прозрачным, предоставляя метки при наведении курсора мыши:

Управляющие структуры могут быть также помечены.

Заманчиво думать об этом как о «встроенной справке», но это не помощь – это просто маркировка. Проблема со следующим пользовательским интерфейсом не в том, что в нем отсутствует «функция справки». Проблема в том, что ничего не помечено.

Этот интерфейс так же информативен, как и эта строка кода:

Почему мы считаем код приемлемым, а пользовательский интерфейс – нет? Почему мы ожидаем, что программисты будут «искать» функции в «документации», в то время как современные пользовательские интерфейсы спроектированы таким образом, что документация обычно не нужна?

Объясните в контексте

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

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

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

Такое соединение может быть особенно эффективным, когда строка кода выполняет несколько функций:

Резюме – Прочтите словарь

Приведенные здесь конкретные решения являются просто примерами. Важна основная цель: дать возможность учащемуся прочитать программу .

  • Среда должна делать смысл прозрачным , чтобы учащийся может сосредоточиться на концепциях высокого уровня, а не на словарном запасе.
  • Среда должна объясните в контексте . Показать и рассказать. Аннотируйте данные, а не только код.

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

An Среда, которая позволяет учащимся зацикливаться на этих вопросах, – это среда, которая препятствует учащимся даже начать работу.

Типичная среда живого кодирования представляет учащегося с кодом слева и выводом кода справа. При изменении кода вывод обновляется мгновенно.

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

Вы понимаете, как было приготовлено это суфле? Вы бы чувствовали себя готовыми создать его самостоятельно?

Конечно, нет. Вам нужно увидеть, как ингредиенты сочетаются. Вам необходимо увидеть шаги .

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

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

Сделайте поток осязаемым

Этот пример программы снова:

Это особенно трудный пример для новичка. Конструкция «for» с тремя операторами в одной строке заставляет поток управления причудливо прыгать и является излишне крутым введением в концепцию цикла.

Чтобы сделать поток более разумным для учащегося, цикл можно переписать, используя ” пока”:

Теперь поток управления должен быть выполнен заметный. Мы должны передать выполнение программы программисту, дать ему почувствовать, что это настоящая вещь , позволить ей владеть it.

В следующем примере программист использует ползунок для прокрутки выполнения:

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

Сделайте поток visible

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

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

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

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

Появляющиеся шаблоны особенно полезны при наличии условных выражений и других форм управления потоком:

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

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

Сделайте время осязаемым

Построчное выполнение – это очень детализированное представление времени. Программист также думает о времени с другой степенью детализации.

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

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

В следующем примере представлена ​​шкала времени для изучения выполнения построчно, и ползунок для покадрового просмотра.

Этот элемент управления позволяет программисту перемещаться вперед и назад во времени, изучать интересные кадры и сравнивать выполнение в разных кадрах.

Сделайте время видимым

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

Одна из самых глубоких и сильных идей в математике – это взаимосвязь между дифференциальными формулировками (такими как пошаговая инструкция). -шаговый процесс, как наша функция “рисования”) и его интегрированная форма (например, функция времени или график во времени). «Время выравнивания» позволяет учащемуся видеть процесс и его траекторию как два представления одного и того же и, таким образом, думать о них как о взаимозаменяемых.

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

Резюме – Следуй за потоком

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

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

Простая программа:

Третья строка объявляет переменную с именем «scaleFactor», которая изменяется с каждой итерацией цикла.

Посмотрите на эту строку и подумайте над этими вопросами:

  • Какие значения принимает scaleFactor? 1? 126? -1? pi / 2?
  • Что такое scaleFactor в начале цикла? В конце?
  • Как scaleFactor изменяется в ходе цикла? Линейно вверх? Линейно вниз? Изменения происходят быстрее или медленнее?

Подождите. Подождите минуту. Вы пытались ответить на эти вопросы, производя арифметические вычисления в уме? Компьютер каким-то образом нарисовал эту картинку, поэтому компьютер должен вычислить все эти scaleFactors сам. Вы серьезно пересчитываете их в уме?

Кроме установки «точки останова», которая похожа на мониторинг трафика на автострады, устроив баррикаду. Или писать в «консоль», что похоже на определение того, куда ваша собака идет в течение дня, следуя по следу помета.

Теперь представьте, зависел ли scaleFactor от некоторых других переменных. , или некоторые другие функции, или внешний вход. Не было бы способа легко ответить на эти вопросы.

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

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

Пионер информационного дизайна Эдвард Тафте имеет одно основное правило, и это правило должно быть принцип, лежащий в основе любой среды для создания или понимания.

Показать данные.

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

Показать данные

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

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

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

Однако все еще трудно ответить на третий вопрос. : как изменяется переменная? Какова форма его изменения? Вопрос трудный, потому что мы, опять же, заглядываем в маленькое отверстие, видя за раз только одну точку.

У Эдварда Тафте есть второе правило. Недостаточно просто показать данные. Мы должны показать сравнения .

Показать сравнения

Данным нужен контекст. Редко бывает достаточно увидеть изолированно одну точку данных. Мы понимаем данные, сравнивая их с другими данными.

В примерах временной шкалы до сих пор использовались точки для представления выполненных строк. Но вместо точек мы можем показывать данные. На следующей временной шкале показаны все факторы scaleFactors:

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

Линия «заливка» устанавливает цвет заливки. Этот цвет может быть показан.

«Треугольник» line рисует треугольник на холсте, вращается и раскрашивается. На временной шкале может отображаться эскиз каждого созданного треугольника.

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

В приведенном выше примере повторяется только двадцать раз. Можно ли понять цикл, состоящий, скажем, из тысяч итераций, не утопая в тысячах чисел?

Да, есть целая область исследований, посвященная изображению больших объемов номеров. Чтобы визуализировать эти данные, мы можем использовать все стандартные методы визуализации данных .

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

Устранение скрытого состояния

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

Строка «заполнения», с другой стороны, устанавливает цвет заливки для последующих операций рисования. Когда программист перемещается по этой линии, какой эффект она видит? Она видит ничего не происходит , потому что функция “заполнения” изменяет скрытое состояние .

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

Здесь есть два варианта дизайна. Одна альтернатива – удалить состояние. Например, цвет может быть передан в качестве параметра параметру ” треугольник “функция.

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

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

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

Текущая матрица преобразования – особенно важный и сбивающий с толку член состояния. Рисование чего-либо интересного с помощью графической библиотеки Processing требует матричных преобразований, но текущее преобразование невидимо . Такие функции, как «масштаб» и «поворот» «не имеют видимого эффекта, а составные преобразования (например, перевод с последующим масштабированием, или должно быть наоборот?) часто включают слепой поиск методом проб и ошибок.

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

Резюме – См. Состояние

Код манипулирует данными. Чтобы понять код, учащийся должен видеть данные и посмотрите, как код влияет на данные .

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

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

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

Программисты же, напротив, традиционно работали в уме, сначала представляя детали программы, а затем кропотливо их кодируя.

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

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

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

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

Получите что-нибудь на экране как можно скорее

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

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

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

На этом этапе она может прекратить воображать и начало реагирования :

  • «Это неправильная форма. Какая форма будет работать лучше?» Она идет вниз по списку и превращает фигуру в треугольник.
  • «Это прямоугольный треугольник. Я хочу другой треугольник» Она придает остриям треугольника форму, более похожую на крышу.
  • «Крыша не лежит на доме.» Она регулирует треугольник, чтобы опустить его на дом.

Как ни странно, я на самом деле не знаю ни одного API, специально разработанного с учетом автозаполнения. Я знаю много API, таких как Processing, которые разработаны для краткости, что не имеет значения в среде с хорошим автозаполнением.

В этом примере предполагалась гипотетическая графическая библиотека, которая была разработан для автозаполнения – все функции рисования начинаются с “draw”, поэтому список завершения будет отображаться так, как задумано дизайнером.

Другой способ структурировать библиотеку – предоставить одну функцию “shape”, которая принимает в качестве аргумента тип формы (треугольник, эллипс и т. Д.). Например:

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

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

Почему должен мы чего-то меньшего ожидаем от среды программирования?

Вывалить ковш с деталями на пол

В детстве у вас, вероятно, был опыт игры с каким-нибудь конструктором – Lego, или Erector Sets, или даже просто блоками. В качестве первого действия перед началом строительства ребенок часто раскладывает все части на полу.

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

Это вторая форма создания-за-реакцией. Помимо реакции на строящийся объект, ребенок также реагирует на части, которые у него есть.

В следующем примере доступные функции расположены рядом с областью кодирования, и программист может бегло просмотреть эти «части» и получить идеи.

Приведенный выше пример призывает программиста изучить доступные функции. Учащийся, который никогда не подумал бы попробовать ввести функцию “Безье” с ее незнакомым именем и восемью аргументами, теперь может легко наткнуться на нее и понять, о чем она.

Пример Выше показан один из способов представления «корзины деталей» для программного рисования. Но будет ли дизайнер пользовательского интерфейса считать, что это лучший интерфейс для рисования изображения на экране компьютера? А как насчет следующего?

Здесь могут возникнуть возражения. С этим интерфейсом это вообще «программирование»?

Нет, не совсем. Но ни один из примеров в этом разделе не является «программированием». Ввод кода для рисования статической формы –

– это не программирование! Это просто очень громоздкая форма иллюстрации. Это становится подлинным программированием , когда код абстрагирован – когда аргументы являются переменными , когда блок кода может делать разные вещи в разное время. В следующем разделе мы обсудим, как создание путем реагирования приводит к созданию путем абстрагирования.

Резюме – Создавайте, реагируя

Таким образом, нам нужен мощный способ получить что-то на экране, и мощные способы его регулировки. Регулируемые значения (такие как перетаскиваемые числа или цветовые палитры) являются ценным компонентом для последней цели, и я давний сторонник регулируемых значений (например, Калькулятор чистки , Объяснения, доступные для изучения , Десять ярких идей ). Однако я всегда предлагал регулируемые числа в контексте, когда регулятор уже понимает значение числа. Как упоминалось ранее, мне очень неудобно подход Академии Хана к поощрению учащиеся настраивают немаркированные числа и выясняют, для чего они нужны, и я чувствую, что это случай применения инструмента без понимания того, для какой цели он служит.

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

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

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

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

Изучение программирования – это изучение абстракции.

Компьютерная программа, которая представляет собой просто список фиксированных инструкции – здесь нарисуйте прямоугольник, затем треугольник – написать достаточно легко. Легко понять, легко понять.

Это также не имеет никакого смысла . Было бы намного проще просто нарисовать этот дом от руки. Какой смысл учиться «программировать», если это просто способ заставить компьютер делать вещи, которые проще делать напрямую?

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

В описании все еще написано «нарисуйте прямоугольник здесь, затем треугольник там», но здесь и там были абстрагированы. Разные параметры дают нам разные здесь и разные значения. .

Как программист учится писать этот абстрактный код? Как она научится составлять единое описание, которое является обобщенным для многих случаев?

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

Начните с константы, затем измените

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

Программист хочет переместить дом в другое место. Она не может переместить его, изменив одно число в коде, потому что есть четыре разных точки, которые все должны измениться одновременно – исходная точка прямоугольника и три точки треугольника.

Здесь программист выбирает одно из чисел, и преобразует его в переменную.

Затем она соединяет переменную с другим числом путем перетаскивания от одного к другому.

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

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

Вот весь процесс введения переменной.

Начните с одного, затем сделайте много

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

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

Переменная в первой строке выделения становится индукционная переменная , и программист может затем настроить ее границы.

Это процесс, начинающийся с конкретного случая, и постепенно обобщающее:

  • Сначала программист создает дом в фиксированном месте. Здесь она имеет интерактивный контроль над каждой отдельной фигурой.
  • Она превращает местоположение дома в переменную. Теперь у нее есть интерактивный контроль над переменной, которая влияет на многие фигуры.
  • Она вводит цикл для изменения этой переменной. Теперь у нее есть интерактивный контроль над границами цикла, который влияет на многие дома , который влияет на многие формы.

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

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

Дублируя вызов функции, она получает несколько домов, которыми можно управлять индивидуально.

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

In Лестница По терминологии абстракции программист поднялся на два уровня по лестнице абстракции – она ​​управляла x, затем абстрагировала x, затем управляла y, затем абстрагировала y.

Процесс, опять же, состоит из начала конкретного и постепенного внедрения абстракции:

  • Программист создает чертеж дома.
  • Она превращает x в переменную, чтобы она могла управлять положением дома.
  • Она превращает x в аргумент функции, так что разные дома могут иметь различные позиции.
  • Она превращает y в переменную, чтобы она могла контролировать высоту дома.
  • Она превращает y в аргумент функции, поэтому разные дома могут иметь разную высоту.

Резюме – Создание путем абстрагирования

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

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

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

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

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

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

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

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

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

Великие работы

Каноническая работа по разработке систем программирования для обучения и, возможно, величайшая книга, когда-либо написанная об обучении в целом, – это «Mindstorms» Сеймура Паперта. .

Проектирование обучающей системы без твердого понимания принципов, изложенных в этой книге, похоже на проектирование механической системы без понимания «рычага». Или «гравитация». Если вы читаете это эссе (а я в этом уверен!), То вам нужно прочитать «Mindstorms».

Шутки в сторону. Я серьезно. Если вы собираетесь разработать что-либо, связанное с обучением, вам буквально нужно прочитать «Mindstorms».

Ради бога, прочтите “Mindstorms” .

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

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

Идентичность и метафора

В Логотип , программист рисует картинки, направляя «черепаху», экранного персонажа, который оставляет след при движении:

Посмотрите всего две минуты этого видео – дети , и бородач говорит:

Алан Кей в Ранняя история Smalltalk : «Операторы присваивания – даже абстрактные – выражают цели очень низкого уровня … Человеческие программисты – это не машины Тьюринга. – и чем меньше их системы программирования требуют техники машины Тьюринга, тем лучше. “

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

В HyperCard , программа представлена ​​в виде стопки карточек, где программист рисует объекты на каждой карточке. В отличие от типичного языка программирования, где «объект» представляет собой абстрактную эфирную сущность, плавающую внутри компьютера, каждый объект в HyperCard имеет «физическое присутствие» – он имеет место на определенной карте, его можно увидеть, это можно взаимодействовал с. Каждый объект в HyperCard – это «реальная вещь», и это мощная метафора, которая позволяет программистам применять свою интуицию и понимание физического мира.

Rocky’s Boots структурирована как видеоигра с персонажем игрока, которого можно перемещать напрямую. Игрок не только может поднимать и перемещать предметы, но и действует как источник энергии – буквально мощная метафора. Все видно и осязаемо – электричество – это не какое-то абстрактное считывание напряжения, его можно рассматривать непосредственно как оранжевый огонь, текущий по проводам. Эта красивая метафора делает тривиальным следовать за потоком и видеть состояние .

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

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

– смоделированные свойства мяча (положение, скорость) не связаны с изображением мяча на экране. Они вычисляются и хранятся абстрактно как «числа» в «переменных», а мяч – просто тень, отбрасываемая этим эфирным внутренним представлением. Мяч нельзя поднять и переместить; нельзя сказать, как взаимодействовать с другими объектами. Это не “живое существо”, и симуляцию нельзя понять или подумать о иначе, чем ” числа в переменных ». Это очень слабый образ мышления. Примеры систем, в которых каждый экранный объект представляет собой живую материальную вещь, см. В Etoys или же Морфический .

Декомпозиция

Модульность это рычаг человеческого разума против сложности. Разбиение сложной вещи на понятные части важно для понимания, возможно сути понимания.

Язык программирования должен поощрять программист to разложить – подойти к сложной проблеме, разбивая ее на более простые задачи. Пейперт называет это разбиением программы на «кусочки размером с ум».

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

Smalltalk – это, по сути, философия декомпозиции в форме языка программирования. . Это Алан Кей, изобретающий объекты:

Боб Бартон «Основной принцип рекурсивного дизайна – сделать части такими же мощными, как и целое». Впервые я подумал о целом как о едином компьютере и задался вопросом, почему кто-то захочет разделить его на более слабые элементы, называемые структурами данных и процедурами. Почему бы не разделить его на маленькие компьютеры … Почему не тысячи из них, каждый из которых моделирует полезную структуру?

Ключевой вывод Smalltalk заключался в том, что сложную компьютерную программу можно разложить на более мелкие компьютеры, называемые «объектами». Программирование на Smalltalk почти полностью представляет собой упражнение в декомпозиции – разбиение мыслей на классы и сообщения.

Форт – это еще один язык, необыкновенная разложимость которого ценна для изучения и понимания.

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

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

Функциональные языки предоставляют два новых, очень важных вида клея. . Это ключ к мощи функционального программирования – он позволяет улучшить модульность.

В учебниках Khan Academy вообще не упоминается декомпозиция или функции, и многие примеры программ написаны как одна длинная список инструкций.

Обработка позволяет использовать логотип -стилевое разложение на подпроцедуры, в виде определений функций. Более мощная декомпозиция в стиле Smalltalk, в которой подмодули можно думать независимо, не поддерживается. В Processing события рисования и ввода привязаны к одной точке входа – функциям верхнего уровня, таким как «draw» и «mouseDown». Поведение подмодулей должно быть связано с этими глобальными функциями. Чистая декомпозиция невозможна.

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

Язык, препятствующий декомпозиции, – это язык, который подрывает наиболее ценный образ мышления программиста.

Перекомпоновка

Создание – это ремикс. В значительной степени новые идеи – это старые идеи в новых комбинациях.

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

HyperCard была разработана для перекомпоновки и, возможно, до сих пор не имеет себе равных в этом отношении. Билл Аткинсон полностью предназначал создателей для сборки программы, копируя и вставляя объекты из других программ, а затем постепенно настраивая и настраивая их. Таким образом, каждая программа служит комплектом деталей для создания новых программ. Поскольку весь исходный код, если таковой имеется, встроен в отдельные объекты в форме сценариев, а также поскольку сценарии используют свободные относительные ссылки на другие объекты, группы связанных объектов можно трансплантировать гораздо проще и успешнее, чем в других системах. Напишите «привет» в файл «привет». Перетащите от «0,0» до «, 114 ” с optionKey.

writeFile («привет», «привет»); dragMouse (0, 0, 0102, 114, OPTION_KEY);

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

HyperTalk использует синтаксис, похожий на английский, но дело не в этом. здесь. Важно то, что каждый аргумент может быть понят в контексте . Понятно, что «hello» – это строка, «greetings» – это имя файла, а «0,0» и «114, 126 “начало и конец точки. В обычном синтаксисе оба неоднозначны.

В качестве другого примера, вот как программист может нарисовать эллипс на трех языках:

canvas drawEllipseCenteredAtX: 63 y: 63 ширина: 0102 высота: 110.

эллипс(63, 67, 0102, 114);

толкать 0102; толкать 0102; толкать 60; толкать 60; вызов _ellipse

В Smalltalk, аргументы имеют контекст. «Эллипс» обработки столь же загадочен, как и язык ассемблера. Читатель должен найти или запомнить каждый аргумент, что является серьезным препятствием для чтения.

Имена имеют значение. Ниже приведены четыре метода массива из инфраструктуры Apple Cocoa и эквивалентные методы JavaScript:

изменить массив и ничего не вернуть addObject addObjectsFromArray arrayByAddingObject

толкать соединение concat