Mời bạn thưởng thức Newsletter #133.
Why Go is an Ideal Language for AI-Assisted Software Engineering
Cameron Balahan và Richard Seroter từ Google cho rằng nút thắt của kỹ thuật phần mềm đã dịch chuyển: khi AI sinh ra hàng trăm dòng mã trong vài giây, phần khó không còn là viết mà là duyệt, kiểm chứng và bảo trì. Ngôn ngữ được thiết kế cho cộng tác nhóm lâu dài sẽ có lợi thế, và Go ra đời ở Google chính với mục tiêu ấy. Go là cả một nền tảng: bộ công cụ chuẩn có sẵn trình định dạng gofmt, khung kiểm thử, quản lý module và công cụ bảo mật, cùng thư viện chuẩn đầy đủ giúp giảm phụ thuộc bên ngoài. Go ưu tiên sự tường minh hơn là ngắn gọn hay khéo léo, và khi mã của người lẫn mô hình ngôn ngữ đều chung một định dạng, việc phát hiện lời gọi API bịa đặt hay lỗi logic trở nên dễ hơn.
Về độ tin cậy, kiểu tĩnh và tốc độ biên dịch rất nhanh tạo vòng lặp tự sửa lỗi ngắn cho agent. Cơ sở dữ liệu checksum chống việc phụ thuộc bị sửa đổi, còn govulncheck chỉ cảnh báo những lỗ hổng mà mã thực sự gọi tới. Về bảo trì, cam kết tương thích ngược bảo đảm mã viết cho Go 1.0 vẫn chạy trên công cụ mới nhất, chương trình biên dịch thành một tệp nhị phân tĩnh, và go fix giúp agent hiện đại hóa mã cũ một cách tất định. Bài viết thiên về lập luận, không có số liệu đo đạc, nhưng thông điệp rõ ràng: AI là cộng sự năng suất cao cần rào chắn chắc chắn, và Go cung cấp sẵn các rào chắn đó.
How does programming language affect token efficiency and correctness?
Có ý kiến cho rằng ngôn ngữ động tiết kiệm token hơn ngôn ngữ tĩnh khi làm việc với mô hình ngôn ngữ lớn. Dan Luu kiểm chứng điều này, bắt đầu bằng việc soi lại hai bộ đánh giá sẵn có. Bộ thứ nhất đo số token để giải các bài Rosetta Code, nhưng bài toán quá đơn giản nên khó khái quát. Bộ thứ hai có lỗi đường dẫn khiến Rust và Haskell trượt oan, cùng kiểm thử luôn đạt bất kể kết quả; chấm lại thì Rust đạt điểm tuyệt đối. Luu tự xây đánh giá riêng: agent viết trọn bộ giải mã zstd chỉ dựa trên đặc tả RFC rồi chấm bằng bộ kiểm thử ẩn, và một bài tái hiện Pandoc chấm trên tập kiểm thử giữ riêng.
Kết quả: với zstd ở mức suy luận trung bình, ngôn ngữ động có vẻ nhỉnh hơn, nhưng ở mức cao nhất thì nhiều ngôn ngữ tĩnh dẫn đầu. Clojure thất bại 36 trên 40 lần ở mức trung bình, chủ yếu vì phép chuyển kiểu byte ném lỗi với giá trị 128–255. Assembly và các ngôn ngữ ít phổ biến làm kém, còn độ phổ biến của ngôn ngữ tương quan nhẹ với độ chính xác và chi phí thấp. Gần như mọi chương trình Pandoc viết bằng C và C++ đều có lỗi an toàn bộ nhớ mà kiểm thử không phát hiện. Tác giả thừa nhận hai bài toán chưa đủ để kết luận chắc chắn, nhưng nhận định “ngôn ngữ động tốt hơn cho mô hình ngôn ngữ lớn” không đứng vững; chọn ngôn ngữ phổ biến là mặc định hợp lý, và đặc tả rõ ràng giúp ích rất nhiều.
My Agentic Coding Setup, July 2026
Domenic Denicola chia sẻ môi trường lập trình cùng agent mà anh chốt lại sau nhiều tháng thử nghiệm, với kết quả là có thể nhờ các mô hình hàng đầu sửa lỗi trên hệ thống thật ngay từ điện thoại khi đang ngồi tàu. Yêu cầu đặt ra khá rõ: agent chạy trên Linux vì chúng thạo Bash hơn PowerShell, công việc chuyển qua lại giữa máy bàn và laptop mà không mất phiên làm việc, nhiều agent làm song song trên cùng dự án, và gần như không phải bấm duyệt quyền. Nền tảng là một máy ảo Ubuntu “dùng xong có thể bỏ” đặt trên máy bàn luôn bật, nối với các thiết bị khác qua mạng riêng Tailscale để SSH và truy cập HTTPS từ bất cứ đâu. Trên đó anh chạy Claude Code và Codex CLI ở chế độ toàn quyền, cài sẵn gh để agent tự quản lý kho mã, PR và CI. Anh thừa nhận cách này không an toàn về nguyên tắc, và chốt chặn chính là đẩy mã lên GitHub sớm và thường xuyên.
Các mảnh ghép còn lại giải quyết từng yêu cầu: git worktree cho agent làm song song (anh chuộng ChatGPT hơn vì Claude đặt worktree ngay trong thư mục dự án), VS Code Remote-SSH để xem xét thay đổi, công cụ Portless bọc qua Tailscale để mỗi máy chủ phát triển có địa chỉ HTTPS riêng chỉ mình anh truy cập được, và chezmoi để đồng bộ AGENTS.md, skill cùng cấu hình giữa các máy. Những điểm còn thiếu gồm dev container để cách ly an toàn hơn, lịch sử phiên gắn chặt với đường dẫn thư mục, và chưa có cách sao lưu bền vững bản ghi phiên.
The Bedrock of Software Design
Alex Fedoseev cho rằng kiểu dữ liệu đại số (algebraic data type) là thứ ảnh hưởng tới cách anh thiết kế phần mềm nhiều nhất, và chúng đơn giản hơn cái tên rất nhiều. Kiểu tích gộp nhiều trường thành một giá trị, như một struct có id và role; kiểu tổng nói rằng giá trị là một trong vài biến thể, mỗi biến thể mang dữ liệu riêng, chẳng hạn phiên đăng nhập hoặc ẩn danh, hoặc đã xác thực và chỉ biến thể sau mới chứa thông tin người dùng. Quy tắc nghiệp vụ nằm rải rác trong chú thích hay hàm kiểm tra rất dễ bị bỏ qua. Thay vì mô hình giao diện trang web bằng một biến boolean cùng vài trường có thể null, ta dùng kiểu tổng với hai biến thể Switchable và Fixed, mỗi biến thể chỉ giữ đúng trường cần thiết, để trạng thái không hợp lệ không thể biểu diễn được.
Tư duy này áp dụng cho cả lỗi và sự vắng mặt của giá trị. Với ngoại lệ, chữ ký hàm chỉ cho thấy trường hợp thành công; Rust thì trả lỗi dự kiến qua Result, và kiểu lỗi cũng có thể là kiểu tổng kèm ngữ cảnh. Thay cho null là Option<T>, và Result<Option<User>, FindUserError> phân biệt rõ ba kết cục: tìm thấy, không có, và tra cứu thất bại. Phép match vét cạn buộc xử lý mọi trường hợp, nên khi thêm vai trò Staff, trình biên dịch chỉ ra mọi chỗ cần quyết định. Kết luận: kiểu tổng và so khớp vét cạn nên là yêu cầu tối thiểu của một ngôn ngữ lập trình.
90 % of the t distribution
Khi ước lượng khoảng tin cậy 90% cho giá trị trung bình, cách làm tắt quen thuộc là lấy trung bình mẫu cộng trừ 1,645 lần độ lệch chuẩn mẫu. Cách này ngầm giả định độ lệch chuẩn mẫu bằng đúng độ lệch chuẩn thật, bỏ qua sai số của chính phép ước lượng ấy, nên khoảng thu được hẹp hơn thực tế, và càng ít mẫu thì sai lệch càng lớn. Bài viết đưa ra một bảng hiệu chỉnh rút ra từ phân phối t của William Sealy Gosset (“Student”): nhân độ lệch chuẩn với 4 khi có 2 mẫu, 2 khi có 3 mẫu, 1,5 khi có 4 mẫu, 1,3 khi có 5 mẫu, 1,2 với 6 đến 8 mẫu và 1,1 với 9 đến 20 mẫu; trên 20 mẫu thì công thức thông thường đã đủ tốt. Ví dụ, với 7 mẫu có trung bình 32 phút và độ lệch chuẩn 8 phút, khoảng đúng là 32 ± 8 × 1,2 × 1,645.
Tác giả còn chỉ ra một mẹo hữu ích: chỉ với hai giá trị vẫn ước lượng được độ phân tán. Sau khi hiệu chỉnh theo phân phối t, độ lệch chuẩn ước lượng xấp xỉ 1,3 lần khoảng cách giữa hai giá trị. Chẳng hạn, ai đó khoe đạt kết quả 49 lít trong khi hai giá trị tham chiếu là 43 và 47 lít: độ lệch chuẩn khoảng 5 lít, điểm giữa là 45, nên 49 chỉ cách chưa tới một độ lệch chuẩn và là kết quả bình thường chứ không có gì nổi bật. Thông điệp chính là mẫu nhỏ cần khoảng tin cậy rộng hơn, và vài con số đã đủ cho những phán đoán thường ngày.
Your agent needs a computer, not a container — introducing @cloudflare/computer
Cloudflare ra mắt bản xem trước của @cloudflare/computer, một môi trường chạy agent mã nguồn mở, cài qua npm, cấp cho mỗi agent một “máy tính” riêng gồm hệ thống tệp, shell, công cụ và khả năng thực thi mã. Luận điểm chính là cấp cho mỗi agent một container riêng sẽ không mở rộng nổi khi số agent chạy đồng thời lên tới hàng trăm triệu, thậm chí hàng tỷ. Isolate phù hợp hơn: khởi động và dừng rất nhanh, ngủ đông khi rảnh, tự lưu trạng thái và mở rộng theo chiều ngang; container chỉ nên dùng khi thực sự cần năng lực của một máy Linux đầy đủ. Mục tiêu đặt ra là container chỉ đảm nhận dưới 10% khối lượng việc của một agent.
Kiến trúc tách “bộ não” khỏi “đôi tay”: vòng lặp agent chạy trong một Durable Object, còn container được gắn vào và gọi như một công cụ khi cần. Không gian làm việc là hệ thống tệp ảo dựa trên SQLite, nạp dữ liệu từ kho lưu trữ đám mây hay kho git, cung cấp các thao tác đọc, ghi, sửa, liệt kê, thực thi, và dùng được qua lớp bọc tương thích node:fs. Có hai môi trường thực thi chung một giao diện exec: isolate dùng just-bash để dịch lệnh shell sang JavaScript, còn container dùng FUSE để đồng bộ thay đổi về không gian làm việc. Mọi thao tác trên tệp đều được kiểm soát và ghi nhật ký, còn mô hình tự chọn môi trường phù hợp cho từng lệnh, việc mà theo tác giả các mô hình hàng đầu làm khá tốt. Cloudflare coi đây là thử nghiệm và mong nhận phản hồi từ những ai chạy agent ở quy mô lớn.
Notes on incidents
Sean Goedecke chia sẻ những gì anh rút ra sau nhiều lần tham gia xử lý sự cố. Trước hết, sự cố phần lớn khá nhàm chán, chủ yếu là chờ đợi: chờ đội khác, chờ triển khai hay chờ đồng nghiệp được gọi dậy. Đa số sự cố tự khỏi, vì hệ thống thiết kế tốt có cơ chế tự phục hồi như Kubernetes khởi động lại pod bị sập hay hàng đợi hấp thụ đợt tăng tải. Anh ước tính hơn một nửa số cuộc gọi sự cố anh từng tham gia sẽ kết thúc trong khoảng thời gian tương tự dù không ai can thiệp. Ngược lại, phần lớn hành động “cứu hỏa” lại làm mọi chuyện tệ hơn: xóa một hàng đợi lớn trên môi trường thật có thể vô tình xóa luôn các tác vụ tính tiền, biến sự cố độ trễ thành sự cố thanh toán. Vì vậy việc đầu tiên nên làm là… không làm gì cả: pha một tách trà hay đi dạo vài phút.
Cách sửa hiệu quả thường rất đơn giản, điển hình là tạm tắt tính năng gây lỗi. Yếu tố quan trọng nhất là hiểu biết về hệ thống: một kỹ sư nắm rõ kho mã sẽ nhanh chóng tìm ra đúng feature flag hay commit cần hoàn tác. Người đó cũng cần dũng cảm và quyết đoán: nói rõ mình định làm gì, chờ một chút rồi làm. Xử lý sự cố giúp ghi điểm với cấp trên, nhưng tác giả nhắc rằng đó không phải nguồn uy tín bền vững, vì lãnh đạo khó phân biệt nỗ lực anh hùng với cách sửa hiển nhiên, và kết quả tốt nhất vẫn là không xảy ra sự cố.
Beyond “Clean Code”: Why Your Comments Matter
Tom Moertel cho rằng chú thích là thành phần cần thiết của mã nguồn tốt. Logic chỉ diễn đạt được điều máy tính được ra lệnh làm, trong khi người đọc còn cần biết tác giả định làm gì và tại sao mã được viết như vậy, những thông tin thường diễn đạt tốt nhất bằng ngôn ngữ tự nhiên. Nên thể hiện ý đồ ngay trong mã khi làm được một cách tự nhiên, nhưng đừng bẻ cong cấu trúc hay đặt tên thật dài chỉ để nhét lời giải thích vào. Anh đồng ý với Robert C. Martin trong Clean Code rằng chú thích không nên dùng để chống đỡ cho logic tồi, nhưng cho rằng khẳng định “chú thích là thất bại” đã đi quá xa. Ví dụ về thông tin “tại sao” gồm thứ tự khóa toàn cục để tránh deadlock, một bất biến về độ dài mảng, lý do chọn cách vét cạn vì đầu vào được bảo đảm nhỏ.
Anh gợi ý một phép thử: đọc mã mà bỏ qua tên gọi, nếu cấu trúc phức tạp hơn cần thiết thì có thể nó đang bị bẻ cong, khi đó hãy dùng chú thích. Anh cũng phản bác các lập luận quen thuộc. “Chú thích có thể nói dối”: không có chú thích thì logic sai chẳng để lại dấu hiệu gì, còn chú thích mâu thuẫn với mã chính là tín hiệu để điều tra. “Chú thích bị lỗi thời”: đó là vấn đề văn hóa kỹ thuật, cần sửa bằng duyệt mã chứ không phải xóa chú thích. Kết luận: mọi thứ trong mã nguồn nên truyền đạt ý đồ rõ ràng, và riêng logic thì không làm được điều đó với thông tin “tại sao”.
Relying on Go
Nhiều ngôn ngữ lập trình mới tự giới thiệu là “giống Go nhưng nhiều tính năng hơn” hoặc “giống Rust nhưng đơn giản hơn”. Anton Zhiyanov chọn hướng khác với Solod, “ngôn ngữ hệ thống dành cho lập trình viên C và Go”: thay vì sửa Go hay tạo ra một ngôn ngữ na ná Go, Solod chính là một tập con của Go. Nhờ vậy nó tận dụng nguyên bộ công cụ sẵn có: tô sáng cú pháp, LSP, linter và quản lý gói. Quy trình làm việc y hệt Go: cài công cụ dòng lệnh so, tạo module, thêm thư viện chuẩn của Solod làm phụ thuộc rồi viết mã Go bình thường; lệnh so run . chạy chương trình như go run. Thư viện chuẩn của Solod tái sử dụng phần lớn mã và kiểm thử của Go, với một số hàm được sửa để hỗ trợ quản lý bộ nhớ thủ công.
Tác giả cũng nói rõ giới hạn: công cụ Go chuẩn không biết về tập con này nên không cảnh báo khi dùng tính năng chưa được hỗ trợ như hàm ẩn danh hay iterator, việc đó do công cụ so đảm nhận. Mã được chuyển từ Go sang cũng không mặc nhiên đúng, nên Solod vẫn cần kiểm thử riêng. Bên dưới, mã Solod được dịch sang C11 rồi biên dịch bằng GCC hoặc Clang, hưởng lợi từ hàng chục năm tối ưu của C; mã C sinh ra vẫn khá dễ đọc, và vì không có runtime nên gọi qua lại với C không tốn chi phí. Thông điệp chính: một ngôn ngữ mới không nhất thiết cần một hệ sinh thái mới, và dựa vào Go chính là điểm mạnh của Solod.