Представляем KlassLive

До того, как COVID-19 сделал Zoom-обучение синонимом, ну, в общем, обучением, будущее образования, казалось, состояло из (а) загрузки видео в Интернет и (б) сидения и позволяя людям смотреть их. Наиболее яркими примерами являются МООК: массовые открытые онлайн-курсы, призванные на порядки расширить охват до тысяч новых учеников. Хотя МООК значительно расширили доступ ко всем видам контента, трудно найти хоть одного учащегося, который извлек бы из формата МООК больше, чем более традиционные, личные методы.

В этом смысле Zoom и МООК могут поделиться несколькими уроками. Во-первых, живое обучение - это обед с заранее записанным обучением. Взаимодействие с людьми имеет значение. Во-вторых, интерактивное обучение съедает ужин пассивного обучения. Делать что-то, а не пассивное слушание действительно имеет значение. Сочетание этих двух вещей особенно эффективно. Такие организации, как Lambda School и Code in Place Стэнфорда, осознали, что быть онлайн не обязательно означает асинхронность, предварительно записанную и пассивную.

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

Интерактивное обучение: некоторые проблемы

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

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

Идти в ногу, или кто что получает

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

def step1(monkey):
    """ Let's write a function 
    that turns a monkey into a wrench. """
    return ...

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

def step2(monkey):
    """ Now write a function that uses step1 
    to turn a monkey into a whole garage. """
    wrench = stage1(monkey)
    return ...

Спустя много шагов это может привести к чему-то довольно сложному:

def step73(monkey):
    """ Write a function that uses steps 1-72,
    to recreate the origins of the universe. """
    after_big_bang = stage72(monkey)
    return ...

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

Метод KlassLive

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

Никакой настройки, никакой установки, никогда

Учащимся KlassLive нужна одна часть информации: URL-адрес. Они присоединяются к живым сеансам через вход на GitHub и сразу же попадают в рабочую среду, подготовленную для рассматриваемой темы.

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

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

Не отставать

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

Веселье!

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

Стек KlassLive

Хотя Python изначально был языком обучения и обучения KlassLive, его реализация полностью построена на современном Javascript поверх груды невероятного программного обеспечения с открытым исходным кодом. Хотя Jupyter является важным источником вдохновения для KlassLive, ни один из открытых исходных кодов Jupyter не используется под капотом.

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

KlassLive состоит из трех основных компонентов:

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

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

Внешний интерфейс

Из всей горы OSS, на которую опирается KlassLive, пожалуй, нет более важной части, чем React. В течение нескольких лет я знал в основном две вещи о React: (1) это делает Facebook и (2) мне не очень нравится Facebook. Ergo, React не имеет значения. Фактически сравнив популярные интерфейсные фреймворки 2019 года, потребовалось около трех страниц руководства, чтобы развеять это мнение. Комбинация компонентов конечного автомата в React и удаление шаблонного программирования с помощью синтаксиса JSX довольно быстро прояснили, почему он стал самым популярным способом создания веб-интерфейсов. Изучение React действительно заставило меня поверить, что создание чего-то вроде KlassLive возможно (для меня). Нет обратного пути.

KlassLive также извлекает выгоду из гигантской экосистемы React. Create React App служил стартером проекта и инструментом навигации для довольно сложных систем кросс-компиляции JavaScript. Практически весь внешний вид KlassLive создается с помощью Material-UI, включая все основные элементы пользовательского интерфейса - проблемы, боковые панели, меню, таблицы и тому подобное. Редактирование кода и Markdown в первую очередь можно отнести к выдающемуся CodeMirror и связанным библиотекам react-codemirror2 и react-markdown.

У меня более сложные отношения со следующей по значимости библиотекой в ​​интерфейсе KlassLive: Redux. Хотя локальный автомат React для каждого компонента пользовательского интерфейса предлагает довольно интуитивно понятную организацию данных и поведения, он быстро переключается на широко распространенное, в основном глобальное состояние. Вокруг React возникло семейство библиотек управления состоянием, самой популярной из которых является Redux. Все данные центрального интерфейса KlassLive - код, введенный в ячейки, оценки ответов и т. Д., Хранятся в магазине Redux. Его механизм обновления, редукторы Redux, составляют изрядную часть кодовой базы внешнего интерфейса.

Использование Redux не было моей любимой частью написания KlassLive. Я пробовал альтернативы, в частности MobX, который оказался более интуитивно понятным. Но победу одержали гигантское сообщество и база знаний Redux. Как правило, в случае сомнений KlassLive использует самые популярные инструменты, доступные для каждой задачи. Прежде всего, это делает помощь максимально доступной.

GraphQL

Связь между интерфейсом и серверной частью KlassLive использует другой известный проект Facebook с открытым исходным кодом: GraphQL. GraphQL - это строго типизированный контракт между клиентом и сервером, который использует простой язык описания запросов для определения своих типов. Например, каждый класс Klass включает в себя, среди еще нескольких механических полей:

type Klass {
    owner: User!,
    title: String,
    desc: String,
    problems: [Problem]!,
    scratch: [Cell],
    metadata: JSON,
    runtime: JSON,
    visibility: Visibility,
}

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

