Những Ngày Ấy (Mười Chín) - nói dối e blog

Những Ngày Ấy (Mười Chín)

Những ngày tháng ấy (Phần 19)

Nếu không tính các công cụ phụ trợ, riêng phần engine của game “Đại Mộng Tây Du” (bao gồm đồ họa, âm thanh, mạng và giao diện người dùng cùng quản lý đối tượng) do tôi trực tiếp viết bằng C++ đã lên tới hơn 30,000 dòng mã. Đây là con số thống kê chính xác hôm nay tôi vừa kiểm tra lại. Toàn bộ phần mã này đều được viết từ đầu sau khi hoàn thành “Đại Mộng Tây Du 2”, trải qua nhiều lần chỉnh sửa, bổ sung và giữ lại đến hiện tại.

Về phía client của “Đại Mộng”, đóng góp của cụ Quách còn lớn hơn nữa. Ngoài việc giữ lại và chỉnh sửa một số ít mã底层 từ phiên bản “Đại Mộng 2” mà tôi để lại, cụ đã viết toàn bộ phần giao diện Python và phần hỗ trợ logic game bằng C++. Sau khi thiết kế lại, chúng tôi đã làm tốt hơn trước rất nhiều. Mã nguồn cực kỳ gọn gàng nhưng lại hoàn thành được nhiều chức năng hơn hẳn. Tôi nhớ mang máng tổng số dòng C++ lúc đó không vượt quá 50,000 (hiện không còn số liệu cụ thể). Trong khi đó, client của “Đại Mộng 2” gồm 27,000 dòng cho engine đồ họa và âm thanh, cùng 31,000 dòng cho phần logic, mạng và giao diện.

Tôi luôn tin tưởng rằng với kiến trúc hợp lý, mã nguồn nên tinh gọn chứ không nên phình to vô độ. Việc viết mã ngắn gọn là kết quả tự nhiên từ việc tránh lặp lại, chứ không phải cố ý theo đuổi số lượng dòng mã ít hay nhiều. Đối với client (cũng như server) của game online, quy mô trên 100,000 dòng C++ là không cần thiết. Về bản chất, game online là dự án nhỏ, đúng không? Nếu ai đó biến một dự án nhỏ thành dự án khổng lồ, thì việc xảy ra vấn đề là điều tất yếu.

Cụ Quách là người vô cùng chăm chỉ, luôn chủ động hoàn thiện chương trình. Khi đó cụ đã cải tiến định dạng file bản đồ, viết lại công cụ tạo dữ liệu bản đồ. Đối với những thứ đã hoàn thành và hoạt động ổn định, cụ vẫn không hài lòng mà tiếp tục cải tiến. Những lập trình viên như vậy cực kỳ quý giá cho dự án.

Những sản phẩm được tạo ra từ tinh thần cầu toàn như thế này, gần như không thể đảm bảo có người làm nếu chỉ dựa vào quản lý dự án. Đây cũng là lý do sau này dù làm quản lý dự án, tôi vẫn nhất định phải trực tiếp viết mã. Nếu chỉ xét dự án ở góc độ hoàn thành chức năng, chúng ta chỉ đạt mức “đạt yêu cầu”, chứ chưa thể gọi là xuất sắc. Huống hồ nhiều yếu tố chất lượng, chi tiết khó định lượng - mức độ đầu tư đến đâu sẽ mang lại lợi ích bao nhiêu, mối quan hệ này không ai lý giải rõ ràng được.

Muốn biến dự án game thành dây chuyền sản xuất, đặt đồng hồ báo giờ rồi đến lúc thu hoạch, đó hoàn toàn là trò cười, chỉ tồn tại trong ảo tưởng của các nhà đầu tư.

Nhiều chi tiết hình ảnh trong “Đại Mộng” không phải do các策划 viên chuyên trách viết trong tài liệu yêu cầu rồi giao cho lập trình viên thực hiện. Những ngày tháng ấy, cụ Quách chơi rất nhiều game online, bản thân cụ là người chơi trung thành của “Ma Đạo Phu Nhân”. Thấy điểm sáng thú vị trong game của người khác, cụ liền nghĩ cách hiện thực hóa. Đồng thời tự nghĩ thêm nhiều ý tưởng vui vẻ khác. Tôi cũng rất sẵn lòng phối hợp.

