21 điểm bởi tsboard 2024-07-24 | 5 bình luận | Chia sẻ qua WhatsApp

Tôi đã dùng Rust được khoảng 10 năm và thực sự rất yêu ngôn ngữ này. Nhưng vẫn có một vài điểm gây thất vọng. Dưới đây là danh sách đó.

1. Vấn đề của Result<T, E>

Việc xử lý lỗi trong Rust rõ ràng và mang tính bắt buộc là một điều tuyệt vời. Tuy nhiên, khi dùng thực tế thì có khá nhiều bất tiện.

  • Khó khăn đối với tác giả thư viện: Quá trình tạo kiểu lỗi mới và chuyển đổi chúng khá phiền phức. Mỗi khi thêm dependency, việc phải bổ sung kiểu lỗi của từng hàm vào kiểu lỗi wrapper lại càng đặc biệt rườm rà.
  • Sự phiền toái trong mã ứng dụng: Điều quan trọng thường không phải là vì sao hàm thất bại, mà là truyền lỗi lên tầng trên và hiển thị kết quả cho người dùng. Khác với Java, Rust không cung cấp backtrace trong quá trình truyền lỗi, nên rất khó xác định nguyên nhân gốc rễ của vấn đề.

2. Độ linh hoạt của hệ thống module

Hệ thống module của Rust quá linh hoạt nên đôi khi lại trở thành bất tiện.

  • Quá linh hoạt: Có thể tái xuất kiểu hoặc tinh chỉnh rất chi tiết mức độ truy cập, nhưng điều này có thể dẫn đến việc vô tình làm lộ các kiểu mà bạn không muốn công khai.
  • Vấn đề với orphan rule: Việc chia dự án thành nhiều crate thường được khuyến nghị, nhưng orphan rule đôi khi lại cản trở điều đó.

3. Thời gian biên dịch và công cụ IDE

Thời gian biên dịch của Rust và việc kiểm tra lỗi của công cụ IDE quá chậm.

  • Thời gian biên dịch dài: Trong các dự án lớn, chỉ cần sửa một hàm là toàn bộ crate lại bị biên dịch lại, điều này rất kém hiệu quả.
  • Tốc độ phản hồi chậm của IDE: Rust analyzer cho cảm giác như đang lập chỉ mục lại toàn bộ dự án sau mỗi lần gõ phím, và điều này đặc biệt là vấn đề trong các dự án lớn.

Kết luận

Rust là ngôn ngữ tôi yêu thích nhất, nhưng những điểm gây thất vọng này vẫn tồn tại. Tôi cũng tò mò không biết những người dùng khác có gặp các vấn đề tương tự hay không.

5 bình luận

 
ranolp 2024-07-28

Về xử lý lỗi, sẽ rất tiện nếu dùng snafu/thiserror cho thư viện và cài eyre/anyhow để dùng cho ứng dụng.

 
y15un 2024-07-26

Nỗi khó khăn của tác giả thư viện: [..snip..] Mỗi khi thêm một dependency, việc phải bổ sung kiểu lỗi của từng hàm vào kiểu lỗi wrapper lại đặc biệt phiền phức.

Đoạn này đúng là chạm đến nỗi đau thật sự. Tôi đã không ít lần tạo một enum lỗi riêng cho crate, rồi mỗi lần lại phải viết impl From<ExtError> for Error cho các kiểu lỗi kéo vào từ dependency và nghĩ rằng 'phiền muốn chết'...

 
eususu 2024-07-26

Có lẽ vì tôi vẫn chưa thực sự bắt đầu nên lại muốn được cảm nhận kiểu thất vọng này.
Cảm ơn bài viết hay~

 
undercat 2024-07-25

Cảm ơn vì bài viết hay!

 
tsboard 2024-07-24

Tôi bổ sung thêm vì có vẻ bình luận dưới đây sẽ hữu ích về thời gian biên dịch dài: (by pr4wl)

Nếu Rust analyzer phải thực hiện tái biên dịch dài mỗi khi có thay đổi, thì có lẽ là do các tính năng hoặc biến môi trường dùng khi build ứng dụng khác với những gì nó đang dùng. Theo mặc định, RA sử dụng cùng thư mục target với cargo build để lưu build artifact, và nếu thực hiện các bản build không tương thích với nhau thì nó sẽ liên tục phải chạy full build.

Vấn đề này đặc biệt thường xảy ra với Bevy khi bạn dùng tính năng bevy/dynamic_linking cho bản build nhưng không dùng cho Rust analyzer.

Cách giải quyết đơn giản nhất là bảo RA dùng một thư mục target khác. Bạn có thể xem thêm chi tiết liên quan tại rust-analyzer.cargo.targetDir.

Một cách khác là cấu hình để mọi tính năng và biến môi trường đều giống nhau, nhờ đó chúng có thể tái sử dụng build artifact của nhau. Tuy nhiên, việc này có thể khá khó xử lý.