Блочные и текстовые языки

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

Используйте списки, основанные на единице

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

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

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

Рекомендация: Один – это первое число.

Поддерживайте либеральные правила именования

Блоки с именами переменных без учета регистра location_x (строчные x) и location_X (заглавная буква X).

Начинающие программисты не ожидают, что location_X и location_x — это разные переменные. В результате Blockly следует примеру BASIC и HTML, делая переменные и функции нечувствительными к регистру. Scratch использует более тонкий подход (как показано справа) и учитывает регистр для имен переменных, но не для проверок на равенство.

Кроме того, Blockly не требует, чтобы переменные и функции соответствовали типичной схеме [_A-Za-z][_A-Za-z0-9]* . Если кто-то хочет назвать переменную List of zip codes или רשימת מיקודים , это совершенно нормально.

Рекомендация: игнорировать регистр, разрешать любые имена.

Сделать все переменные глобальными

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

Рекомендация: область действия выходит за рамки, оставьте это на потом.

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

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

var last = stack.pop();  // Get and remove last element.
stack.pop();  // Just remove last element.

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

а) Обходить проблему. Большинство блочных языков разрабатывают язык таким образом, чтобы избежать подобных случаев. Например, в Scratch нет блоков, которые имели бы одновременно побочные эффекты и возвращаемое значение.

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

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

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

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

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

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

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

Генерировать читаемый код

Продвинутые пользователи Blockly должны иметь возможность просмотреть сгенерированный код (JavaScript, Python, PHP, Lua, Dart и т. д.) и сразу распознать написанную ими программу. Это означает, что необходимо приложить дополнительные усилия, чтобы сохранить читаемость этого машинного кода. Лишние круглые скобки, числовые переменные, раздавленные пробелы и многословные шаблоны кода — все это мешает созданию элегантного кода. Сгенерированный код должен включать комментарии и соответствовать руководствам по стилю Google .

Рекомендация: гордитесь своим сгенерированным кодом. Покажите это пользователю.

Принимайте различия между языками

Побочным эффектом стремления к чистому коду является то, что поведение Blockly во многом определяется поведением кросс-компилируемого языка. Наиболее распространенным языком вывода является JavaScript, но если Blockly будет выполнять кросс-компиляцию на другом языке, не следует предпринимать необоснованных попыток сохранить точное поведение на обоих языках. Например, в JavaScript пустая строка является ложью, тогда как в Lua она является истиной. Определение единого шаблона поведения для выполнения кода Blockly независимо от целевого языка приведет к созданию неподдерживаемого кода, который будет выглядеть так, как будто он вышел из компилятора GWT.

Рекомендация: Blockly — это не язык, позвольте существующему языку влиять на поведение.