Tập 13: Rust đúng, nhưng khó

Lần đầu tiên đối mặt với bộ kiểm tra mượn (borrow checker) của Rust, nhiều lập trình viên trải qua một cảm xúc rất con người: không phải sự ngưỡng mộ hệ thống kiểu tuyệt vời, mà là sự ức chế: “Tại sao cái máy này không cho tôi chạy đoạn code rõ ràng là logic đúng này?”

Tôi hoàn toàn thấu hiểu cảm giác đó. Bạn đang tập trung giải một bài toán thực tế. Trong tư duy của bạn, dữ liệu vẫn còn sống, tham chiếu vẫn hoàn toàn hợp lệ, và đoạn mã chỉ thiếu vài dòng nữa là hoàn tất. Nhưng trình biên dịch lại kiên quyết chặn cửa bằng một thông báo lỗi dài về lifetime, move semantics hoặc mutable borrow. Nếu đã quen viết C, bạn cảm thấy mình bị tước đi quyền năng kiểm soát phần cứng. Nếu đã quen Java hay Go, bạn thấy mình đang phải tự tay giải quyết một bài toán quản lý bộ nhớ phiền toái mà runtime vốn có thể tự xử lý hộ đằng sau hậu trường.

Nhưng sau những cơn bực dọc ban đầu, Rust đặt lên bàn một thành tựu công nghệ đột phá: an toàn bộ nhớ tuyệt đối (memory safety) mà không cần đến bộ thu gom rác (GC) chạy ngầm mặc định. Quyền sở hữu (ownership), borrowing và lifetimes cung cấp cho compiler đủ thông tin tĩnh để triệt tiêu toàn bộ các lỗi use-after-free, dangling pointer và data race từ compile time. Đó không phải là mẹo cú pháp bề ngoài; đó là sự thay đổi hoàn toàn bản chất hợp đồng giữa người viết code và máy tính.

Rust đúng ở chỗ nó từ chối giả vờ rằng vòng đời bộ nhớ (lifetimes) không tồn tại. Mọi dữ liệu đều có vòng đời thực tế. Trong C, vòng đời ấy nằm mơ hồ trong đầu lập trình viên và phụ thuộc vào trí nhớ của họ. Trong Java hay Go, nó được runtime quản lý ngầm thông qua reachability. Rust đưa toàn bộ câu chuyện ấy lên compile time và biến nó thành một phần của hệ thống kiểu có thể kiểm chứng toán học.

Độ khó xuất hiện khi mô hình lý thuyết chính xác của compiler tràn hoàn toàn lên bề mặt trải nghiệm viết code hàng ngày. Trong code đơn giản, Rust tự động suy luận rất thông minh. Nhưng khi tham chiếu đi qua struct, qua biên giới các API hoặc nhiều luồng thực thi, người viết bắt buộc phải bắt đầu đặt tên cho lifetimes như 'a, hiểu rõ thế nào là variance, reborrowing, interior mutability và hàng loạt khái niệm lý thuyết kiểu nâng cao khác. Các khái niệm ấy đều có lý do kỹ thuật cực kỳ chính đáng để tồn tại. Nhưng tổng hợp toàn bộ các lý do ấy lại tạo ra một rào cản học tập khổng lồ cho lập trình viên.

DUY không được phép tự mãn coi mình thông minh hơn Rust. Chưa có bất kỳ bằng chứng thực tế nào cho điều đó. Rust đã trải qua nhiều năm va đập thực tế ở production, có cộng đồng lớn, hệ sinh thái đồ sộ và đã sửa chữa hàng vạn góc cạnh thô ráp mà DUY thậm chí chưa từng chạm tới. Điều DUY có quyền làm chỉ là đặt ra một câu hỏi nghiên cứu nghiêm túc: "Liệu có thể giữ nguyên các bảo đảm an toàn bộ nhớ tĩnh ấy, nhưng thay đổi hoàn toàn cách con người tiếp xúc và tương tác với chúng không?"

Hướng đi của DUY là để common case (các trường hợp phổ biến) được tự động suy luận (inference) nhiều hơn, sử dụng bộ ba khái niệm owned, viewregion gần gũi với ý định tự nhiên của con người, đồng thời xây dựng hệ thống diagnostics mang tính hướng dẫn và định vị thông minh. Thay vì bắt lập trình viên phải mô tả mọi quan hệ lifetime chi tiết, trình biên dịch chỉ nên yêu cầu họ khai báo rõ ràng ở ranh giới các module (boundaries) nơi vòng đời thực sự mơ hồ hoặc có tác động lớn đến kiến trúc.

Đây là một mục tiêu nghiên cứu nghiêm túc, chưa phải là một chiến thắng. Nếu suy luận tự động quá đà làm thông báo lỗi trở nên mơ hồ khó đoán, DUY sẽ đổi một loại phức tạp nhìn thấy lấy một loại phép thuật vô hình đáng sợ hơn. Nếu region quá thô, đỉnh bộ nhớ (memory peak) sẽ tăng vọt. Nếu bộ kiểm tra view escape yếu ớt, an toàn bộ nhớ chỉ còn là khẩu hiệu suông. Muốn khẳng định mình dễ tiếp cận hơn Rust, DUY cần các nghiên cứu usability chi tiết trên người dùng thật sự; mọi ý kiến chủ quan của tác giả ngôn ngữ đều vô giá trị.

Tôi biết ơn Rust vì nó đã khai phá ra một con đường khả thi và công khai sòng phẳng cái giá phải trả của con đường ấy. DUY không chạy trốn borrow checker. DUY cần học hỏi sâu sắc vì sao nó lại nghiêm khắc đến thế, rồi tìm kiếm giải pháp để sự nghiêm khắc ấy giống như một người thầy thông thái hướng dẫn lập trình viên, thay vì một nhân viên an ninh chỉ biết lạnh lùng lắc đầu từ chối.


Bình luận (0)

Đang tải bình luận...