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

Qua nhiều năm, nhóm Blockly và Blockly Games đã học được nhiều bài học có thể áp dụng cho những người đang phát triển khối mới. Sau đây là danh sách lỗi mà chúng tôi đã mắc phải hoặc những lỗi thường gặp của người khác.

Đây là những bài học chung mà chúng tôi đã học được khi sử dụng kiểu 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 cũng không phải là danh sách đầy đủ những vấn đề mà người dùng có thể gặp phải và cách tránh những vấn đề đó. Mỗi trường hợp đều khác nhau một chút và có những ưu nhược điểm riêng.

1. So sánh có điều kiện và vòng lặp

Khó khăn nhất đối với người dùng mới là điều kiện và vòng lặp. Nhiều môi trường dựa trên khối sẽ nhóm cả hai khối này vào cùng một danh mục "Controls", với cả hai khối có cùng hình dạng và màu sắc. Điều này thường dẫn đến sự thất vọng khi người dùng mới nhầm lẫn hai khối này. Blockly khuyên bạn nên di chuyển các điều kiện và vòng lặp vào các danh mục "Logic" và "Vòng" riêng biệt, mỗi danh mục có một màu khác nhau. Điều này làm rõ rằng đây là những ý tưởng riêng biệt hoạt động theo cách 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 nền tảng

Các lập trình viên mới bắt đầu phản ứng không tốt khi lần đầu gặp danh sách có số 0. Do đó, Blockly tuân theo Lua và Lambda Moo bằng cách lập chỉ mục danh sách và lập chỉ mục chuỗi một.

Để sử dụng tính năng Blockly nâng cao, bạn có thể hỗ trợ danh sách có giá trị từ 0 để giúp chuyển đổi sang văn bản dễ dàng hơn. Đối với những đối tượng trẻ tuổi hoặc người mới chơi, bạn vẫn nên lập chỉ mục một.

Đề xuất: Thứ nhất là con số đầu tiên.

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

Có 3 cách để lấy tham số từ người dùng. Trình đơn thả xuống là lựa chọn 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 bạn tự do hơn và phù hợp cho các hoạt động sáng tạo hơn. Dữ liệu đầu vào khối giá trị (thường có khối bóng đổ) mang lại cơ hội tính toán một 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 dữ liệu 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 các khối mà nó đang tham chiếu đến. Dễ dàng chụp ảnh màn hình. Nhưng nếu có 50 hình ảnh như vậy và ứng dụng được dịch sang 50 ngôn ngữ, thì đột nhiên một hình ảnh duy trì 2.500 hình ảnh tĩnh. Sau đó, bảng phối màu sẽ thay đổi và cần cập nhật lại 2.500 hình ảnh.

Để trích xuất từ cơn ác mộng bảo trì này, Blockly Games đã thay thế toàn bộ ảnh chụp màn hình bằng thực thể của Blockly đang chạy ở chế độ chỉ có thể đọc. Kết quả trông giống như hình ảnh nhưng được đảm bảo là mới nhất. Chế độ chỉ đọc đã mang đến khả năng quốc tế hoá.

Đề xuất: Nếu bạn hỗ trợ nhiều ngôn ngữ, hãy sử 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ị không phải ở các quốc gia khác) cho thấy sự nhầm lẫn ngày càng gia tăng giữa bên trái và bên phải. Vấn đề này đã được giải quyết bằng cách bổ sung mũi tên. Nếu hướng là tương đối (ví dụ: với hình đại diện), thì kiểu mũi tên là rất quan trọng. Mũi tên thẳng → mũi tên thẳng hoặc mũi tên ↱ sẽ gây nhầm lẫn khi hình đại diện hướng về hướng ngược lại. Hữu ích nhất là mũi tên tròn ⟳, ngay cả trong trường hợp góc xoay nhỏ hơn so với mũi tên biểu thị.

Đề xuất: Nếu có thể, hãy bổ sung các biểu tượng Unicode cho văn bản.

6. Khối cấp cao

Bất cứ khi nào có thể, bạn nên sử dụng phương pháp ở cấp độ cao hơn, ngay cả khi điều đó làm giảm hiệu suất hoặc tính linh hoạt của quá trình thực thi. Hãy xem xét biểu thức sau của Apps Script:

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

