自訂模塊:樣式指南

多年來,Blockly 和 Blockly Games 團隊學到許多可以適用於開發新區塊的學員。以下是我們犯的許多錯誤,或其他人經常犯的錯誤。

這些是我們使用 Blockly 視覺風格學到的一般課程,可能不適用於所有用途或設計。此外也有其他解決方案。另外,這份清單並未完整列出使用者可能會遇到的問題,以及如何避免這些問題。每種情況都不盡相同,各方面也各有優缺點。

1. 條件式與迴圈

新使用者最困難的區塊是條件式和迴圈。許多區塊式環境會將這兩個區塊歸入同一個「控制項」類別,而兩個區塊的形狀和顏色都相同。這通常會令人感到困擾,因為新使用者能對兩個區塊感到困惑。Blockly 建議將條件式和迴圈移至單獨的「Logic」和「Loop」類別,每個類別使用不同的顏色。由此可見,這些概念雖是不同的想法,卻仍存在不同的行為,即使形狀都很相似。

建議:將條件和迴圈分開。

2. 單一清單

初級程式設計人員第一次遇到零式清單時,會做出不良反應。因此,Blockly 遵循 Lua 和 Lambda Moo 的領導力,將清單和字串索引建立為單一項目。

對於 Blockly 的進階用途,系統支援以零為基礎的清單,以便輕鬆轉換至文字。我們建議較年輕或較新手 採用單一索引結構

建議:一個是第一個指標。

3. 使用者輸入內容

有三種方法可以向使用者取得參數。下拉式選單是最嚴格的限制,適用於簡單的教學課程和練習。輸入欄位可以讓使用者享有更多自由,也適合用於更多創意活動。值區塊輸入 (通常帶有陰影區塊) 可讓您計算值 (例如隨機產生器),而非只計算靜態值。

建議:選擇適合使用者的輸入方式。

4. 即時模塊圖片

區塊的說明文件應包含其所參照的區塊圖片。擷取螢幕畫面非常簡單,不過,如果有 50 張這類圖片,且應用程式翻譯為 50 種語言,就會有 2,500 張靜態圖片。色彩配置會改變,又需要更新 2,500 張圖片。

為了從這次維護的夜晚中抽取自身體力,Blockly Games 把所有螢幕截圖替換成 Blockly 的例項,使其在唯讀模式中執行。這個結果與圖片相同,但保證是最新的。唯讀模式已支援國際化。

建議:如果你支援多種語言,請使用唯讀模式。

5. 您的另一半

美國兒童的意見回饋 (但顯然並非來自其他國家/地區) 顯示,左右兩邊之間看起來會不太清楚。新增箭頭可以解決這個問題。如果方向是相對的 (例如相對於顯示圖片),則箭頭樣式很重要。當顯示圖片朝反方向時,顯示 → 直箭頭或 ↱ 轉彎箭頭會令人困惑。最適合使用 ⟳ 圓形箭頭,即使轉動角度小於箭頭時,也能使用 ⟳ 圓形箭頭。

建議:盡可能使用萬國碼 (Unicode) 圖示補充文字。

6. 高階封鎖

即使這麼做會降低執行效能或彈性,也應盡可能採取更高層級的做法。請思考以下這個 Apps Script 運算式:

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

在保存所有潛在功能的 1:1 對應下,上述運算式將使用四個區塊建構。但 Blockly 的目標在於更高層級,並提供一個能封裝整個運算式的區塊。我們的目標是針對 95% 的情況進行最佳化,即使剩下的 5% 也比較困難。Blockly 並非取代文字語言,旨在協助使用者克服初始學習曲線,以便使用文字語言。

建議:不要盲目將整個 API 轉換為模塊。

7. 選擇性的傳回值

文字型程式設計中的許多函式都會執行動作,然後傳回值。系統不一定會使用這項傳回值。堆疊的 pop() 函式就是一個範例。系統可能會呼叫彈出視窗,取得並移除最後一個元素,或者呼叫該方塊只移除最後一個元素遭到忽略的元素。

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

封鎖式語言通常不適合忽略傳回值。值區塊必須插入接受該值的項目。有幾種策略可以處理這個問題。

a) 引導問題。大部分的區塊式語言都會設計語言來避免這類情況。舉例來說,Scratch 沒有任何區塊具有副作用和回傳值。

