无标题 - nói dối e blog

无标题

Cảm giác tốt hơn nhiều rồi

Cảm giác tốt hơn nhiều rồi

Tôi cảm thấy khá hơn nhiều rồi. Thực ra tôi chưa từng tự tay viết một dự án quy mô lớn nào bằng Lua cả. Những dự án vượt quá 5.000 dòng mã đều được viết bằng C hoặc C++. Vài ngày gần đây tôi mới thực sự làm được thứ gì đó phức tạp. Sau nhiều lần chỉnh sửa và tinh giản, sản phẩm cuối cùng vừa vặn khoảng 3.000 dòng (sai số chỉ vài chục đơn vị). Trong đó, phần module nền tảng viết bằng C chiếm hơn 900 dòng (chỉ là việc đóng gói socket API và mã hóa/giải mã luồng byte), phần còn lại đều do tôi thiết kế và triển khai bằng Lua.

Thú thật, 2.000 dòng mã cũng chẳng đáng là bao. Nhưng biết đâu, hệ thống wiki Sputnik được viết bằng Lua cũng chưa đến 2.000 dòng đâu. Lua có một đặc tính rất riêng, chỉ khi sử dụng lâu dài mới cảm nhận được. Nó khác biệt rõ rệt so với những ngôn ngữ động phổ biến như Python hay Ruby. Trước đây tôi chọn Lua chỉ vì những lý do hời hợt như nhẹ và hiệu suất cao, dù điều đó cũng quan trọng, nhưng nắm bắt được bản chất ngôn ngữ mới là yếu tố then chốt.

Không trường học nào dạy Lua - thứ ngôn ngữ nhỏ bé này. Ngôn ngữ giảng dạy thường là C, C++, Java (hoặc cổ điển hơn là Fortran, Lisp?). Gần đây nghe nói có trường dạy Python, nhưng tôi nghĩ Lua khó có cửa vào giảng đường. Phần lớn lập trình viên dùng Lua đều tự học, từng sử dụng ngôn ngữ khác, đặc biệt là C/C++. Điều này dễ hiểu vì Lua không có nhiều thư viện trưởng thành như Python, muốn áp dụng vào dự án thực tế bắt buộc phải viết mở rộng bằng C.

Có lẽ tương lai kho thư viện Lua sẽ ngày càng phong phú, lập trình viên không còn phải tự tay viết module mở rộng. Nhưng theo tôi, hiện trạng này cũng không hẳn xấu. Chính việc tự mình triển khai giúp ta hiểu rõ bản chất, từ hiệu năng đến cách sử dụng tối ưu. Ngay cả mã nguồn Lua cũng không quá đồ sộ, đáng để nghiên cứu kỹ lưỡng.

Lua có thiết kế cực kỳ tinh gọn, kiểu dữ liệu ít đến mức tối giản - thêm một chút sẽ thừa thãi, bớt đi lại thiếu sót. Điều này khiến chúng ta không thể đổ lỗi cho thiết kế ngôn ngữ khi dùng không tốt. Chỉ cần hiểu sâu sắc là có thể vận dụng linh hoạt.

Gần như mỗi lập trình viên Lua đều có phong cách viết code khác biệt. Chúng ta có thể xây dựng hệ thống theo hướng đối tượng, dùng như ngôn ngữ hàm, hay đơn giản là mô tả dữ liệu (đây chính là mục đích ban đầu của Lua 1.0). Tuy nhiên điều này gây khó khăn cho dự án lớn nhiều người tham gia. Nhưng thực tế, dự án lớn đến đâu đi nữa, các kiến trúc sư vẫn có thể chia nhỏ thành component độc lập, rồi dùng Lua để triển khai nhanh chóng. Thay vì dùng ngôn ngữ khác cần hàng chục nghìn dòng, Lua chỉ cần 2-3 nghìn dòng là xong.

Trong Lua, kiểu dữ liệu phức tạp chỉ có table và userdata. Userdata thường đơn giản, chỉ dùng cho dữ liệu cần hiệu suất cao, được xử lý ở tầng C nên dễ cách ly (dĩ nhiên nếu dùng không cẩn thận vẫn phát sinh vấn đề, thường do các lập trình viên mới xem nhẹ Lua chỉ là keo dán mã C).

