Khối tuỳ chỉnh: Hướng dẫn về kiểu

Trong những năm qua, đội ngũ Blockly và Blockly Games đã rút ra nhiều bài học áp dụng cho những nhà phát triển đang phát triển các quy tắc chặn mới. Sau đây là một tập hợp những lỗi chúng tôi mắc phải hoặc những lỗi mà người khác thường mắc phải.

Đây là những bài học chung mà chúng tôi đã rút ra khi sử dụng phong cách hình ảnh của Blockly và có thể không áp dụng cho mọi trường hợp sử dụng hoặc thiết kế. Ngoài ra còn có các giải pháp khác. Đây là Ngoài ra, đây không phải là một danh sách đầy đủ các vấn đề mà người dùng có thể gặp phải và cách tránh chúng. Mỗi trường hợp có một chút khác biệt và có ưu điểm riêng.

1. Câu lệnh có điều kiện và câu lệnh lặp

Các quy tắc chặn khó nhất đối với người dùng mới là các điều kiện và vòng lặp. Nhiều môi trường dựa trên khối nhóm cả hai khối này vào cùng một phần "Kiểm soát" danh mục, với cả hai khối có cùng hình dạng và cùng màu sắc. Điều này thường gây khó chịu vì người dùng mới nhầm lẫn hai nhóm này. Blockly đề xuất di chuyển các điều kiện và vòng lặp vào 'Logic' riêng biệt và "Vòng" các phân loại, mỗi loại có một màu riêng. Điều này làm rõ rằng đây là những ý tưởng riêng biệt có hành vi khác nhau, mặc dù có hình dạng tương tự nhau.

Đề xuất: Tách biệt các điều kiện và vòng lặp.

2. Danh sách dựa trên một cơ sở lưu trú

Các lập trình viên mới bắt đầu phản ứng không tốt khi gặp các danh sách từ 0 đầu tiên bất cứ lúc nào. Kết quả là, Blockly theo sát cách Lua và Lambda Moo bằng cách lập danh sách và lập chỉ mục chuỗi.

Để sử dụng Blockly nâng cao hơn, các danh sách dựa trên 0 được hỗ trợ để tạo chuyển sang văn bản dễ dàng hơn. Dành cho độc giả trẻ tuổi trở lên bạn vẫn nên dùng tính năng lập chỉ mục một lần.

Đề xuất: Một là số đầu tiên.

3. Hoạt động đầu vào của người dùng

Có ba cách để lấy thông số từ người dùng. Một trình đơn thả xuống là hạn chế nhất và phù hợp với các hướng dẫn và bài tập đơn giản. Trường nhập dữ liệu cho phép tự do hơn và phù hợp cho nhiều hoạt động sáng tạo hơn. Khối giá trị đầu vào (thường có một khối bóng) mang lại cơ hội tính toán giá trị (ví dụ: một trình tạo ngẫu nhiên) thay vì chỉ là một giá trị tĩnh.

Đề xuất: Chọn phương thức nhập phù hợp với người dùng của bạn.

4. Hình ảnh khối trực tiếp

Tài liệu về khối phải bao gồm hình ảnh của khối mà nó đang đề cập sang. Việc chụp ảnh màn hình rất dễ dàng. Nhưng nếu có 50 hình ảnh như vậy và dịch sang 50 ngôn ngữ, bỗng dưng có 1 người duy trì 2.500 ngôn ngữ hình ảnh tĩnh. Sau đó, bảng phối màu sẽ thay đổi và cần cập nhật 2.500 hình ảnh -- một lần nữa.

Để thoát khỏi cơn ác mộng phải bảo trì này, Blockly Games đã thay thế tất cả ảnh chụp màn hình có các bản sao Blockly chạy ở chế độ chỉ đọc. Kết quả trông giống hệt như hình ảnh nhưng được đảm bảo là mới nhất. Chỉ đọc đã giúp quốc tế hoá trở nên khả thi.

Đề xuất: Nếu bạn hỗ trợ nhiều ngôn ngữ, hãy dùng chế độ chỉ có thể đọc.

5. Bên trái khác của bạn

Phản hồi của trẻ em ở Hoa Kỳ (mặc dù thú vị là không phải từ các quốc gia khác) cho thấy sự nhầm lẫn lan rộng giữa bên trái và bên phải. Vấn đề này đã được giải quyết bằng thêm mũi tên. Nếu hướng là tương đối (ví dụ: với hình đại diện), kiểu mũi tên là rất quan trọng. A → mũi tên thẳng hoặc mũi tên ↱ gây nhầm lẫn khi hình đại diện hướng về phía ngược lại. Hữu ích nhất là vòng tròn mũi tên, ngay cả trong trường hợp góc xoay nhỏ hơn mũi tên biểu thị.