Khi “Đại Mộng” ra mắt, nhiều bạn bè cũ nhận xét game rất hấp dẫn, mang phong cách của game đơn. Trong đó, sự chú ý đến từng chi tiết nhỏ đóng vai trò then chốt. Đã là game tương tác, chúng ta phải khác biệt với việc nộp biểu mẫu điện tử. Game là trải nghiệm hành trình, chứ không phải kết quả cuối cùng.

Tôi nghĩ toàn bộ nhóm dự án “Đại Mộng” đều rất nỗ lực, không vì dự án không có thời hạn kết thúc rõ ràng mà buông lỏng. Nhớ có lần vào một cuối tuần mùa hè, bộ phận QC báo một bug gây crash client. Nhưng nguyên nhân bug này hoàn toàn không có quy luật. Chỉ cần chơi vài ba chục tiếng, chương trình tự nhiên sập, không cách nào tái hiện lỗi. Xác suất xảy ra cực thấp, vài ngày mới gặp một lần. Khi kiểm tra stack trace sau lỗi, đoạn mã liên quan hoàn toàn bình thường, vấn đề nằm ở một giá trị số trong đối tượng bị sai lệch. Mà loại đối tượng này trong bộ nhớ có hàng ngàn cái tương tự, mỗi lần lỗi lại ở vị trí khác nhau.

Những lập trình viên từng trải nghiệm debug đều hiểu, loại bug này cực kỳ khó truy tìm. Không thể xác định nguyên nhân từ hiện trường, không thể đặt breakpoint để theo dõi trạng thái bộ nhớ bất thường từ sớm. Thông thường chỉ có thể dựa vào việc đọc lại toàn bộ mã liên quan để phân tích. Khi đoạn mã xung quanh hiện trường lỗi đều đúng, lập trình viên đối mặt với việc phải đọc lại toàn bộ mã liên quan.

Nếu không có niềm tin rằng mọi bug đều có thể truy ra nguyên nhân, với loại lỗi xác suất thấp lại không có phương pháp đối phó này, nhiều dự án gấp gáp sẽ phải tạm gác lại. Nhưng cả cụ Quách và tôi đều cho rằng, chưa tìm ra nguyên nhân thì tuyệt đối không thể tiếp tục phát triển. Bug giống như cục u ám trong lòng, không giải quyết được thì làm gì cũng khó chịu.

Nhớ mấy hôm đó, từ thứ Năm đến thứ Bảy đều không có tiến triển. Sáng Chủ Nhật, tôi đang đẩy tạ ở phòng gym thì điện thoại reo, cụ Quách hào hứng báo đã thu được một đoạn video crash sau khi client chạy được nửa tiếng. Như đã nói, video ghi lại lỗi rất hữu ích cho việc debug. Trước đó video đều dài vài tiếng, mỗi lần tái hiện lỗi phải chờ hàng chục phút, hiệu suất cực thấp. Khi thu được video chỉ dài nửa tiếng này, ý nghĩa vô cùng to lớn. Tôi lập tức bắt taxi trở về công ty, hai người chúng tôi ở văn phòng trống trải debug suốt cả ngày.

Kết quả sau đó khiến chúng tôi vỡ lẽ. Thời điểm thực sự gây ra vấn đề lại xảy ra trước thời điểm crash vài phút. Nguyên nhân là do tại giao diện giữa Python và C++, thứ tự tăng/giảm tham chiếu bị viết ngược. Điều này khiến Python tham chiếu đến một đối tượng C++ vừa bị giải phóng. Thông thường tham chiếu sẽ được giải phóng ngay lập tức. Nhưng trong một trường hợp đặc biệt, con trỏ bộ nhớ bị truyền đi nơi khác và được tham chiếu lại. Mối quan hệ tham chiếu sai này duy trì rất lâu, đến khi hàng loạt đối tượng tạm thời bị hủy mới bộc lộ ra.

Đây là bug khó debug nhất trong sự nghiệp của tôi, để lại ấn

0%