
Giải phẫu quá trình đưa phần mềm đến độ hoàn hảo: Cách đánh giá mã bắt được lỗi mà kiểm thử bỏ sót
Xuyên suốt loạt bài GeekBye v2, cùng một điều cứ lặp đi lặp lại: một bản sửa lỗi vượt qua mọi bài kiểm thử trên máy của lập trình viên, rồi khâu đánh giá mã chứng minh rằng nó sẽ thất bại với gần như tất cả mọi người. Đây là quy trình đằng sau chín bản phát hành — cửa kiểm soát đánh giá, những phát hiện bắt lỗi ngay từ đầu, và kỷ luật kiểm thử trước khi phát hành đã biến "nó chạy được trên máy tôi" thành "nó chạy được".
Trong vài tuần, GeekBye đã phát hành chín bản — từ v2.0.0 đến v2.0.11 — và loạt bài này kể lại câu chuyện của từng bản một. Đọc chúng cùng nhau, một mẫu hình hiện ra thú vị hơn bất kỳ lỗi đơn lẻ nào: hết lần này đến lần khác, một bản sửa lỗi vượt qua mọi bài kiểm thử trên máy của lập trình viên, và đánh giá mã chứng minh nó sẽ thất bại với gần như tất cả những người còn lại.
Khoảng cách đó — giữa "nó chạy được trên máy tôi" và "nó chạy được" — chính là nơi độ tin cậy thực sự tồn tại. Đây là quy trình khép lại khoảng cách ấy, và là mục lục cho mọi bản phát hành nó tạo ra.
Mẫu hình: kiểm thử màu xanh, câu trả lời sai
Dưới đây là ba trường hợp rõ ràng nhất trong loạt bài, vì chúng biến điều trừu tượng thành cụ thể.
- Trong bản sửa lỗi chụp màn hình đa màn hình (v2.0.10), phiên bản đầu tiên neo việc chụp màn hình vào cửa sổ lớp phủ của ứng dụng. Nó vượt qua kiểm thử — trên một máy dev đơn màn hình. Đánh giá đã lý giải xem cửa sổ lớp phủ đó thực sự nằm ở đâu (luôn là màn hình chính, trừ khi bạn tự tay kéo nó đi) và chứng minh rằng "bản sửa" đó sẽ lại phân giải về sai màn hình với gần như mọi người dùng thực. Điểm neo đúng — con trỏ chuột — đến từ lập luận đó, chứ không phải từ một lần chạy kiểm thử.
- Trong bản phát hành dự phòng WebSocket (v2.0.8), đánh giá phát hiện rằng chính mã
403mà một proxy chặn trả về đã bị phân loại là lỗi xác thực nghiêm trọng — nên cơ chế dự phòng mà tính năng này tồn tại để kích hoạt lại không bao giờ có thể chạy. Tính năng này lẽ ra đã được phát hành, vượt qua các bài kiểm thử theo kịch bản thuận lợi, và chẳng làm được gì cho đối tượng thực của nó. - Trong bản sửa lỗi hết thời gian chờ khi rảnh (v2.0.9), phiên bản đầu tiên đóng dấu chiếc đồng hồ "vẫn còn sống" bên trong một luồng mã mà một phần bản ghi chép hợp lệ bỏ qua — bản ghi của người nói còn lại. Đánh giá bắt được rằng một thay đổi trong tương lai có thể âm thầm tái tạo chính lỗi đang được sửa, và dấu thời gian được chuyển đến một chỗ vô điều kiện, kèm một bài kiểm thử để giữ nó ở đó.
Không lỗi nào trong số này được bắt bằng cách chạy mã. Tất cả đều được bắt bởi một người đánh giá lý giải tại sao mã hoạt động — và tìm ra một trường hợp mà nó không hoạt động.
Ba phần của cửa kiểm soát
Quy trình đằng sau loạt bài không hề cầu kỳ. Đó là ba thói quen được áp dụng không ngoại lệ.
1. Đánh giá lý giải về tính đúng đắn, chứ không chỉ chạy mã. Một bài kiểm thử vượt qua chứng minh mã hoạt động với trường hợp bạn đã nghĩ tới. Đánh giá là một mô hình thứ hai, mang tính phản biện về hệ thống, đặt câu hỏi trường hợp nào bạn đã không nghĩ tới? — màn hình thứ hai, proxy doanh nghiệp, bản ghi bỏ qua nhánh, khách hàng đang chậm hơn một phiên bản. Bước đánh giá trong loạt bài này thường là một tác nhân đánh giá độc lập được yêu cầu bác bỏ bản sửa, chứ không phải chấp thuận nó. Cách đóng khung đó chính là điểm mấu chốt: một người đánh giá cố gắng phá vỡ lập luận của bạn sẽ tìm ra cái lỗ hổng mà một người đánh giá cố gắng phê duyệt nó lướt qua.
2. Mỗi bản sửa hành vi được phát hành kèm một bài kiểm thử ghim đúng điểm thất bại. Không phải một bài kiểm thử rằng tính năng hoạt động — mà một bài kiểm thử rằng chính lỗi cụ thể này đã chết. Mã 403 của proxy bị chặn phải rơi xuống cơ chế dự phòng; một mã 403 xác thực thật thì không được phép. Đồng hồ hoạt động phải đóng dấu trên một bản ghi bỏ qua khâu gán nguồn. Những bài kiểm thử này tồn tại để lỗi không thể lặng lẽ quay lại sau sáu tháng khi ai đó tái cấu trúc gần đấy — điểm thất bại được đóng đinh xuống sàn.
3. Bản dựng được công chứng và kiểm chứng trước khi phát hành. Vài bản sửa trong số này đi từ chẩn đoán đến một bản phát hành đã ký, đã công chứng, tự động cập nhật chỉ trong vòng một ngày. Tốc độ đó chỉ an toàn vì cửa kiểm soát có kỷ luật: bản chẩn đoán chứng minh nguyên nhân gốc rễ (bản phát hành về quyền micro đã phát hành bản chẩn đoán trước tiên), bài kiểm thử ghim bản sửa, đánh giá bác bỏ lập luận, và chỉ đến lúc đó một bản dựng đã công chứng thật sự mới được phát hành. Sự nghiêm ngặt là thứ khiến tốc độ trở nên an toàn, chứ không phải thứ đánh đổi với nó.
Tại sao điều này lại quan trọng hơn với một ứng dụng AI
Có một lý do khiến kỷ luật này là bắt buộc, đặc biệt với một công cụ như GeekBye. Vài lỗi hiểm hóc nhất trong loạt bài đều sai một cách lặng lẽ, chứ không phải sập một cách ồn ào: một ảnh chụp màn hình đưa sai màn hình cho AI (v2.0.10), một bản ghi âm thiên lệch về những thuật ngữ rác nên "speak" biến thành một cái tên (v2.0.11), một trợ lý trả lời sai chế độ mà không có cách nào nhận ra (v2.0.3 + v2.0.5). Khi ứng dụng của bạn đưa ngữ cảnh cho một mô hình, một đầu vào sai tạo ra một đầu ra sai một cách đầy tự tin và không có lỗi ở bất cứ đâu. Bạn không thể kiểm thử để thoát khỏi những thất bại không hề ném ra lỗi. Bạn phải lý giải để thoát ra — mà đó chính xác là mục đích của cửa kiểm soát đánh giá.
Loạt bài, theo thứ tự
Mỗi bài trong số này là một nghiên cứu tình huống độc lập về một bản phát hành. Đọc từ đầu đến cuối, chúng là giải phẫu quá trình đưa một sản phẩm từ "chạy được" đến "đáng tin cậy".
- Một phiên bản 2 thực sự đòi hỏi những gì: 206 lần commit của những trạng thái trung thực — v2.0.0. Nền tảng: đừng bao giờ hiển thị một trạng thái không đúng sự thật.
- Ngày ứng dụng của chúng tôi tự DDoS chính mình — v2.0.1 + v2.0.4. Một hàng chờ tải lên khi khởi động giẫm đạp lên chính backend của chúng tôi, và chiếc thang liveness mà nó buộc phải tạo ra.
- Phần mềm điềm tĩnh: bản sửa nhấp nháy và con chip chế độ trả lời — v2.0.3 + v2.0.5. Những bản phát hành không có tính năng nào nhưng mua lấy niềm tin từng chi tiết một.
- Ứng dụng Mac của bạn quên quyền truy cập micro mỗi lần khởi động — v2.0.6. Cơ chế App Translocation của macOS, và việc phát hành bản chẩn đoán trước bản sửa.
- Một biến CSS, năm vòng đánh giá, và một chuỗi công cụ Swift đã nói dối — v2.0.7. Độ trong suốt đồng nhất, và một tệp nhị phân đổi kích thước vì tài liệu bất đồng với kịch bản kiểm soát.
- Phiên âm trực tiếp khi tường lửa chặn WebSocket — v2.0.8. Một cơ chế dự phòng thuần HTTPS, và mã
403lẽ ra đã giấu nó khỏi chính nó. - Tại sao trợ lý ghi chú AI của bạn ngừng ghi giữa cuộc họp — v2.0.9. Một bộ đếm giờ khi rảnh chỉ có thể nghe thấy bạn, và một cú sập có thể khóa cứng máy tính của bạn.
- Tại sao ghi màn hình lại chụp nhầm màn hình — v2.0.10. Lỗi sai màn hình, và bản sửa vượt qua trên một màn hình nhưng lẽ ra đã thất bại trên hai.
- Tại sao phiên âm AI nghe nhầm các thuật ngữ kỹ thuật — v2.0.11. Thiên vị lời nói về phía vốn từ của bạn — và bản hồi quy khiến nó tệ hơn trước khi khiến nó tốt hơn.
Điều rút ra
Sự hoàn hảo không phải một trạng thái bạn đạt tới; nó là một cửa kiểm soát bạn duy trì. Chín bản phát hành, và cùng ba câu hỏi ở mỗi bản: trường hợp nào bạn đã không nghĩ tới, điểm thất bại chính xác có được một bài kiểm thử ghim lại không, và một bản dựng đã ký thật sự có được phát hành không? Chẳng có gì trong đó là hào nhoáng. Tất cả đều là lý do khiến GeekBye v2 mang lại cảm giác điềm tĩnh. Nếu bạn xây dựng phần mềm — dù là AI hay không — phần có thể chuyển giao được không nằm ở bất kỳ bản sửa đơn lẻ nào. Nó nằm ở thói quen coi một bộ kiểm thử toàn màu xanh là khởi đầu của lập luận, chứ không phải điểm kết thúc của nó.
Mọi bản phát hành ở trên đều đang hoạt động thông qua tự động cập nhật. Để xem những bản sửa này cộng lại thành sản phẩm gì, hãy đọc có gì mới trong GeekBye v2.