7 điểm bởi GN⁺ 2025-05-07 | 4 bình luận | Chia sẻ qua WhatsApp
  • Tác giả, người đã dùng C++ hơn 20 năm, giới thiệu cơ duyên khiến mình khám phá lại các ưu điểm của Rust thông qua bài nói chuyện của Matt Godbolt
  • Trong C++, những sai sót do nhầm lẫn kiểu không được trình biên dịch phát hiện đầy đủ, nhưng Rust ngăn chặn mạnh mẽ ngay từ thời điểm biên dịch
  • Rust có thiết kế thuận lợi cho việc ngăn chặn lạm dụng API, chứ không chỉ dừng ở an toàn bộ nhớ đơn thuần
  • Đặc biệt, ngay cả trong xử lý đầu vào lúc chạy, Rust cũng buộc phải xử lý lỗi một cách tường minh, giúp giảm rủi ro
  • Đây là ví dụ cho thấy thiết kế ngôn ngữ có thể trở thành công cụ mạnh mẽ để ngăn lỗi của lập trình viên

Mở đầu

  • Bài nói chuyện "Correct by Construction" của Matt Godbolt làm nổi bật vấn đề trong thiết kế API của C++, đồng thời cũng phù hợp với triết lý của Rust
  • Đây là tài liệu nhập môn tốt để hiểu các điểm mạnh của Rust

What's in a type — giới hạn của C++

  • Một chữ ký hàm như void sendOrder(const char *symbol, bool buy, int quantity, double price) rất dễ phát sinh lỗi
  • Nếu chỉ dùng các kiểu cơ bản như bool, int, double, thì ngay cả khi truyền nhầm kiểu, trình biên dịch cũng không cảnh báo
  • Bí danh kiểu như using Price = double không thực sự tạo ra sự phân biệt kiểu
  • Sau khi dùng class và constructor explicit để tạo Quantity, Price, trình biên dịch có thể bắt được một số lỗi, nhưng:
    • Giá trị âm vẫn được chấp nhận, và điều này chỉ trở thành vấn đề ở runtime
    • Có thể dùng static_assert và template để ép kiểm tra ở thời điểm biên dịch
    • Nhưng các phép chuyển đổi runtime như atoi vẫn có thể gây tràn số nguyên, và trình biên dịch không phát hiện được

Rust khác như thế nào?

  • Ngay cả với cùng một định nghĩa hàm, Rust cũng hiển thị lỗi không khớp kiểu một cách rõ ràng ngay lúc biên dịch
  • Việc định nghĩa kiểu mới như struct Price(pub f64); struct Quantity(pub u64); cũng đơn giản, đồng thời ngăn đầu vào âm một cách tự nhiên
  • Với chuyển đổi chuỗi runtime như &quot;string&quot;.parse::<u64>(), Rust cũng yêu cầu xử lý lỗi một cách tường minh
  • Nếu ép mở gói giá trị bằng .expect(), ứng dụng có thể crash lúc chạy, nhưng điều này được nhấn mạnh là vẫn tốt hơn lỗi im lặng của C++

Kết luận

  • Rust bảo vệ lập trình viên không chỉ bằng an toàn bộ nhớ mà còn qua ngăn lạm dụng API, kiểm tra lúc biên dịch và hệ thống kiểu rõ ràng
  • Điều này cho thấy sức mạnh của thiết kế ngôn ngữ trong việc ngăn lỗi của lập trình viên từ sớm
  • Người mới học Rust có thể gặp khó khi phải vật lộn với borrow checker, nhưng điều đó sẽ được giải quyết theo thời gian
  • Dù C++ đã phát triển rất nhiều về mặt lịch sử, nó vẫn bộc lộ hạn chế trong việc mang lại mức an toàn và sự rõ ràng mang tính nền tảng như Rust

Tham khảo

4 bình luận

 
cronex 2025-05-08

Phần lớn những điểm thường được nêu là nhược điểm của C++ xem ra chủ yếu là những thứ vẫn được giữ lại vì tính tương thích với ngôn ngữ C. Liệu có thể bỏ tính tương thích với C và thay đổi để có thể phát triển theo hướng đó không?

 
coremaker 2025-05-08

Giá mà nó không cung cấp unsafe thì có lẽ đã tốt hơn.

 
codemasterkimc 2025-05-08

Ngôn ngữ gốc rễ = Rust

 
GN⁺ 2025-05-07
Ý kiến trên Hacker News
  • Ưu điểm lớn nhất của Rust là kiểu Result, giúp thống nhất cách lan truyền lỗi. Điểm hấp dẫn là không cần phải bận tâm tới xử lý ngoại lệ hay nhiều kiểu trả về lỗi khác nhau

    • Nhờ cú pháp rút gọn ? và giao diện hàm mang tính hàm của Result, việc xử lý lỗi trở nên thú vị và dễ làm hơn
    • So với cách xử lý lỗi phức tạp của C++, điều gây khó chịu là sự thiếu nhất quán
  • Có rất nhiều bất mãn với C++. Đặc biệt, vấn đề là phải nhớ quá nhiều quy tắc, và chỉ cần sai một điều là mã có thể trở nên dễ tổn thương

    • Để nâng cao độ an toàn của C++, cần một cách tiếp cận tương tự như phương thức an toàn của Rust
  • Mã C++ hiện đang viết khá giống Rust. Nó dùng kiểu tường minh và mạnh, cùng với quản lý vòng đời rõ ràng

    • Trình biên dịch Rust hữu ích hơn trong việc bắt bug và báo lỗi
  • Vấn đề chuyển đổi ngầm trong C++ là vấn đề của thư viện hơn là của ngôn ngữ

    • Ngay trong C++ cũng có thể triển khai các tính năng tương tự Rust, nhưng cần có sự hỗ trợ từ thư viện
  • Rust không có tham số từ khóa hay tuple có tên, nên việc dùng struct Args/Options khá bất tiện

  • Tùy chọn -Wconversion có thể bắt được một số vấn đề chuyển đổi nhất định, nhưng không áp dụng cho mọi trường hợp

    • Ví dụ, việc chuyển 1000.0 thành 1000 được coi là không làm mất độ chính xác
  • Điểm Rust tốt hơn là không có chuyển đổi số ngầm. Trong C++, nên tránh dùng atoi và thay vào đó dùng các hàm chuyển đổi của STL

  • Các tính năng tương tự ràng buộc của SQL hoặc kiểu tùy chỉnh và validator của pydantic thì Rust hay Golang vẫn chưa có

  • Nếu quan tâm tới podcast lập trình "Two's Complement" của Matt và Ben Rady thì rất đáng nghe thử