Lua Không Phải Là C++ - nói dối e blog

Lua Không Phải Là C++

Lua không phải là C++

Lua không phải là C++ Chủ đề này bắt đầu từ một dự án công việc gần đây của cá nhân tôi theo đề nghị của đồng nghiệp Dingdang. Tôi đang hỗ trợ dự án game Đại Đường Vô Song trong lĩnh vực lập trình. Lý do chính là bởi vì engine game DT2 đang được chúng tôi phát triển có tầm quan trọng chiến lược - hiện đang được sử dụng trong ít nhất 4 dự án công ty (3 dự án còn lại đang trong giai đoạn nghiên cứu phát triển chưa công bố).

Hệ thống của DT2 được xây dựng chủ yếu bằng mã Lua, nhưng về thiết kế hệ thống vẫn kế thừa nhiều mã nguồn từ phiên bản Đại Đường tiền nhiệm. Phiên bản gốc được viết bằng C++, để tận dụng lại các mã nguồn này (dù cá nhân tôi cho rằng việc tái sử dụng này không mang lại nhiều giá trị thực tế, nhưng do hoàn cảnh phức tạp nên không tiện bàn sâu), nhóm phát triển DT2 đã xây dựng một tầng trung gian cực kỳ phức tạp để kết nối gần như liền mạch giữa Lua và C++.

Về mặt người dùng, bạn có thể tạo ra các đối tượng lớp trong Lua mà không cần sửa đổi mã C++ gốc, cú pháp sử dụng gần như tương tự C++, thậm chí cho phép kế thừa đa cấp và ghi đè hàm ảo. Đặc biệt hơn, hệ thống còn hỗ trợ mô hình kế thừa đa hình (multiple inheritance).

Do khoảng cách địa lý giữa các nhóm phát triển, mãi đến gần đây tôi mới tiếp cận được tài liệu và mã nguồn liên quan. Trực giác cho tôi thấy đây là một lớp kết nối quá dày đặc, cần phải loại bỏ ngay. Nếu không phải vì hàng loạt lỗi phát sinh trong giai đoạn thử nghiệm Vô Song, có lẽ sẽ ít người đồng tình với quan điểm này. Tuy nhiên thực tế cho thấy dù lớp kết nối này được triển khai hoàn hảo, việc sử dụng nó một cách chính xác gần như bất khả thi. Một lớp trung gian phức tạp như vậy rất khó đảm bảo tính ổn định.

Trong thời gian qua, nhờ nỗ lực không ngừng của đội ngũ kỹ thuật (tôi chỉ đóng vai trò phụ trong việc sửa lỗi), các vấn đề nghiêm trọng đã được khắc phục phần lớn. Tuy nhiên để tiến hành cải tiến vừa phải, chúng tôi cần hành động. Qua trao đổi với các kỹ sư tiền nhiệm, tôi hiểu rõ lý do tại sao họ phải xây dựng hệ thống theo cách này - xuất phát từ sự thiếu hiểu biết về Lua và nhu cầu cấp thiết tái sử dụng mã C++. Dù vậy, tôi vẫn muốn nhấn mạnh: giải pháp tốt nhất là trước tiên phải xác định rõ vấn đề có thực sự tồn tại hay không. Đôi khi “không làm gì cả” lại là lựa chọn khôn ngoan nhất.

Trông bề ngoài, lớp kết nối này được thiết kế rất tinh vi khi che giấu hoàn toàn chi tiết máy ảo Lua. Các lập trình viên C++ có thể làm việc mà không cần biết đến sự tồn tại của Lua, ngược lại mã Lua cũng không cần quan tâm đến việc lớp đó được triển khai bằng C++. Trong môi trường Lua, bạn vẫn có thể kế thừa và mở rộng mô hình đối tượng C++ một cách hoàn hảo.

Về phía C++, mã nguồn thể hiện trình độ chuyên môn cao với việc sử dụng linh hoạt template để tối ưu hóa khả năng tái sử dụng, kết hợp hiệu quả các container STL và con trỏ thông minh để đảm bảo độ ổn định nền tảng.

Nếu không vì một lỗi nhỏ trong quản lý vòng đời đối tượng giữa bộ đếm tham chiếu C++ và cơ chế GC của Lua, có lẽ hệ thống này vẫn sẽ tiếp tục được sử dụng và tôi cũng không cần tham gia vào việc đánh giá mã nguồn.

Đúng vậy, các lỗi kỹ thuật có thể dần được sửa chữa, sai sót thiết kế có thể điều chỉnh với chi phí hợp lý. Nhưng chúng ta cần đặt câu hỏi lớn hơn: Liệu việc mô phỏng mô hình hướng đối tượng C++ trong Lua có thực sự cần thiết?

Hướng đối tượng không phải là đặc trưng độc quyền của C++. Điều này không phải lỗi của C++, bởi ngôn ngữ này chỉ đang thể hiện theo cách riêng của nó. Chúng ta nên tìm kiếm cách biểu đạt phù hợp với bản chất của Lua, giống như Ruby on Rails đang làm với Ruby.

Tất nhiên, việc đào tạo lập trình viên mới cho ngôn ngữ mới luôn khó khăn hơn so với việc mô phỏng một ngôn ngữ thành dạng khác. Nếu chúng ta cứ dùng tư duy viết C++ để lập trình Lua, khi quyết định viết lại game bằng Lua, chúng ta sẽ không chỉ mất đi hiệu năng mà còn đánh mất nhiều giá trị khác.

Trong chuyến công tác Quảng Châu gần đây, tôi được biết nhóm Tây Du đã cải tiến thiết kế server Đại Thoại và Mộng Hoàn, tách riêng xử lý kết nối thành tiến trình độc lập, giúp nâng cao hiệu năng server đáng kể. Hiện tại server Mộng Hoàn đã đạt mức hỗ trợ 10,000 người dùng đồng thời trên một máy chủ.

Tiếc thay, server Đại Thoại 3 vẫn chỉ dừng ở mức 3,000 người dùng/máy. Dù có yếu tố logic phức tạp hơn, nhưng nguyên nhân cốt lõi nằm ở việc Đại Thoại 3 sử dụng Lua - ngôn ngữ có khả năng biểu đạt mạnh mẽ hơn. Điều này khiến lập trình viên vô tình áp dụng phong cách C++ vào Lua, trong khi mã nguồn LPC của Mộng Hoàn lại gần với C hơn.

Không phải C++ chậm hơn C - với ngôn ngữ biên dịch, C++ thậm chí có thể nhanh hơn C. Nhưng với ngôn ngữ thông dịch động, phong cách lập trình kiểu C++ sẽ làm giảm hiệu năng nghiêm trọng. Metatable trong Lua từ phiên bản 5 trở đi là một tính năng tuyệt vời, nhưng mọi tính năng mạnh mẽ đều có nguy cơ bị lạm dụng. May mắn thay Lua vẫn là ngôn ngữ đơn giản. Nếu một ngày Ruby trở nên phổ biến trong ngành phát triển game, tôi không dám tưởng tượng hậu quả sẽ ra sao ;)

Với các lập trình viên C/C++ mới tiếp cận Lua, lời khuyên đầu tiên của tôi thường là: Hãy tìm hiểu Lisp/Scheme, vì Lua mang nhiều gen Scheme hơn là C. Hoặc thử chơi với Haskell để hiểu rõ lập trình hàm. C++ có thể mô phỏng lập trình hàm qua template, nhưng ít người sử dụng. Khi bước vào thế giới Lua, bạn cần nghiêm túc tiếp cận tư

0%