Benutzerdefinierte Bausteine: Styleguide

Im Laufe der Jahre hat das Team von Blockly und Blockly Games viele Erkenntnisse gewonnen, die auf die Entwicklung neuer Blöcke anwendbar sind. Im Folgenden finden Sie eine Sammlung von Fehlern, die wir gemacht haben oder die häufig von anderen gemacht werden.

Dies sind allgemeine Lektionen, die wir mit dem visuellen Stil von Blockly gewonnen haben, und gelten möglicherweise nicht für alle Anwendungsfälle oder Designs. Es gibt auch andere Lösungen. Hierbei handelt es sich jedoch nicht um eine vollständige Liste von Problemen, auf die Nutzer stoßen könnten, und dazu, wie sie vermieden werden können. Jeder Fall ist ein wenig anders und hat seine eigenen Vor- und Nachteile.

1. Bedingungen im Vergleich zu Schleifen

Die schwierigsten Blöcke für neue Nutzer sind Bedingungen und Schleifen. In vielen blockbasierten Umgebungen werden diese Blöcke in derselben Kategorie "Steuerelemente" zusammengefasst, wobei beide Blöcke dieselbe Form und Farbe haben. Dies führt oft zu Frustration, da neue Nutzende die beiden Blöcke verwechseln. Blockly empfiehlt, Bedingungen und Schleifen in separate Kategorien "Logik" und "Schleifen" zu verschieben, die jeweils eine andere Farbe haben. Dies macht deutlich, dass es sich um verschiedene Ideen handelt, die sich anders verhalten, obwohl sie ähnliche Formen haben.

Empfehlung: Bedingungen und Schleifen trennen.

2. Auf eins basierende Listen

Programmieranfänger reagieren schlecht, wenn sie zum ersten Mal auf nullbasierte Listen stoßen. Infolgedessen folgt Blockly dem Beispiel von Lua und Lambda Moo und erstellt die Listen- und Stringindexierung eins.

Für eine fortgeschrittenere Verwendung von Blockly werden nullbasierte Listen unterstützt, um den Übergang zu Text zu erleichtern. Für jüngere oder unerfahrene Zielgruppen wird weiterhin eine einbasierte Indexierung empfohlen.

Empfehlung: Eines ist die erste Zahl.

3. Nutzereingaben

Es gibt drei Möglichkeiten, einen Parameter vom Nutzer zu erhalten. Ein Drop-down-Menü ist am restriktivsten und eignet sich für einfache Anleitungen und Übungen. Ein Eingabefeld ermöglicht mehr Freiheit und eignet sich für mehr kreative Aktivitäten. Eine Wertblockeingabe (normalerweise ein Schattenblock) bietet die Möglichkeit, einen Wert zu berechnen (z.B. ein Zufallsgenerator), anstatt nur ein statischer Wert zu sein.

Empfehlung: Wählen Sie eine für Ihre Nutzer geeignete Eingabemethode.

4. Live-Blockbilder

Die Dokumentation für Blöcke sollte Bilder der Blöcke enthalten, auf die sie sich bezieht. Screenshots lassen sich ganz einfach erstellen. Wenn es jedoch 50 dieser Bilder gibt und die Anwendung in 50 Sprachen übersetzt wird, verwaltet eine Person plötzlich 2.500 statische Bilder. Dann ändert sich das Farbschema und 2.500 Bilder müssen aktualisiert werden.

Um uns aus diesem Wartungsalptraum zu erholen, ersetzte Blockly Games alle Screenshots durch Instanzen von Blockly, die im Lesemodus ausgeführt wurden. Das Ergebnis sieht mit einem Bild identisch aus, ist aber garantiert aktuell. Der schreibgeschützte Modus hat die Internationalisierung ermöglicht.

Empfehlung: Wenn mehr als eine Sprache unterstützt wird, verwende den schreibgeschützten Modus.

5. Ihr linker

Das Feedback von Kindern in den USA (interessanterweise nicht aus anderen Ländern) zeigte, dass es zwischen links und rechts zu Unstimmigkeiten kommt. Dies wurde durch das Hinzufügen von Pfeilen gelöst. Wenn die Richtung relativ ist (z. B. zu einem Avatar), ist der Pfeilstil wichtig. Ein → gerader Pfeil oder ein ↱-Abbiegepfeil ist verwirrend, wenn der Avatar in die entgegengesetzte Richtung zeigt. Am hilfreichsten ist ein kreisförmiger ⟳-Pfeil, auch wenn der gedrehte Winkel kleiner ist als der Pfeil.

Empfehlung: Ergänzen Sie den Text nach Möglichkeit durch Unicode-Symbole.

