Введение
Жизнь в современном мире развивается динамично, технологии появляются и умирают, а вместе с ними устаревают и наши навыки. 20 лет назад нужно было помнить функции Windows API, сейчас многие специалисты даже не знают, что это такое, и им не мешает это работать. На первый план вышли другие технологии, требующие совершенно другого опыта. Например, Java Script, HTML 5, CSS. Через 10 лет на смену, скорее всего, придут другие технологии и инструменты, другой способ
Как это было ранее
Сейчас появляются новые способы получения знаний – вебинары и видеоуроки, различные видеокурсы. Наряду с этим книги не потеряли своей актуальности, просто теперь у вас есть широкий выбор, каким способом получать знания – со смартфона или в библиотеке. Конечно, эти способы отличаются степенью интерактивности и комфорта.
В старых добрых книгах есть раздел «Контрольные вопросы». Зачем они нужны? Дело в том, что важным моментом обучения является самопроверка. Не только потому, что человек может самостоятельно узнать, правильно ли он усвоил пройденный материал. Важно также, что в момент ответа на контрольные вопросы человек критически переоценивает пройденное, открываются новые углы зрения и перспективы, что значительно повышает эффективность обучения.
Представляем себе, что вы прочитали главу из книги по механике, посвященную блокам. Какие вопросы могут вам встретиться в конце главы? Например:
Из каких элементов состоит блок?
Что такое полиспаст?
Возможно, к главе прилагались бы задачи. Например:
Условие задачи:
В системе, изображённой на рисунке, присутствуют блоки и грузы, соединенные тросами, масса самого правого груза равна 700 грамм, а массы блоков от 100 до 600 грамм. Система уравновешена и неподвижна. Найдите массы грузов m1, m2 и m3. Массой, трением и растяжением тросов можно пренебречь. Кстати, это довольно интересная задача, кто хочет порешать ее, лучше не заглядывать дальше, поскольку далее будет ответ.
Для того чтобы узнать и проверить, мы бы заглянули в конец книги и посмотрели ответы. Таким образом, мы бы критически проанализировали прочитанное, и оно запомнилось бы намного лучше, чем если бы мы просто прочитали материал. Самопроверка закрепляет знания.
Сейчас (наши дни)
Однако прогресс не стоит на месте, и теперь, читая электронную книгу, вы тоже можете встретить,
например, такое проверочное упражнение:
Здесь, как видите, все гораздо нагляднее и быстрее. Нужно перетащить все гири на свои места. При этом правильность ответа мы узнаем сразу и не будем тратить время на перелистывание страниц в поисках страницы с ответами. Что очень важно, наше внимание останется сконцентрировано на предметной области.
Как сделать такое упражнение
Каким же образом сделать такое упражнение? Здесь в общем случае нужно четыре человека:
1. Нужен специалист в предметной области (в данном случае физик), который сформулирует суть упражнения и варианты ответов.
2. Нужен дизайнер, который придаст упражнению надлежащий внешний вид.
3. Нужен web-программист, который напишет код.
4. Нужен специалист по контролю качества (Quality Control — QC), который убедится, что данное упражнение работает хорошо, во всех браузерах и т.п.
Процесс разработки упражнения выглядят следующим образом:
1. Специалист формулирует суть задачи, ручкой на бумаге рисует схему упражнения.
2. Дизайнер придает этому нужный вид.
3. Программист реализует упражнение.
4. QC проверяет упражнение, делает свои замечания и возвращает упражнение программисту. Шаги 3-4 повторяются несколько раз.
5. Потом дизайнер в рамках процедуры авторского надзора делает свои замечания по внешнему виду упражнения, и, таким образом, шаги 3-5 повторяются несколько раз.
6. Потом опять подключается специалист, который проверяет, не потерялась ли за всеми перипетиями суть упражнения. В общем случае шаги 3-6 могут также повторяться несколько раз.
Только после этого картинку можно публиковать в электронной книге или записывать на DVD.
Таким образом, мы видим, что процесс может занимать достаточно длительное время.
Будущее
Идея нашего инструмента заключалась в том, чтобы подобные упражнения создавал непосредственно специалист в предметной области, поэтому инструмент мы решили сделать максимально простым. На данном этапе он поддерживает 4 основных типа упражнения:
Drag Elements, сопоставление элементов друг-другу.
Text Gaps, ввод текста вручную.
Sorting, сортировка.
Single, Multiple choice.
Однако мы не будем рассматривать все возможности системы.
Давайте просто попробуем создать упражнение по уравновешиванию гирь. Для начала, конечно же, нам нужна картинка соответствующего размера. Попросим дизайнера нарисовать ее:
Далее заходим в наш инструмент и создаем новое упражнение типа Drag Drop
Чтобы вся информация о задаче была в одном месте, введем вопрос прямо в заголовке упражнения.
Теперь загрузим нашу картинку в редактор.
Теперь необходимо отметить места, куда можно будет перетаскивать гири. Для этого нам понадобится три элемента управляющих элемента типа «Прямоугольник» и текстовые элементы, чтоб нарисовать знаки вопроса:
Каждому прямоугольнику необходимо задать свойство Behavior. Это свойство надо выставить в “drop-target”. Все, что осталось, – это загрузить изображения гирь и выставить им в качестве Behavior значение “drop-element”, а также поставить им правильные target.
Теперь можно проиграть упражнение в режиме тестирования.
Готово!!! Можно вставлять в книжку.
Реализация
Для реализации такого инструмента была выбрано популярное сочетание технологии AngularJS и Breeze.JS. Такой подход позволяет иметь одну модель данных, которая синхронизируется одновременно с отображением с помощью AngularJS и с серверной стороной при помощи Breeze.JS. Такой подход вполне естественен для подобного рода решений, поскольку вся сложность сосредотачивается на клиентском уровне, а не “размазывается” по всем слоям приложения. Мы не будем здесь описывать подробно архитектуру решения, возможно, сделаем это в следующей статье. Остановимся на одной интересной проблеме, которая встретилась нам при реализации.
Важным моментом является то, что приложение сразу сохраняет все изменения клиентской модели на серверной стороне. Поэтому для работоспособности приложения критически важна последовательность выполнения операций. Представим, например, что вы добавляете элемент и сразу удаляете его. Если при этом порядок будет нарушен, то вы сначала удалите несуществующий элемент и получите ошибку. Для решения этой проблемы существует расширение для breeze, называемое breeze.savequeuing.js.
Однако при использовании этой библиотеки обнаружилась следующая проблема: Breeze обновляет состояние сущностей на клиентской модели значениями, только что сохранёнными на сервере. Таким образом, при большом количестве изменений в единицу времени состояние сущности на клиенте может вернуться в некоторое предыдущее состояние в результате запаздывания сохранения на сервере. Можно, конечно, иметь две копии клиентской модели и перезаписывать поля сущностей выборочно, обрабатывая события сохранения в breeze. Однако в этом случае теряется сама суть использования breeze, т.е. создание общей для клиента и сервера модели данных.
К счастью, breeze поддерживает своего рода расширяемость (собственно breeze.savequeuing.js реализована именно таким образом), поэтому можно сделать свое расширение, работающее “поверх” breeze.savequeuing.js, которое перетирает не все сущности, а только некоторые, по нашему выбору.
Как это сделать. Во-первых, переопределим функцию updateTargetFromRaw.
EntityType.prototype.enableSaveWithNoResultUpdate = function () { this._updateTargetFromRaw = EntityType.prototype._updateTargetFromRawNoResultUpdate;
};
Код этой функции довольно длинный, поэтому мы заменили часть кода комментариями.
EntityType.prototype._updateTargetFromRawNoResultUpdate
= function (target, raw, rawValueFn) {
var overwrite =
/* Вычислить некоторым образом, нужно ли обновлять сущность или нет */;
this.dataProperties.forEach(function (dp) {
var rawVal = rawValueFn(raw, dp);
if (rawVal === undefined) return;
var dataType = dp.dataType;
var oldVal;
if (dp.isComplexProperty) {
//
} else {
var val;
if (overwrite) {
// Стандартный код breeze.js, который обновляет сущность
} else {
if ((dp.isPartOfKey || !tp || (tp === dp.defaultValue))) {
// Стандартный код breeze.js, который обновляет сущность
}
}
}
});
// ...
}
Давайте разберем его подробнее. Во-первых, что является контекстом вызова (this) для этой функции. Контекстом является объект, который содержит метаданные сущности. Кроме того, функция принимает три параметра:
target – сущность, которую надо (или не надо) обновить.
raw – “сырые” данные возвращаемые с сервера.
rawValueFn – функция, которая умеет извлекать значение некоторого свойства из сырых данных. Если overwrite == false, т.е. обновлять сущность не нужно, то мы ничего не делаем, за исключением одно важного случая, – если свойство является частью ключа. Почему это важно? Потому что при добавлении новой сущности ключ пуст, а значение в нем появляется только после сохранения на сервере. И после сохранения на сервере его надо сохранить и на клиенте. Если overwrite == true, то сохраняем сущность в обычном порядке.
Конечно, в итоге у нас все получилось и заработало так, как надо.
Чего мы добились
Самое главное для нас было уменьшить время создания интерактивных упражнений и сократить трудозатраты. Процесс разработки упражнения теперь выглядит так:
Как видите, он значительно оптимизирован. Нам удалось исключить 2 из 4-х человек, участвующих в создании упражнения. Нам нужны только дизайнер, чтобы нарисовать картинки к упражнению, и специалист в предметной области, который займется созданием упражнения. Отпадает также трудоемкая работа по тестированию поведения упражнения в разных браузерах. Таким образом, время, затрачиваемое на создание, сокращается в несколько раз.
Всегда приятно видеть, как IT-решения помогают трансформировать реальную жизнь и делать ее чуть-чуть проще.
Автор: eastbanctech