Đề xuất: Bổ sung văn bản bằng các biểu tượng Unicode nếu có thể.

6. Khối cao cấp

Bất cứ khi nào có thể, hãy áp dụng phương pháp cấp cao hơn, ngay cả khi phương pháp đó giúp giảm hiệu suất thực thi hoặc tính linh hoạt. Hãy xem xét biểu thức Apps Script sau:

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

Trong mối liên kết 1:1 giúp giữ lại tất cả các khả năng tiềm năng, thông tin trên biểu thức sẽ được tạo bằng cách sử dụng bốn khối. Tuy nhiên, mục tiêu của Blockly là ở cấp độ cao hơn và sẽ cung cấp một khối đóng gói toàn bộ biểu thức. Mục tiêu là để tối ưu hoá cho 95% trường hợp, ngay cả khi làm cho 5% còn lại khó khăn hơn. Blockly không nhằm mục đích thay thế các ngôn ngữ dựa trên văn bản, nhằm giúp người dùng vượt qua giai đoạn "tìm hiểu" ban đầu để họ có thể sử dụng ngôn ngữ dựa trên văn bản.

Đề xuất: Đừng chuyển đổi toàn bộ API thành các khối một cách mù quáng.

7. Giá trị trả về không bắt buộc

Nhiều hàm trong lập trình văn bản thực hiện một thao tác rồi trả về một giá trị. Giá trị trả về này có thể được hoặc không thể sử dụng. Ví dụ: Hàm pop(). Cửa sổ bật lên có thể được gọi để lấy và xoá phần tử cuối cùng, hoặc có thể được gọi để chỉ xoá phần tử cuối cùng có giá trị trả về đang bị bỏ qua.

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

Các ngôn ngữ dựa trên khối thường không hiệu quả trong việc bỏ qua giá trị trả về. Đáp khối giá trị phải cắm vào một thứ gì đó chấp nhận giá trị. Có để giải quyết vấn đề này.

a) Hướng đến vấn đề. Hầu hết các ngôn ngữ dựa trên khối đều thiết kế ngôn ngữ để tránh những trường hợp này. Ví dụ: Scratch không có bất kỳ khối nào có cả tác dụng phụ và giá trị trả về.

b) Cung cấp hai khối. Nếu khoảng trống trong hộp công cụ không phải là vấn đề, là cung cấp hai đoạn mã cho mỗi loại khối này, một khối có và một khối mà không có giá trị trả về. Nhược điểm là có thể dẫn đến nhầm lẫn hộp công cụ có nhiều khối gần giống hệt nhau.

c) Thay đổi một khối. Dùng trình đơn thả xuống, hộp đánh dấu hoặc chế độ điều khiển khác cho phép để người dùng chọn xem có giá trị trả về hay không. Khối sau đó thay đổi hình dạng tuỳ thuộc vào tuỳ chọn. Ví dụ: nhìn thấy trong khối truy cập danh sách của Blockly.

d) Sử dụng giá trị. Phiên bản đầu tiên của App Inventor đã tạo ra một đường ống đặc biệt chặn ăn bất kỳ giá trị được kết nối nào. Người dùng không hiểu khái niệm và phiên bản thứ hai của App Inventor đã xoá khối ống và thay vào đó, khuyên người dùng chỉ cần chỉ định giá trị cho biến bị loại bỏ.

Đề xuất: Mỗi chiến lược đều có ưu và nhược điểm, hãy chọn chiến lược phù hợp người dùng.

8. Tạo khối

Một số khối có thể yêu cầu số lượng đầu vào thay đổi. Ví dụ: khối phép cộng để tính tổng một tập hợp các số tuỳ ý hoặc một khối if/elseif/else khối bằng một tập hợp các mệnh đề elseif tuỳ ý hoặc một hàm khởi tạo danh sách có số lượng phần tử được khởi tạo tuỳ ý. Có một vài chiến lược, mỗi loại đều có những ưu điểm và nhược điểm riêng.

a) Cách đơn giản nhất là làm cho người dùng tạo thành một khối nhỏ hơn chặn. Ví dụ: thêm ba số bằng cách lồng hai số có hai số các khối cộng. Một ví dụ khác là chỉ cung cấp khối if/else, và khiến người dùng lồng chúng để tạo các điều kiện elseif.

Ưu điểm của phương pháp này là tính đơn giản ban đầu (cả cho người dùng và nhà phát triển). Nhược điểm là trong trường hợp có khoảng không quảng cáo lớn số lần lồng, mã trở nên rất cồng kềnh và khó khăn cho người dùng đọc và duy trì.