6. Übergeordnete Bausteine

Wann immer möglich, sollte ein übergeordneter Ansatz gewählt werden, auch wenn dadurch die Ausführungsleistung oder -flexibilität verringert wird. Betrachten Sie diesen Apps Script-Ausdruck:

SpreadsheetApp.getActiveSheet().getDataRange().getValues()

Bei einer 1:1-Zuordnung, bei der alle potenziellen Funktionen erhalten bleiben, würde der obige Ausdruck mit vier Blöcken erstellt werden. Blockly zielt jedoch auf eine höhere Ebene ab und stellt einen Block bereit, der den gesamten Ausdruck enthält. Das Ziel ist eine Optimierung für den 95 %-Fall, auch wenn dies die restlichen 5% schwieriger macht. Blockly ist kein Ersatz für textbasierte Sprachen. Es soll Nutzern dabei helfen, die anfängliche Lernkurve zu überwinden und textbasierte Sprachen zu verwenden.

Empfehlung: Wandeln Sie die gesamte API nicht blind in Blöcke um.

7. Optionale Rückgabewerte

Viele Funktionen in der textbasierten Programmierung führen eine Aktion aus und geben dann einen Wert zurück. Dieser Rückgabewert kann verwendet werden oder nicht. Ein Beispiel ist die Funktion pop() eines Stacks. „Pop“ kann aufgerufen werden, um das letzte Element abzurufen und zu entfernen, oder einfach das letzte Element, wobei der Rückgabewert ignoriert wird.

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

Bei blockbasierten Sprachen kann ein Rückgabewert im Allgemeinen nicht gut ignoriert werden. Ein Wertblock muss mit einem Element gesteckt werden, das den Wert akzeptiert. Es gibt mehrere Strategien, um dieses Problem zu lösen.

a) Umgehen Sie das Problem. Die meisten blockbasierten Sprachen entwickeln die Sprache, um diese Fälle zu vermeiden. Scratch hat beispielsweise keine Blöcke, die Nebenwirkungen und einen Rückgabewert haben.

b) Stellen Sie zwei Blöcke bereit. Wenn der Platz in der Toolbox kein Problem darstellt, besteht eine einfache Lösung darin, zwei dieser Art von Block bereitzustellen, einen mit und einen ohne Rückgabewert. Der Nachteil ist, dass dies zu einer verwirrenden Toolbox mit vielen nahezu identischen Blöcken führen kann.

c) Ändern Sie einen Block. Verwenden Sie ein Drop-down-Menü, ein Kästchen oder ein anderes Steuerelement, über das der Nutzer auswählen kann, ob es einen Rückgabewert gibt oder nicht. Die Form des Blocks ändert sich dann abhängig von seinen Optionen. Ein Beispiel dafür finden Sie in der Blockly-Listenzugriffssperre.

d) Nutzen Sie den Mehrwert. In der ersten Version von App Inventor wurde ein spezieller Pipe-Block erstellt, der alle verbundenen Werte aufnahm. Die Nutzer verstand das Konzept nicht und die zweite Version von App Inventor hat den Pipe-Block entfernt und stattdessen empfohlen, den Wert einfach einer Wegwerf-Variablen zuzuweisen.

Empfehlung: Jede Strategie hat Vor- und Nachteile. Wählen Sie die für Ihre Nutzer geeignete Strategie aus.

8. Wachsende Blöcke

Für bestimmte Blöcke kann eine variable Anzahl von Eingaben erforderlich sein. Beispiele sind ein Additionsblock, der eine beliebige Menge von Zahlen summiert, ein if/elseif/else-Block mit einer beliebigen Reihe von elseif-Klauseln oder ein Listenkonstruktor mit einer beliebigen Anzahl initialisierter Elemente. Es gibt mehrere Strategien mit jeweils Vor- und Nachteilen.

a) Die einfachste Methode besteht darin, den Nutzer dazu zu bringen, den Block aus kleineren Blöcken zusammenzustellen. Ein Beispiel wäre das Addieren von drei Zahlen durch Verschachteln von zwei Blöcken mit zwei zusätzlichen Zahlen. Ein weiteres Beispiel wäre, nur if/else-Blöcke anzugeben und Nutzer zu verschachteln, um elseif-Bedingungen zu erstellen.

Der Vorteil dieses Ansatzes ist die anfängliche Einfachheit (sowohl für den Nutzer als auch für den Entwickler). Der Nachteil besteht darin, dass bei einer großen Anzahl von Verschachtelungen der Code sehr umständlich und für den Nutzer schwer zu lesen und zu pflegen wird.