query GetKlass ($id: String) {
  klass(id: $id) {
  	id
    title
    desc
    owner 
    runtime
    visibility
	  problems {
        title
        desc
        setup { ...CellData }
        prompt { ...CellData }
        solution { ...CellData }
        tests { ...CellData }
      }
      scratch { ...CellData }
  }
}

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

На сервере GraphQL выполняет ряд функций преобразователя. Запросы и мутации, по сути, проходят через дерево вызовов функций решателя, передавая результаты каждого на следующий уровень. Данные Klass хранятся в экземпляре MongoDB, работающем в сервисе Atlas MongoDb.com. Популярная библиотека отображения объект-документ Mongoose определяет схему и обеспечивает подобие типобезопасности для серверного кода.

Apollo также включает набор скриптов, которые генерируют интерфейсы TypeScript на языке описания схем GraphQL. Помимо этого автоматически сгенерированного кода, TypeScript в значительной степени представляет собой любопытство для KlassLive. Его классы используются в нескольких разделах, где я имел тенденцию ошибаться при преобразовании между версиями аналогичных данных в памяти, на проводе и в базе данных, таких как записные книжки Klass. В общем, неясно, помогло это или навредило.

Бегущий по подчинению

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

Публичный экземпляр Klass.Live имеет существенно другие потребности в безопасности, чем любая локальная, частная или среда с более высоким уровнем доверия. В то время как ограниченный доступ может ограничивать использование внутри конкретной компании, учебного заведения или домена, общедоступный Klass.Live нацелен на то, чтобы позволить любому, у кого есть учетная запись GitHub. Основным препятствием для безопасности является безопасный запуск произвольного кода от почти произвольных пользователей. Разнообразные онлайн-среды разработки, задачи кодирования и другие инструменты программирования, такие как CoderPad, CodeSandbox, CodePen, CodeBunk, repl.it, CoderByte и FooBar от Google - все они находят разные решения. к этой проблеме. CoderPad, например, частично включает файл readme, если вы меня взламываете в своих интерактивных сеансах собеседований, которые выполняются на изолированных облачных виртуальных машинах.

Контейнеры Docker общедоступного Klass.Live выполняются средой выполнения Google gVisor. Это та же самая защита, которую Google Cloud Platform предлагает свои собственные среды App Engine. gVisor - это, по сути, прокси для части интерфейса Unix, предназначенный для ограничения поверхности атаки.

За безопасность gVisor приходится платить. Во-первых, он добавляет накладные расходы производительности сверх того, что уже понесено средой выполнения контейнеров. Для коротких и простых задач это мало что значит, но для более сложных классов это складывается. Во-вторых, по причинам, очень связанным с Беркли, Scala входит в число наиболее приоритетных языков KlassLive. К сожалению, я обнаружил, что gVisor особенно плохо работает со своим стеком на основе Java, особенно для больших программ с большим объемом памяти. Частные экземпляры KlassLive могут избежать этих накладных расходов и проблем, вместо этого работая в среде выполнения Docker по умолчанию.

Дороги не проложены

На пути создания KlassLive были также опробованы и заброшены несколько инструментов с высоким потенциалом. Вероятно, наиболее известным является NextJs Верселя. Хотя основной вклад Next заключается в расширении жизненного цикла компонентов React с включением рендеринга на стороне сервера, я счел его привлекательным по разным причинам. Самый популярный метод маршрутизации внутри приложения в React использует маршрутизаторы на основе компонентов, например, из популярного React-Router. Например, верхний уровень KlassLive выглядит примерно так:

class KlassLiveRouter extends React.Component {
    render() {
        return (
            <Switch>
                <Route path="/" exact component={HomeContent}/>)}/>
                <Route path={`/account`} exact component={UserPage} exact={false}/>
                <Route path={`/klass/:id`} component={KlassMatcher} exact={false}/>
                <Route path={`/session/:id`} component={SessionMatcher} exact={false}/>
                <Route component={NotFoundContent}/>
            </Switch>
        );
    }
}

Когда я начал работать с React, мне это очень не понравилось. Я нашел маршрутизацию Next на основе файловой системы более интуитивно понятной. Но использовать Next оказалось намного сложнее, особенно для такого новичка. Сочетание одного и того же кода, работающего как на клиенте, так и на сервере, сделало такие вещи, как инициализация и настройка, намного более сложными. Попытки связать это с MobX, скорее всего, не помогли. Хотя я думаю, что у Next есть что-то довольно крутое, в случае сомнений KlassLive по умолчанию использует самые популярные варианты с наибольшей базой знаний: в данном случае Redux и React-Router.

Связанный с Vercel сервис Now заслуживает дополнительной похвалы, так как на нем размещается Klass.Live SPA, а также вступительная презентация от PyConDe 2019, а также мой собственный личный веб-сайт. Его бессерверные функции также запускают версию сервера KlassLive GraphQL с ограниченной функциональностью.

Жду с нетерпением

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

Наконец, KlassLive благодарит многих сотрудников и стартапов лондонской Founders Factory, моего временного дома вдали от дома летом 2019 года, которые предоставили неоценимые советы и поддержку, а также восторженной публике на выставке Берлин 2019 года. PyConDE ».