- Khi các AI agent trở thành trung tâm của việc viết mã, những thực hành tốt vốn từng là “tùy chọn” như kiểm thử, tài liệu hóa và static typing nay đã trở thành yếu tố bắt buộc
- Yêu cầu 100% code coverage, để mọi dòng mã đều được kiểm chứng thực tế và được hỗ trợ bởi các ví dụ chạy được
- Làm rõ cấu trúc thư mục và cách đặt tên tệp để LLM dễ khám phá codebase hơn, đồng thời khuyến khích tổ chức tệp theo đơn vị nhỏ
- Xây dựng môi trường phát triển nhanh, tạm thời và có thể chạy đồng thời để nhiều agent có thể làm việc song song
- Trọng tâm là duy trì một hệ sinh thái mã mà AI có thể tin cậy thông qua hệ thống kiểu tĩnh và các công cụ kiểm soát chất lượng tự động
AI và tính bắt buộc của “mã tốt”
- Trong thời gian dài, các lập trình viên đã xem kiểm thử, tài liệu hóa, module nhỏ, static typing là tiêu chuẩn của mã tốt, nhưng trên thực tế chúng thường bị lược bỏ
- Tuy nhiên, AI agent không giỏi tự dọn dẹp mã, nên những thực hành tốt này trở nên hoàn toàn cần thiết
- Để agent không đi sai hướng, việc thiết lập guardrail rõ ràng và cưỡng chế thực thi là bắt buộc
- Khi có guardrail vững chắc, LLM sẽ hội tụ theo đúng lộ trình; còn trong môi trường không hoàn chỉnh, nó sẽ khuếch đại vấn đề
100% code coverage
- Các nhóm đang bắt buộc 100% code coverage, không chỉ để ngăn lỗi mà còn nhằm xác minh hành vi của toàn bộ mã do agent viết ra
- Ở mức coverage 95% hay 99,99%, nguồn gốc của phần mã chưa được kiểm thử vẫn không rõ ràng; còn ở mức 100%, mọi dòng chưa được xác minh đều có thể được nhận diện rõ ràng
- Báo cáo coverage được dùng như danh sách những gì cần kiểm thử, và LLM bắt buộc phải đưa ra ví dụ chạy được mỗi khi thay đổi mã
- Cách tiếp cận này còn mang lại các hiệu ứng phụ như loại bỏ mã không thể tiếp cận, làm rõ edge case, và cải thiện hiệu quả review code
Namespace và cấu trúc tệp
- Agent khám phá codebase thông qua hệ thống tệp, nên cấu trúc thư mục và tên tệp đóng vai trò như một giao diện quan trọng
- Một đường dẫn rõ ràng như ./billing/invoices/compute.ts truyền tải nhiều thông tin hơn hẳn ./utils/helpers.ts
- Nên ưu tiên các tệp nhỏ, được định nghĩa rõ ràng, vì điều đó cho phép LLM nạp toàn bộ tệp vào ngữ cảnh và tránh suy giảm hiệu năng
- Kiểu tổ chức này dẫn đến tốc độ và độ chính xác khám phá của agent tốt hơn
Môi trường phát triển nhanh, tạm thời và có thể chạy đồng thời
- Thay vì một môi trường phát triển đơn lẻ như trước, phát triển dựa trên agent chuyển sang mô hình quản lý nhiều tiến trình song song
- Fast: quy trình kiểm thử và xác minh phải chạy nhanh; nhóm đã tối ưu để hoàn thành hơn 10.000 assertion trong vòng 1 phút
- Đạt tốc độ nhờ song song hóa cao, cô lập mạnh, và lớp cache cho các lời gọi bên thứ ba
- Ephemeral: với lệnh
new-feature <name>, có thể tạo môi trường mới trong 1–2 giây, tự động cấu hình và chạy agent
- Nếu cần thiết lập thủ công thì tần suất sử dụng sẽ giảm mạnh, nên tự động hóa hoàn toàn là yếu tố cốt lõi
- Concurrent: để có thể chạy nhiều môi trường phát triển cùng lúc, cần thiết lập tránh xung đột cho port, DB, cache, v.v.
- Có thể dùng Docker hoặc cấu hình cô lập dựa trên biến môi trường
Hệ thống kiểu end-to-end và quản lý chất lượng tự động
- Tự động hóa càng nhiều thực hành tốt càng tốt để giảm độ tự do của LLM và duy trì chất lượng nhất quán
- Thiết lập linter và formatter tự động thật nghiêm ngặt, để mỗi khi LLM hoàn thành công việc thì bản sửa tự động được áp dụng
- Khuyến nghị dùng ngôn ngữ kiểu tĩnh, đặc biệt tận dụng hệ thống kiểu mạnh xoay quanh TypeScript
- Thông qua những tên kiểu mang ý nghĩa như
UserId, WorkspaceSlug, SignedWebhookPayload, có thể biểu đạt rõ ý đồ của mã
- Dùng OpenAPI để duy trì sự khớp kiểu giữa frontend và backend
- Tận dụng hệ thống kiểu và trigger của Postgres để bảo đảm tính toàn vẹn dữ liệu, đồng thời tạo client an toàn về kiểu với Kysely
- Mọi client bên thứ ba cũng cần có định nghĩa kiểu chính xác hoặc được bọc lại trước khi sử dụng
Kết luận: Định nghĩa lại chất lượng mã trong kỷ nguyên AI
- Agent là những coder xuất sắc và không biết mệt, nhưng hiệu năng của chúng phụ thuộc vào chất lượng môi trường
- “Mã tốt” không còn là lựa chọn, mà là điều kiện tiên quyết để AI hoạt động đúng cách
- Thiết lập ban đầu có thể tạo cảm giác nặng nề, nhưng đó là khoản đầu tư bắt buộc đã bị trì hoãn quá lâu
- Với sự hỗ trợ từ đội ngũ lãnh đạo kỹ thuật, cần hướng tới mục tiêu xây dựng codebase thân thiện với AI
1 bình luận
Ý kiến trên Hacker News
Cái bẫy khi đạt 100% coverage là nếu cùng một agent viết cả code lẫn test, nó có thể rơi vào tự xác thực mâu thuẫn
Nếu agent tạo ra logic sai và cả test để kiểm chứng nó cũng được viết sai, thì test vẫn pass nhưng code thực tế vẫn có lỗi
Coverage kiểu này chỉ có ý nghĩa khi test được viết trước code hoặc được con người kiểm định nghiêm ngặt
Nếu không, nó chỉ tạo ra ảo giác về độ tin cậy mà thôi
Điểm cốt lõi là để nhiều con người với các cách tư duy khác nhau kiểm tra điểm mù của nhau
Dù có nhiều model AI đi nữa thì cuối cùng vẫn nên xem chúng là một “tâm trí” duy nhất
Tốt nhất là người viết code thì AI viết test, AI viết code thì người viết test, hoặc đôi bên review chéo cho nhau
Tuy vậy, ngay cả giữa con người với nhau cũng có trường hợp chỉ ý kiến của một người được phản ánh vì quan hệ quyền lực, và AI cũng không ngăn được điều đó
Cần cố tình chèn bug vào để xem nó có fail hay không
Đây không chỉ là vấn đề của AI mà với con người cũng vậy
Dù sao thì nhờ AI mà nhiều lập trình viên đang học được các nguyên tắc kỹ nghệ phần mềm đúng đắn, đó là điều tốt
SQLite hay phần mềm hàng không nhắm tới mức này
Tuy vậy, đây vẫn chưa phải giả thuyết đã được kiểm chứng về mặt học thuật
Vì thế cần dùng integration test hoặc UI automation test để kiểm chứng các kịch bản người dùng thực tế
Dữ liệu lấy từ môi trường production hoặc test trong môi trường shadow cũng hữu ích
Trước thời LLM thì việc thiết lập khá phiền, nhưng giờ ROI đã tốt hơn
Như Uncle Bob từng nhấn mạnh, điều quan trọng là đầu tư vào việc cấu trúc test
LLM viết test lặp đi lặp lại, nhưng nếu yêu cầu thì nó cũng áp dụng tốt nguyên tắc DRY hay factory pattern
Đây là cách tôi bắt đầu thử từ hôm qua: viết spec trước bằng TLA+/PlusCal, rồi để Codex triển khai đúng theo spec đó
Tôi chỉ thị nó phải bám sát spec, không được sáng tạo
Code tạo ra xấu nhưng chính xác, và nhanh hơn nhiều so với tự tay chuyển dịch
Tuy vậy, khi tối ưu hóa chưa đủ hoặc quá lộn xộn thì tôi vẫn sửa lại một phần
Đặc biệt tôi đang thử nghiệm cấu trúc dữ liệu lock-free, nhưng Codex vẫn hay cố dùng lock nên tôi phải tự chỉnh
Cuối cùng tôi tập trung vào logic toán học, còn AI phụ trách chi tiết triển khai
Đây chính là luồng lý tưởng của “đặc tả trước, code sau”
Tôi đồng cảm với bài viết của Martin Kleppmann
Với các model mới nhất, cách này thực sự hoạt động tốt, và hiệu quả chi phí cũng tốt hơn 10~100 lần
Cái này nghe như hallucination hoặc bài chào hàng
Nếu bug production thực tế và gánh nặng bảo trì còn không đủ để ép người ta viết code tốt, thì AI cũng không làm được
AI ở mức hiện tại thậm chí còn dễ làm code tệ hơn
Ngay cả độ dài method còn chưa có đồng thuận, thì không tồn tại tiêu chuẩn chất lượng phổ quát
Các chỉ số như test coverage cũng rất dễ bị thao túng, và nếu áp dụng sai còn phản tác dụng
Đặc biệt khi AI viết test, nó có thể tạo ra sự tự tin giả tạo
Tôi nghĩ phát triển phần mềm có thể là ứng dụng thực tiễn duy nhất của LLM
So với các lĩnh vực khác, ở đây có thể tạo vòng phản hồi nhanh hơn nhiều
Ta lập kế hoạch với LLM rồi vài giờ sau xác nhận thất bại, khi đó LLM sẽ nói “đó là lý do không nên làm vậy”
Nó giống như xây một căn nhà theo chuẩn điện của Mỹ rồi đến lúc lắp máy rửa chén chuẩn Canada mới phát hiện vấn đề
Phần mềm tương đối an toàn nên trước đây có thể phát triển ẩn danh, nhưng giờ đang hình thành văn hóa ký tên chịu trách nhiệm
Trong tương lai có khi chỉ những người viết code rủi ro cao, nhiều đổi mới mới được trả lương cao
AI cứ tiếp tục sinh ra đoạn code vô nghĩa, ta debug, rồi nó lại sinh ra thứ vô nghĩa khác, chỉ rơi vào vòng lặp vô hạn
Chỉ cần khớp đúng chuẩn dòng điện là an toàn
Dù vậy tôi vẫn thấy may là với unit test ta còn có điểm chạm với thực tế
Tôi đang dùng LLM để học về mạch RLC và inerter
Nhiều người thấy LLM sinh code nhanh thì ngạc nhiên, nhưng tốc độ hay số lượng không phải nút thắt của chất lượng
Cuộc cách mạng thực sự sẽ đến khi AI tạo ra code chính xác hơn con người
Giá trị thật sự đến từ việc biết code hoạt động như thế nào
Giữa những kỹ sư chỉ đoán mò trong cuộc họp, khoảnh khắc một người mở đoạn code thật ra cho mọi người xem mới là khoảnh khắc có giá trị nhất
“Code tốt” có lẽ là loại code được tối ưu theo bộ nhớ làm việc hữu hạn của con người
Model có thể nhìn toàn bộ ngữ cảnh cùng lúc nên không bị ràng buộc như vậy
Nếu context window lớn hơn 100 lần thì có khi kiểu tranh luận này sẽ bớt quan trọng đi
Tôi lo rằng nếu yêu cầu LLM đạt 100% coverage thì các giả định sai sẽ bị cố định hóa
Dù vậy, nếu vẫn có review của con người thì chắc vẫn có thể nói “cái này sai rồi, xóa test đi và viết lại chứ?”
LLM cùng viết PRD theo kiểu phỏng vấn để làm rõ phạm vi và kỳ vọng
“Best practice” thay đổi theo môi trường công nghệ
Giờ việc viết code đã dễ hơn nên 100% coverage có thể hữu ích hơn cho LLM
Test cho LLM một mục tiêu rõ ràng, và giúp các tương tác về sau an toàn hơn
Mỗi test tham chiếu tới ticket bug trong quá khứ và đảm bảo bản sửa lỗi tiếp tục được duy trì
Nếu đưa kịch bản cho LLM, phần lớn nó sẽ sinh ra code có chất lượng gần tương đương nhau
Khác với nghệ thuật sáng tạo, phần mềm là ngành đặc biệt phù hợp để tự động hóa
Khi đọc bài này tôi tưởng nội dung sẽ là “để AI hiệu quả thì chúng ta phải viết code tốt”
Thực tế Claude thường mắc lỗi với tên biến mơ hồ hoặc code phi logic
Nếu tên biến là “iteration_count” nhưng lại chứa tổng, AI sẽ bị đánh lừa
Cuối cùng thì code sạch giúp ích cho cả AI lẫn con người
Vì AI dùng tài liệu nội bộ làm nguồn học, nên giờ tài liệu được cập nhật được xem là bắt buộc
Trước đây nó có ưu tiên thấp, nhưng giờ lại ảnh hưởng trực tiếp tới chất lượng model
Dù vậy theo thời gian thì phần này cũng sẽ được cải thiện
Làm vậy sẽ tăng khả năng LLM triển khai chính xác ngay từ lần đầu
Bài này cho thấy mức độ hiểu biết kỹ thuật hời hợt của các công ty làm prompt
100% coverage không thể xác minh mọi tổ hợp đầu vào
Nó chỉ đơn giản là chạy qua mọi dòng bằng một vài ví dụ
Cuối cùng vẫn cần tới chứng minh hình thức, mà thứ đó thì đắt đỏ đến mức khổng lồ và LLM không giúp được gì
Ngược lại, tạo ra môi trường phát triển có tính phản hồi bằng test có thể mở ra một thời kỳ hoàng kim mới
Nếu coverage có vấn đề thì sau này mở rộng thêm cũng được
Tốt hơn là ngay từ đầu hãy thiết lập test kỹ lưỡng nhất có thể
Đã có nhiều thử nghiệm kết nối nó với proof assistant
Ngay cả khi đặc tả có chút lỗi, phần lớn trường hợp nó vẫn cho ra kết quả dùng được