Chương 8: Commit Tiếp Theo Có Thêm Người Review
Commit tiếp theo của Khải không vào nhánh chính ngay. Nó nằm trong một pull request đang chờ hai người duyệt. Ba năm trước, nếu đang vội, anh có thể đẩy thẳng lên hệ thống thật; bây giờ, nhánh được bảo vệ chẳng quan tâm người sáng lập là ai.
Phương để lại bình luận: “Anh thêm kiểm thử cho phần chuyển đổi dữ liệu và ghi rõ cách hoàn tác nhé.” Khải đọc rồi lẩm bẩm: “Ngày xưa chính tôi đặt ra quy tắc này, giờ lại thấy ghét nó.” Cậu kỹ sư trẻ ngồi cạnh bật cười.
LearnFree khi ấy đã thành một dự án có nhóm nòng cốt nhỏ và một cộng đồng đủ ổn định. Không phải “phong trào toàn cầu” với hàng chục nghìn người đóng góp. Qua nhiều năm, có vài trăm người từng tham gia ở những mức độ khác nhau, phần lớn là dịch thuật, nội dung, sửa lỗi và viết tài liệu. Nhóm người duy trì thực sự còn hoạt động thì nhỏ hơn nhiều. Dự án có người dùng ở nhiều nơi, nhưng con số được báo cáo theo số liệu vận hành phù hợp, không gom lượt tải về rồi gọi là “người học đang hoạt động”. Khải đã học được cách không dùng những con số chỉ để làm đẹp.
Chuyện tiền bạc cũng chẳng có gì huyền thoại. Một vài khoản tài trợ, các hợp đồng hỗ trợ và triển khai, tiền quyên góp, một mối hợp tác với trường học và tổ chức xã hội. Đủ trả lương cho nhóm nòng cốt; có năm dư một chút, có quý phải hoãn tuyển người.
Không có sân khấu công nghệ toàn cầu nào tung hô người sáng lập như huyền thoại. Khải nói chuyện ở vài hội thảo lập trình và giáo dục, cùng một hội nghị mã nguồn mở trong khu vực; bài nói về sau được vài nghìn lượt xem, và anh thích như vậy. Slide đầu tiên không ghi “Người đồng sáng lập đã đánh cắp code của tôi”, mà ghi: “Từ một sản phẩm phụ thuộc vào nhà sáng lập đến một cơ chế quản trị rõ ràng.”
Anh kể về sự cố ở mức cần thiết: quyền của nhà sáng lập quá rộng, chuỗi quyền sở hữu trí tuệ được làm muộn, truy cập dữ liệu người dùng không theo nguyên tắc quyền tối thiểu, rồi bản viết lại theo quy trình “phòng sạch”, chuyện giấy phép mã nguồn mở và cơ chế duy trì dự án. Anh không dựng Kiệt thành phản diện để đổi lấy tràng pháo tay.
Một khán giả hỏi: “Nếu được làm lại, anh có mở mã nguồn LearnVN ngay từ đầu không?”
Khải nghĩ một lúc. “Tôi không biết.” Cả phòng bật cười. “Mã nguồn mở không tự sửa được thỏa thuận giữa các nhà sáng lập, quyền riêng tư hay quản lý truy cập. Có thể tôi vẫn chọn mã nguồn đóng, nhưng tôi sẽ làm rõ chuyện sở hữu và quản trị hơn.” Đó là câu trả lời anh tự hào nhất: không khẩu hiệu, không hệ tư tưởng tuyệt đối nào.
LearnVN vẫn tồn tại, với chủ sở hữu và đội ngũ khác. Thỉnh thoảng Khải vẫn thấy quảng cáo của app cũ, và không còn thấy đau như trước. Thương hiệu EduPro đã dừng sau khi tài sản và đội ngũ được chuyển sang công ty khác. Kiệt không biến mất khỏi ngành; anh làm tư vấn hạ tầng ở quy mô nhỏ hơn.
Một lần, hai người gặp nhau ở một sự kiện công nghệ. Không ai tránh mặt ai.
“LearnFree ổn đấy,” Kiệt nói.
“Cảm ơn.”
“Mày mở hết thật à?”
“Code lõi mở theo giấy phép. Không phải dữ liệu, thương hiệu hay toàn bộ nội dung.”
Kiệt cười. “Mày vẫn thích sửa câu của người khác.”
“Bệnh nghề nghiệp,” Khải đáp. Họ nói chuyện vài phút rồi ai đi đường nấy. Không có màn tha thứ lớn lao nào, cũng không có chuyện bắt tay làm lại công ty. Chỉ là hai người từng làm chung giờ có thể đứng trong cùng một căn phòng mà không cần biến quá khứ thành trận đấu cuối cùng.
Mẹ Khải đã nghỉ dạy sau nhiều năm đứng lớp, nhưng bà vẫn giữ cuốn từ điển cũ. Một buổi chiều về nhà, Khải thấy bà đang mở LearnFree trên máy tính bảng, xem một bài học mới.
“Mẹ làm gì đấy?”
“Xem tụi con giải thích thì hiện tại hoàn thành thế nào.”
“Có đúng không mẹ?”
“Tạm được.”
Khải cười. “App của con mà.” Bà nhìn anh, và anh tự sửa lại: “App của dự án.”
“Khác gì nhau?”
“Khác nhiều lắm mẹ.” Anh giải thích: code có giấy phép, người đóng góp được ghi công, dự án có những người duy trì, tổ chức giữ thương hiệu, người dùng có quyền với dữ liệu của mình theo chính sách và pháp luật, nội dung có giấy phép riêng.
Bà Hoa nghe được nửa chừng thì ngắt lời: “Ngày xưa mẹ chỉ hỏi app có giúp học sinh học được không.”
“Giờ con cũng hỏi thế.”
“Thế còn mấy thứ kia?”
“Để app sống được mà không phải tin vào một người duy nhất.” Bà gật đầu, như thể câu trả lời ấy cuối cùng cũng đủ ngắn.
Tối đó, Khải mở laptop. Pull request của anh vẫn chưa được hợp nhất. Phương thêm bình luận thứ hai, một người đóng góp khác đề nghị viết thêm kiểm thử cho một trường hợp biên. Khải sửa từng chỗ, nhưng không ngồi một mình từ tám giờ tối tới hai giờ sáng như ngày trước. Đến mười một giờ, anh dừng tay; mai duyệt tiếp. Nhóm nòng cốt có lịch trực luân phiên, và người sáng lập không được biến sự kiệt sức thành văn hóa.
Commit cuối ngày mang dòng mô tả “fix: clarify offline sync conflict handling”. Không có dòng “Dành cho Páo” nào; anh không dùng một đứa trẻ làm biểu tượng cho một tính năng. Chủ đề liên kết có ghi chú thí điểm, kiểm thử và tên người duyệt. Khải thích cách đó hơn.
Trước khi đi ngủ, anh mở bảng theo dõi bảo mật. Không có sự cố lớn nào. Một đợt rà soát quyền truy cập sắp đến hạn, hai người duy trì cần thay thông tin đăng nhập theo chính sách, và một người đóng góp xin quyền phát hành nhưng chưa đủ tiêu chí. Dự án vẫn đang sống.
Nó sống không phải vì code không bao giờ bị sao chép. Với mã nguồn mở, việc sao chép hay fork vốn là điều đã được dự liệu trong giấy phép. Dự án sống vì quyền và trách nhiệm được nói rõ: ai được hợp nhất code, ai được phát hành, ai được vào hệ thống thật, ai được dùng dữ liệu, ai được dùng tên và logo, ai phải duyệt khi có thay đổi rủi ro.
Khải gập laptop. Ngày trước anh nghĩ giá trị nằm ở chỗ không ai lấy được mã nguồn của mình. Sau đó anh phản ứng bằng một cực ngược lại: nếu ai cũng có mã nguồn thì chẳng ai lấy cắp được. Giờ anh hiểu cả hai đều quá đơn giản. Giá trị không chỉ nằm ở code, mà ở những quyền được thiết kế rõ ràng, dữ liệu được bảo vệ đúng cách, một cộng đồng có cơ chế quản trị, một sản phẩm giải quyết vấn đề thật, và một đội ngũ không phụ thuộc vào niềm tin mù quáng giữa hai nhà sáng lập.
Commit tiếp theo vẫn sẽ có lỗi. Vẫn sẽ có tranh luận, và rất có thể sẽ có người fork. Điều đó không còn làm Khải sợ như trước. Lần này, nếu ai dùng code, dự án đã nói rõ họ được làm gì; nếu ai chạm vào dữ liệu hay hệ thống thật, dự án cũng đã nói rõ họ không được làm gì.
Và lần này, một commit không còn là lời tuyên bố sở hữu. Nó chỉ là một thay đổi có tác giả, có người duyệt, có giấy phép và bối cảnh, nằm trong một hệ thống lớn hơn chính người viết ra nó. Khải thấy cách hiểu ấy nhẹ nhõm hơn rất nhiều so với câu “code của tôi”.
Đó mới là điều anh ước mình đã viết ngay từ commit đầu tiên.