Thực sự phức tạp chỉ có table - chúng liên kết chéo nhau tạo thành mạng quan hệ sống/chết phức tạp. Các kiểu dữ liệu liên quan đến thu gom rác như string, closure (và thread thêm sau này) lại không gây nhiều rắc rối.

Độ phức tạp của kiểu dữ liệu ảnh hưởng trực tiếp đến quá trình thu gom rác. Chúng ta biết rằng Lua không có lỗi tràn bộ nhớ hay rò rỉ như C, nhưng tôi không tin vào “thuốc tiên” nào cả. Thiết kế không hoàn thiện sẽ khiến vấn đề bị ẩn giấu.

Ở C/C++ chúng ta quan tâm bố trí bộ nhớ và quản lý tài nguyên, thì với Lua cũng cần hiểu rõ dữ liệu sinh ra khi nào, chết đi ra sao, làm sao giảm tải cho garbage collector. Cái khó của việc sau không kém cái trước, vì lỗi C thường gây crash rõ ràng, còn Lua chỉ biểu hiện qua việc tiêu hao tài nguyên, những sai lầm không gây crash mới là điều đáng sợ nhất.

Khi lập trình viên quan tâm hiệu năng nhận ra mỗi lần tạo table mới, closure mới hay nối chuỗi đều sinh ra đối tượng mới. Dù chỉ tồn tại tạm thời vài chu kỳ, cũng tạo áp lực cho hệ thống thu gom rác. Nếu họ cố gắng giảm thiểu việc này, đồng thời kiểm soát quy mô code, hệ thống ổn định sẽ tự hình thành. Đây chính là trải nghiệm của tôi trong nửa tháng qua với Lua.

Ngôn ngữ tưởng chừng chỉ là chi tiết nhỏ trong thiết kế phần mềm, nhưng lại ảnh hưởng sâu sắc đến tư duy thiết kế. Là lập trình viên, khi quá phụ thuộc vào một ngôn ngữ duy nhất, chúng ta cần tự cảnh tỉnh và thử nghiệm những góc nhìn mới.

Vài điều khác để chia sẻ thêm: Dù rất bận rộn, hôm nay tôi mới có thời gian viết dài thế này. Dự án tay tôi đã hoàn thành phần của mình, phần còn lại phụ thuộc vào đồng nghiệp, cần điều chỉnh giao thức truyền thông. Nhưng vì cuối tuần, nguyên tắc của tôi là không bắt ép ai làm ngoài giờ trừ khi bất khả kháng. Trước khi viết dòng code cuối cùng, tôi đã cân nhắc kỹ những phần có thể làm trước, giờ chỉ còn chờ thứ Hai.

Tôi luôn chia nhỏ dự án lớn thành các module nhị phân độc lập, phân công từng người phụ trách. Đây là mô hình hợp tác duy nhất tôi công nhận cho dự án cỡ trung. Ở phía client game thường là các module độc lập với vài interface C tối giản; phía server thì chia thành nhiều tiến trình riêng biệt, giao tiếp qua giao thức mạng.

Quá nhiều trải nghiệm khiến tôi mất niềm tin vào hợp tác ở cấp độ mã nguồn. Có lẽ phương pháp cặp đôi (pair programming) của XP tốt hơn, nhưng lần thử trước khiến tôi thấy mệt mỏi. Tôi thích tự làm một mình hơn, dĩ nhiên前提是具备足够 năng lực và thái độ tích cực với lập trình để đảm bảo chất lượng code.

Làm sao giữ chất lượng code? Bí quyết của tôi là đơn giản hóa mọi thứ, viết code ngắn gọn (mỗi file độc lập không quá 500 dòng), loại bỏ mọi thứ không cần thiết. Ngăn bug không phát sinh còn dễ hơn né tránh cẩn thận. Nếu không được thì viết lại, đừng debug quá nhiều. Đừng dành quá nhiều thời gian cho một đoạn code, phải nhanh chóng giải quyết xong. Nếu tốn quá nhiều công sức, chắc chắn có vấn đề trong thiết kế. Thế giới có nhiều việc phức tạp, nhưng không bao gồm việc triển khai module có yêu cầu rõ ràng :D.

Làm sao hoàn thành dự án hiệu quả? Hãy chọn những lập trình viên xuất sắc nhất, dù chỉ một vài người. Đừng nghĩ nhỏ việc thành lớn. Tập trung họ lại và hoàn thành trong 1-2 tháng. Nếu không tìm được người giỏi, hãy tự tin

0%