b) 提供兩個模塊。如果工具箱中的空間沒有問題,簡單的解決方案就是提供這兩種類型的區塊,一個有沒有傳回值。缺點是,這會使工具箱裡有許多幾乎相同的區塊,令人感到困惑。

c) 修改一個區塊。使用下拉式選單、核取方塊或其他控制項,讓使用者選擇是否要提供傳回值。該區塊接著會根據選項改變形狀。例如 Blockly 的清單存取區塊,就可發生這種情況。

d) 攝取值。首版 App Inventor 建立了特殊的管道區塊,用於指派任何連線值。使用者不瞭解這個概念,而第二個版本的 App Inventor 移除了管道區塊,而是建議使用者直接將該值指派給 Throwway 變數。

建議:每項策略各有優缺點,請選擇適合使用者的選項。

8. 成長的方塊

某些區塊可能需要的輸入數量不一。例如,新增區塊可加總任意一組數字,或含有任意組合的 elseif 子句的 if/elseif/else 區塊,或包含任意數量初始化元素的清單建構函式。目前有幾個策略,各有優缺點。

a) 最簡單的做法是將使用者組合的區塊移出較小的區塊。例如建立兩個數字加法區塊的巢狀結構,就新增三個數字。另一個範例只提供 if/else 區塊,並讓使用者透過巢狀結構建立其他條件。

此方法的優點在於簡單明瞭 (適用於使用者和開發人員)。缺點是如果巢狀數量較大,程式碼就會變得繁瑣,且讓使用者難以讀取及維護。

b) 另一種做法是動態展開區塊,在結尾一律保留一個自由輸入內容。同樣地,如果結尾有兩個自由輸入值,區塊會刪除最後一個輸入。這是我們採用第一版 App Inventor 的方法。

App Inventor 使用者會因為幾種原因而自動不喜歡自動增加的封鎖。首先,遊戲總是會有免費的輸入內容,而程式從未完成。接著,在堆疊中間插入元素會令人感到困擾,因為這會牽涉到編輯作業下方的所有元素取消連結,然後再重新連結。也就是說,如果順序並不重要,而使用者能夠自在程式中的孔洞,這是非常方便的選擇。

c) 如要解決此問題,有些開發人員會新增 +/- 按鈕,封鎖手動新增或移除輸入內容。開啟 Roberta 時,系統會使用兩個這類按鈕 新增或移除底部的輸入內容其他開發人員會在每個資料列中新增兩個按鈕,以便從堆疊中間插入和刪除功能。其他則會在每一列中新增兩個向上/向下按鈕,因此可以配合堆疊重新排序。

這項策略是一種多樣化的選項,從每個區塊僅兩個按鈕,至每列四個按鈕。一端指的是使用者無法執行所需操作的危險,在另一端 UI 卻充滿了外觀看起來像星艦 Enterprise 橋接按鈕的按鈕。

d) 最彈性的方法是在區塊中加入分子泡泡。系統會以單一按鈕開啟該區塊的設定對話方塊。您可隨時新增、刪除或重新排列元素。

這個做法的缺點是,變體對新手使用者來說並不容易。導入變異器時需要某種形式的指令。以幼童為目標對象的區塊應用程式不應使用變動器。然而,一旦瞭解相關知識,對進階使用者而言相當重要。

建議:每項策略各有優缺點,請選擇適合使用者的選項。

9. 清楚產生程式碼

進階 Blockly 使用者應能查看產生的程式碼 (JavaScript、Python、PHP、Lua、Dartt 等),並立即辨識自己編寫的程式。這表示需要額外花費心力,才能讓機器產生的程式碼可讀取。過於寬鬆的括號、數字變數、打碎的空白字元和詳細程式碼範本都有助於產生優雅的程式碼。產生的程式碼應包含註解,且符合 Google 樣式指南的規定。

建議:您對產生的程式碼感到自豪。請向使用者顯示。

10. 語言相依性

想要保持程式碼乾淨的一個副作用是,Blockly 的行為主要是根據跨編譯語言的行為定義。最常見的輸出語言為 JavaScript,但如果 Blockly 跨越編譯為不同語言,則不應嘗試在這兩種語言中維持確切行為,不執行不合理的嘗試。例如,在 JavaScript 中,空字串為 false,但在 Lua 中則為 true。如果為 Blockly 的程式碼執行單一行為模式,無論目標語言為何,均會導致無法維護的程式碼看起來像是來自 GWT 編譯器。

建議:Blockly 不是語言,允許現有語言影響行為。