b) Alternativ kann der Block dynamisch erweitert werden, sodass am Ende immer eine kostenlose Eingabe vorhanden ist. Ebenso löscht der Block die letzte Eingabe, wenn am Ende zwei kostenlose Eingaben vorhanden sind. Dies ist der Ansatz, den die erste Version von App Inventor verwendet hat.

Automatisch vergrößerte Blöcke wurden von den Nutzern von App Inventor aus mehreren Gründen nicht gemocht. Erstens gab es immer eine kostenlose Eingabe und das Programm war nie "abgeschlossen". Zweitens war das Einfügen eines Elements in der Mitte des Stapels frustrierend, da alle Elemente unter der Bearbeitung getrennt und wieder verbunden wurden. Wenn die Reihenfolge jedoch nicht wichtig ist und Nutzer sich mit Löchern in ihrem Programm vertraut machen können, ist dies eine sehr praktische Option.

c) Um das Lochproblem zu lösen, fügen einige Entwickler Plus- und Minus-Schaltflächen zu Blöcken hinzu, mit denen Eingaben manuell hinzugefügt oder entfernt werden. Öffnen Roberta verwendet zwei Schaltflächen, um Eingaben von unten hinzuzufügen oder zu entfernen. Andere Entwickler fügen jeder Zeile zwei Schaltflächen hinzu, damit das Einfügen und Löschen aus der Mitte des Stapels möglich ist. Andere fügen in jeder Zeile zwei Nach-oben-/Nach-unten-Schaltflächen hinzu, um eine Neuanordnung des Stapels zu ermöglichen.

Diese Strategie bietet eine Reihe von Optionen, die von nur zwei Schaltflächen pro Block bis zu vier Schaltflächen pro Zeile reichen. An einem Ende besteht die Gefahr, dass Nutzer die benötigten Aktionen nicht ausführen können. Am anderen Ende ist die Benutzeroberfläche so voller Schaltflächen, dass sie wie die Brücke von Raumschiff Enterprise aussieht.

d) Der flexibelste Ansatz besteht darin, eine Mutatorblase zum Block hinzuzufügen. Dies wird als einzelne Schaltfläche dargestellt, mit der ein Konfigurationsdialogfeld für diesen Block geöffnet wird. Elemente können beliebig hinzugefügt, gelöscht oder neu angeordnet werden.

Der Nachteil dieser Methode besteht darin, dass sie für unerfahrene Nutzer nicht intuitiv ist. Die Einführung von Mutatoren erfordert irgendeine Art von Anweisung. Blockbasierte Apps, die auf jüngere Kinder ausgerichtet sind, sollten keine Mutatoren verwenden. Für Poweruser sind sie trotzdem von unschätzbarem Wert.

Empfehlung: Jede Strategie hat Vor- und Nachteile. Wählen Sie die für Ihre Nutzer geeignete Strategie aus.

9. Generierung von sauberem Code

Fortgeschrittene Blockly-Benutzer sollten den generierten Code (JavaScript, Python, PHP, Lua, Dart usw.) anzeigen können und das Programm, das sie geschrieben haben, sofort erkennen. Dies bedeutet, dass zusätzlicher Aufwand unternommen werden muss, um diesen maschinengenerierten Code lesbar zu halten. Überflüssige Klammern, numerische Variablen, reduzierte Leerzeichen und ausführliche Codevorlagen stehen der Erzeugung von elegantem Code im Weg. Der generierte Code sollte Kommentare enthalten und den Styleguides von Google entsprechen.

Empfehlung: Seien Sie stolz auf Ihren generierten Code. Zeigen Sie es den Nutzern.

10. Sprachabhängigkeit

Ein Nebeneffekt des Wunsches nach sauberem Code besteht darin, dass das Verhalten von Blockly weitgehend durch das Verhalten der kompilierten Sprache definiert wird. Die gängigste Ausgabesprache ist JavaScript, aber wenn Blockly in eine andere Sprache übergreifend kompiliert werden sollte, sollten keine unangemessenen Versuche unternommen werden, das genaue Verhalten in beiden Sprachen aufrechtzuerhalten. In JavaScript ist ein leerer String beispielsweise falsch, in Lua hingegen wahr. Das Definieren eines einzelnen Verhaltensmusters für den Code von Blockly, der unabhängig von der Zielsprache ausgeführt werden soll, würde zu nicht verwaltbarem Code führen, der so aussieht, als käme er aus dem GWT-Compiler.

Empfehlung: Blockly ist keine Sprache. Lass die vorhandene Sprache das Verhalten beeinflussen.