Trong ánh xạ 1:1 giúp giữ lại tất cả các khả năng tiềm năng, biểu thức trên sẽ được tạo bằng cách sử dụng 4 khối. Tuy nhiên, Blockly hướng đến 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 trường hợp 95%, ngay cả khi điều này khiến 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, mà nhằm giúp người dùng vượt qua đường cong học tập ban đầu để có thể sử dụng các ngôn ngữ dựa trên văn bản.

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

7. Giá trị trả lại hàng không bắt buộc

Nhiều hàm trong lập trình dựa trên văn bản thực hiện một thao tác, sau đó trả về một giá trị. Giá trị trả về này có thể được hoặc không được sử dụng. Ví dụ như hàm pop() của ngăn xếp. Bạn có thể gọi Pop để lấy và xoá phần tử cuối cùng, hoặc chỉ cần xoá phần tử cuối cùng với giá trị trả về 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 phù hợp trong việc bỏ qua giá trị trả về. Khối giá trị phải cắm vào nội dung chấp nhận giá trị đó. Có một số chiến lược để xử lý vấn đề này.

a) Hướng dẫn giải quyết 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ó 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 đề, thì giải pháp đơn giản là cung cấp hai trong số mỗi loại khối này, một có và một không có giá trị trả về. Nhược điểm là tính năng này có thể dẫn đến một hộp công cụ khó hiểu với nhiều khối gần giống hệt nhau.

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

d) Ăn giá trị. Phiên bản đầu tiên của App Inventor đã tạo một khối dấu sổ thẳng đặc biệt ăn mọi giá trị được kết nối. Người dùng không hiểu khái niệm này và phiên bản thứ hai của App Inventor đã xoá khối dấu gạch ngang và thay vào đó đề xuất người dùng chỉ cần chỉ định giá trị cho một biến 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 với người dùng của bạn.

8. Khối tăng trưởng

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

a) Phương pháp đơn giản nhất là khiến người dùng soạn khối từ các khối nhỏ hơn. Ví dụ: cộng 3 số, bằng cách lồng 2 khối cộng 2 số. Một ví dụ khác là chỉ cung cấp các khối if/else và yêu cầu người dùng lồng ghép các khối lệnh này để tạo các điều kiện aggregate.

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

b) Một cách khác là tự động mở rộng khối để luôn có một 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í ở cuối. Đây là phương pháp mà phiên bản đầu tiên của Nhà sáng chế ứng dụng đã sử dụng.

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

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

Chiến lược này là một loạt các tuỳ chọn, từ chỉ 2 nút trên mỗi khối, cho đến 4 nút trên mỗi hàng. Ở một bên là mối nguy hiểm khiến người dùng không thể thực hiện các hành động mà họ cần, phía bên kia, giao diện người dùng chứa đầy các nút đến mức trông giống như chiếc cầu của Enterprise Starship.

d) Phương pháp linh hoạt nhất là thêm bong bóng biến đổi vào khối. Nút 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 cho khối đó. Bạn có thể thêm, xoá hoặc sắp xếp lại các phần tử tuỳ ý.

Nhược điểm của phương pháp này là các biến thể không trực quan đối với những người dùng mới. Để làm quen với biến đổi, bạn cần thực hiện một số hình thức hướng dẫn. Ứng dụng dựa trên khối nhắm mục tiêu đến trẻ nhỏ không được sử dụng biến thể. Mặc dù đã được học, nhưng chúng lại 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 với người dùng của bạn.

9. Tạo mã sạch

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

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

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

Tác động phụ của mong muốn có mã sạch là hành vi của Blockly được xác định phần lớn về hành vi của ngôn ngữ được biên dịch chéo. Ngôn ngữ đầu ra phổ biến nhất là JavaScript, nhưng nếu Blockly biên dịch chéo sang một ngôn ngữ khác, thì không nên thực hiện bất kỳ nỗ lực hợp lý nào để duy trì hành vi chính xác trên cả hai ngôn ngữ. Ví dụ: trong JavaScript, chuỗi trống là false, trong khi trong Lua, chuỗi trống là true. Việc xác định một mẫu hành vi duy nhất để mã của Blockly thực thi bất kể ngôn ngữ đích sẽ dẫn đến việc không thể duy trì mã, 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 có tác động đến hành vi.