mirror of
https://github.com/tiennm99/blog.git
synced 2026-10-11 12:09:02 +00:00
docs(newsletter): add newsletter 133
This commit is contained in:
1 parent
5e318ba847
commit
54b65c2f54
1 file changed
+68
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: "Newsletter #133"
|
||||
date: 2026-10-01
|
||||
tags: ["AI-Assisted", "Go", "AI Agents", "Software Design", "Reliability", "Databases", "Statistics"]
|
||||
categories: ["Newsletter"]
|
||||
---
|
||||
|
||||
*Mời bạn thưởng thức Newsletter #133.*
|
||||
|
||||
## [Why Go is an Ideal Language for AI-Assisted Software Engineering](https://developers.googleblog.com/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ì. AI giống một đồng đội giỏi nhưng khó đoán, nên 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 không chỉ là ngôn ngữ mà 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 và đơn giản hơn là ngắn gọn hay khéo léo, và khi mã của kỹ sư lâu năm, người mới lẫn mô hình ngôn ngữ đều có chung một định dạng, việc phát hiện lời gọi API bịa đặt, lỗi logic hay lỗ hổng 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 và module mirror chống việc phụ thuộc bị sửa đổi hay biến mất, còn `govulncheck` chỉ cảnh báo những lỗ hổng mà mã thực sự gọi tới. Kiểm thử và fuzzing có sẵn giúp gia cố mã trước khi lên môi trường thật. 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 duy nhất, và `go fix` có hàng chục bộ hiện đại hóa giúp agent cập nhật mã cũ sang cách viết mới một cách tất định. Bài viết thiên về lập luận, không đưa ra số liệu đo đạc cụ thể, nhưng thông điệp rõ ràng: AI là cộng sự năng suất cao cần những 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?](https://danluu.com/pl-tokens/)
|
||||
|
||||
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 (C tốn khoảng 2,6 lần Clojure, J tiết kiệm nhất), 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, một symlink đưa mọi kiểm thử sau đó về cùng một tệp thực thi Go, và có 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, không có internet hay kiểm thử, 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. Bài thứ ba, cài đặt một trò chơi cờ bàn có luật mơ hồ, bị loại vì mọi ngôn ngữ đều được gần 0 điểm.
|
||||
|
||||
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ẹ tới vừa với độ chính xác và chi phí thấp. Đáng chú ý, 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à bộ 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 một ngôn ngữ phổ biến là lựa chọn 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](https://domenic.me/agentic-coding-setup/)
|
||||
|
||||
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, gập máy vẫn chạy tiếp, 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 ứng dụng ChatGPT hơn vì Claude đặt worktree ngay trong thư mục dự án, khiến `node_modules` và các lệnh tìm kiếm bị lẫ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, vốn có thể là nơi duy nhất lưu lại các quyết định thiết kế.
|
||||
|
||||
## [The Bedrock of Software Design](https://alex.draftist.io/blog/the-bedrock-of-software-design-ycqvcedsj)
|
||||
|
||||
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 hơn bất cứ điều gì khác, và chúng đơn giản hơn cái tên rất nhiều. Có hai loại: *kiểu tích* gộp nhiều trường thành một giá trị, như một struct có `id` và `role`; còn *kiểu tổng* nói rằng một 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 là ẩn danh, hoặc là đã 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ụ thường nằm rải rác trong chú thích, hàm kiểm tra hay trong đầu ai đó nên dễ lỗi thời hoặc 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, cho phép vô số tổ hợp sai, 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. Mục tiêu là khiến 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à bản thân kiểu lỗi cũng có thể là kiểu tổng kèm ngữ cảnh, như khoảng giá trị hợp lệ khi cổng nằm ngoài phạm vi. 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, biến thay đổi nghiệp vụ thành một danh sách việc cần làm. Kết luận của tác giả: 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, không phải tính năng tùy chọn.
|
||||
|
||||
## [90 % of the t distribution](https://entropicthoughts.com/ninety-percent-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"), người từng làm việc ở hãng bia Guinness: 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. Độ lệch chuẩn mẫu của hai số đánh giá thấp mức phân tán thật rất nhiều, nhưng 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](https://blog.cloudflare.com/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. Bài có ví dụ một agent phân loại lỗi tự sao chép kho mã, tái hiện và sửa lỗi. 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](https://www.seangoedecke.com/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ố. Điều đầu tiên: 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, chờ thay đổi có hiệu lực hay chờ đồng nghiệp được gọi dậy. Điều thứ hai: đ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, circuit breaker cho dịch vụ quá tải thời gian hồi phục, 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 để tránh hành động vội vàng.
|
||||
|
||||
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, và viết bản vá chỉ mất vài phút trong khi duyệt mã, CI và triển khai tốn cả giờ. 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, trong khi nhiều kỹ sư giỏi khác thì loay hoay. 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](https://blog.moertel.com/posts/2026-07-27-beyond-clean-code-why-your-comments-matter.html)
|
||||
|
||||
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, tách thêm hàm hay đặt tên thật dài chỉ để nhét lời giải thích vào, vì như vậy mã càng khó đọc. 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ỏ, hay thời gian chạy kỳ vọng của một biến thể tìm kiếm nhị phân; mã hóa chúng vào tên biến sẽ sinh ra những định danh vô lý.
|
||||
|
||||
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 quy trình như 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 nhất có thể, và riêng logic thì không làm được điều đó với thông tin "tại sao".
|
||||
|
||||
## [Relying on Go](https://antonz.org/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; có hàm được giữ gần như nguyên vẹn, có hàm phải sửa để hỗ trợ quản lý bộ nhớ thủ công qua các bộ cấp phát tường minh.
|
||||
|
||||
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, kể cả chạy với sanitizer và công cụ phân tích tĩnh. 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.
|
||||
|
||||
## [Beyond Happy Path Engineering: Databases](https://blog.gaborkoos.com/posts/2026-08-01-Beyond-Happy-Path-Engineering-Databases/)
|
||||
|
||||
Bài tiếp theo trong loạt viết về việc làm phần mềm bền vững khi rời khỏi "đường đi hạnh phúc", lần này là cơ sở dữ liệu, tầng thường được coi là đáng tin nhất. Ví dụ xuyên suốt là luồng thanh toán của một cửa hàng trực tuyến: kiểm tra tồn kho, tạo đơn, ghi nhận thanh toán, trừ kho, hiển thị xác nhận, chạy trơn tru khi kiểm thử cục bộ vì không có lưu lượng cạnh tranh. Môi trường thật thì khác: thanh toán, trang quản trị, tác vụ nền, báo cáo và migration cùng tranh nhau kết nối, khóa và bộ nhớ đệm. Một truy vấn chậm giữ kết nối và khóa, khiến pool kết nối cạn, yêu cầu xếp hàng, người dùng thử lại, và cuối cùng "thanh toán sập" dù chẳng có gì hỏng hẳn. Hai yêu cầu có thể cùng đọc thấy còn một sản phẩm và cùng bán nó; transaction không tự giải quyết được, vì quy tắc nghiệp vụ phải được thực thi tường minh. Ngoài ra còn bản sao đọc bị trễ khiến người dùng không thấy đơn vừa tạo, timeout không cho biết lệnh ghi đã commit hay chưa, deadlock, và migration chạy trong lúc nhiều phiên bản ứng dụng cùng hoạt động.
|
||||
|
||||
Tác giả đề xuất bắt đầu từ bất biến cần giữ, như "không bán vượt tồn kho", và thực thi nó ngay trong câu lệnh ghi, kèm ràng buộc trong cơ sở dữ liệu thay vì chỉ trong mã ứng dụng, vốn có thể bị script hay trang quản trị bỏ qua. Giữ transaction ngắn, không gọi mạng bên trong, truy cập bảng theo thứ tự nhất quán và chỉ thử lại lỗi tạm thời. Thao tác ghi cần idempotent với mã định danh ổn định, mỗi endpoint cần quy định rõ mức độ "tươi" của dữ liệu đọc, migration nên chạy theo nhiều bước tương thích, và khôi phục phải được diễn tập trước. Các kỹ thuật mạnh hơn như transactional outbox hay isolation serializable chỉ nên dùng khi có áp lực đo được. Sự cố của Atlassian năm 2022 và GitHub năm 2018 cho thấy khả năng khôi phục và tính đúng đắn quan trọng không kém độ bền dữ liệu.
|
||||
Reference in new issue
Block a user