b) Một giải pháp thay thế là tự động mở rộng khối để luôn có một khối dữ liệu đầu vào miễn phí ở cuối. Tương tự, khối này sẽ xoá dữ liệu đầu vào cuối cùng nếu có hai đầu vào miễn phí vào cuối. Đây là phương pháp tiếp cận đầu tiên của Nhà sáng chế ứng dụng được sử dụng.

Người dùng của App Inventor trong một vài ứng dụng không thích các ứng dụng chặn tự động phát triển lý do. Đầu tiên, chương trình luôn có dữ liệu đầu vào miễn phí và chương trình "complete" ("hoàn tất"). Thứ hai, chèn một phần tử vào giữa ngăn xếp là vì nó liên quan đến việc ngắt kết nối tất cả các yếu tố bên dưới bản chỉnh sửa và đang kết nối lại chúng. Tuy nhiên, nếu thứ tự không quan trọng và người dùng có thể tạo thoải mái với các lỗ hổng trong chương trình của họ, đây là một lựa chọn rất tiện lợi.

c) Để giải quyết vấn đề lỗ hổng, một số nhà phát triển thêm nút +/- để chặn thêm hoặc xoá thông tin đầu vào theo cách thủ công. Roberta sử dụng hai nút như vậy để thêm hoặc xoá mục nhập ở dưới cùng. Các nhà phát triển khác thêm hai nút vào mỗi nút để thao tác chèn và xoá ở giữa ngăn xếp có thể đã được hỗ trợ. Một số người dùng khác thêm hai nút lên/xuống ở mỗi hàng để sắp xếp lại thứ tự của ngăn xếp có thể được hỗ trợ.

Chiến lược này có nhiều lựa chọn, từ chỉ 2 nút trên mỗi khối, đến 4 nút trên mỗi hàng. Cuối cùng là mối nguy hiểm là người dùng không thể để thực hiện hành động họ cần, nhưng ở đầu kia, giao diện người dùng đã được lấp đầy các nút trông giống như cầu nối của Enterprise.

d) Cách linh hoạt nhất là thêm bong bóng biến đổi vào khối. Chiến dịch này được biểu thị dưới dạng một nút duy nhất mở ra hộp thoại cấu hình chặn. Có thể thêm, xoá hoặc sắp xếp lại các phần tử theo ý muốn.

Nhược điểm của phương pháp này là biến đổi (mutator) không trực quan đối với người dùng mới. Việc giới thiệu về biến đổi cần có một số hình thức hướng dẫn. Các ứng dụng bị chặn nhắm đến trẻ em không được dùng biến thể biến đổi. Mặc dù khi đã được học nhưng chúng là vô giá đối với người dùng thành thạo.

Đề xuất: Mỗi chiến lược đều có ưu và nhược điểm, hãy chọn chiến lược phù hợp người dùng.

9. Tạo mã sạch

Người dùng Advanced Blockly phải có thể xem mã đã tạo (JavaScript, Python, PHP, Lua, Dart, v.v.) và nhận ra ngay chương trình họ viết. Điều này có nghĩa là bạn sẽ phải nỗ lực hơn nữa để giữ lại mã do máy tạo này dễ đọc hơn. Dấu ngoặc đơn thừa, biến số, khoảng trắng bị gạch bỏ và tất cả các mẫu mã chi tiết đều cản trở việc tạo mã thanh lịch. Mã được tạo phải bao gồm cả nhận xét và phải tuân thủ Hướng dẫn quy tắc của Google.

Đề xuất: Tự hào về mã do bạn tạo. Hiển thị hình ảnh đó cho người dùng.

10. Sự phụ thuộc vào ngôn ngữ

Một tác dụng phụ của mong muốn mã sạch là hành vi của Blockly được xác định chủ yếu về cách hoạt động của ngôn ngữ được biên dịch chéo. Nhiều nhất ngôn ngữ đầu ra chung là JavaScript, nhưng nếu Blockly biên dịch chéo sang một ngôn ngữ khác, không nên cố gắng không hợp lý để bảo toàn hành vi chính xác trên cả hai ngôn ngữ. Ví dụ: trong JavaScript, trường chuỗi là false, trong khi ở Lua là đúng. Xác định một mẫu duy nhất để mã của Blockly thực thi, bất kể ngôn ngữ đích là gì dẫn đến mã không thể duy trì trông giống như mã bắt nguồn từ trình biên dịch GWT.

Đề xuất: Blockly không phải là một ngôn ngữ, hãy cho phép ngôn ngữ hiện tại ảnh hưởng đến hành vi.