Bloques personalizados: paradigmas de bloques

Existen varios paradigmas para elegir a la hora de diseñar una aplicación que utiliza Blockly. Estas elecciones deben considerarse con anticipación, ya que afectan los bloques que necesitará el usuario.

Configuración

Muchas aplicaciones de Blockly se usan para describir configuraciones, en lugar de programas ejecutables. Las aplicaciones de configuración suelen comenzar con la inicialización de un bloque de nivel raíz en el lugar de trabajo. Un buen ejemplo es la pestaña Block Factory de las herramientas para desarrolladores de Blockly:

Blockly.Blocks['factory_base'] = {
  init: function() {
    this.setDeletable(false);
    this.setMovable(false);
    this.setEditable(false);
    // etc...
  }
}

Blockly.serialization.blocks.append({'type': 'factory_base'}, workspace);

Esto crea un bloque intransferible y intransferible que contiene toda la configuración del usuario. El lugar de trabajo se puede serializar en cualquier momento para determinar la configuración actual.

Es posible que esas aplicaciones deseen inhabilitar automáticamente cualquier bloque que no esté conectado al bloque raíz. Esto se puede lograr con una línea:

workspace.addChangeListener(Blockly.Events.disableOrphans);

Programa en serie

La mayoría de las aplicaciones de Blockly están diseñadas para crear programas en serie. Los usuarios se apilan bloques que se ejecutan en orden.

Cada bloque (no inhabilitado) en el lugar de trabajo formará parte del programa. Si hay varias pilas de bloques, las superiores se ejecutan primero. (Si dos pilas tienen aproximadamente la misma altura, se da prioridad a las pilas a la izquierda (a la derecha en el modo de derecha a izquierda).

El lugar de trabajo se puede exportar a código ejecutable en cualquier momento. Este código se puede ejecutar en el lado del cliente en JavaScript (con eval o el intérprete de JS) o en el servidor en cualquier lenguaje.

import {javascriptGenerator} from 'blockly/javascript';

var code = javascriptGenerator.workspaceToCode(workspace);

Programa paralelo

Algunas aplicaciones de Blockly eligen ejecutar todas las pilas de bloques en paralelo, en lugar de en serie. Un ejemplo sería una aplicación de música en la que un bucle de batería se ejecuta en simultáneo con una melodía.

Una forma de implementar la ejecución paralela es generar el código para cada bloque de forma individual:

import {javascriptGenerator} from 'blockly/javascript';

var json = Blockly.serialization.workspaces.save(workspace);

// Store top blocks separately, and remove them from the JSON.
var blocks = json['blocks']['blocks'];
var topBlocks = blocks.slice();  // Create shallow copy.
blocks.length = 0;

// Load each block into the workspace individually and generate code.
var allCode = [];
var headless = new Blockly.Workspace();
for (var i = 0; block < topBlocks.length; i++) {
  var block = topBlocks[i];
  blocks.push(block);
  Blockly.serialization.workspaces.load(json, headless);
  allCode.push(javascriptGenerator.workspaceToCode(headless));
  blocks.length = 0;
}

Si el lenguaje de destino es JavaScript, el array allCode se puede usar para crear varios intérpretes de JS para una ejecución simultánea. Si el lenguaje objetivo es similar a Python, el array allCode se puede ensamblar en un solo programa que use un módulo de subprocesos.

Al igual que con cualquier programa paralelo, se deben tomar decisiones cuidadosas con respecto a cualquier recurso compartido, como variables y funciones.

Programa controlado por eventos

Los controladores de eventos son solo funciones a las que llama el sistema, y no el programa. Estos bloques pueden encerrar la pila de bloques que se ejecutarán o pueden ser encabezados que se sitúan sobre una pila de bloques.

A algunos desarrolladores les gusta agregar un "sombrero" a la parte superior de los bloques de eventos para que se vean diferentes a los demás. Este no es el aspecto predeterminado de Blockly, pero se puede agregar anulando la constante del renderizador ADD_START_HATS a true (Codelab de procesadores personalizados: Anula constantes) o agregando un tema y configurando la opción de sombrero en el estilo de bloque. Puedes encontrar más información sobre la configuración de sombreros en bloques como parte de los temas aquí.

Dentro de un modelo controlado por eventos, puede ser útil crear también un controlador para el inicio del programa. En este modelo, se ignorará cualquier bloque en el lugar de trabajo que no esté conectado a un controlador de eventos y no se ejecutará.

Cuando diseñes un sistema que usa eventos, considera si es posible o deseable admitir varias instancias del mismo controlador de eventos.