- Ngay cả khi LLM tiếp tục viết code thay bạn, nếu cứ merge nguyên các câu điều kiện trùng lặp và triển khai tạm bợ, phần code được sinh ra về sau có thể đi theo thực hành đó như quy tắc của dự án
- Nếu lặp lại logic kiểm tra quyền truy cập trong route handler, background job, API endpoint, webhook, v.v., dù test có pass thì gánh nặng bảo trì vẫn còn nguyên
- Vì mô hình tạo code tiếp theo dựa trên các file đang mở, pattern hiện có và thay đổi gần đây, 4 câu điều kiện bị copy sẽ trở thành tín hiệu gọi ra bản copy thứ năm
- Ngay cả khi sau này yêu cầu refactor, cũng khó đảm bảo LLM sẽ dọn dẹp đúng tất cả các bản copy hiện có; pattern xấu sẽ gần với style của codebase hơn là một lỗi nhất thời
- Khi các câu điều kiện trùng lặp, hàm “god” và các lần merge kiểu “để sau dọn” tích tụ, sẽ khó đảo ngược chỉ bằng prompt, và cuối cùng con người vẫn phải tự sửa
Thứ LLM tham chiếu là codebase hiện tại
- LLM không viết code trong “chân không”, mà đọc codebase của người dùng
- Các file đang mở
- Pattern đã tồn tại
- Những thay đổi gần đây
- Những lối tắt đã được merge vào codebase trở thành tín hiệu học rằng “ở đây làm như thế này”
- Cùng một điều kiện kiểm soát truy cập có thể bị lặp lại ở nhiều nơi
if (user.isActive && user.hasPermission('read') &&
!user.isSuspended && account.status === 'open') {
// do a thing
}
- Câu điều kiện này có thể được trích xuất thành helper dùng chung, nhưng code do LLM tạo ra có thể bị merge nguyên chỉ vì nó chạy được và test pass
- Khi yêu cầu endpoint thứ năm có cùng quy tắc, mô hình nhiều khả năng sẽ làm theo các bản copy hiện có trong repository thay vì thiết kế lại từ đầu
Ảo tưởng rằng có thể giao việc bảo trì cho LLM
- Suy nghĩ “sau này khi cần đổi thì LLM cũng sẽ làm” khiến ta bỏ mặc trùng lặp và code smell
- Một vài câu điều kiện trùng lặp có thể không chí mạng, nhưng những code smell như vậy sẽ tiếp tục tích tụ
- Câu điều kiện trùng lặp
- Hàm “god”
- Các lần merge đã định “để sau dọn”
- Khi pattern xấu tăng lên, chúng cũng ảnh hưởng đến kết quả của prompt tiếp theo, và khó có thể tin rằng sau này LLM sẽ sửa không sót tất cả các instance
- Dù nghĩ rằng mình đang outsource việc bảo trì cho LLM, thực tế có thể lại là tạo ra tình huống khiến nó lặp lại các thói quen ngày càng tệ hơn
- Cần viết code như thể con người sẽ bảo trì nó, và phải giữ cho các pattern code mà LLM hấp thụ rồi trả ngược lại luôn ở trạng thái tốt
1 bình luận
Các ý kiến trên Hacker News
Nên tạo lệnh /review bằng một file Markdown trống tại
.claude/commands/review.md, rồi đưa vào đó checklist mà agent cần kiểm traKhi cần review code, nhập
/reviewthì nó sẽ xem checklist đó, lập kế hoạch các mục có thể sửa rồi hỏi lạiFile của tôi bắt đầu bằng “hãy vào chế độ lập kế hoạch. xem xét khác biệt giữa nhánh này và main. những điều cần cân nhắc: ...”, và tôi liên tục thêm các mục phát hiện trong quá trình review code rồi giao cho agent sửa, nên giờ đã khoảng 200 mục
Agent không bận tâm khi nhận cả một bức tường phản hồi chung chung mà sẽ xem từng mục một; tôi đã ngạc nhiên khi thêm “hãy kiểm tra xem những thứ mới tạo có trùng lặp với code hiện có không” thì nó thực sự bắt đầu lên kế hoạch dọn dẹp
Vẫn mới chỉ là mức chạm bề mặt, và ta cần đưa cho công cụ công cụ dành cho công cụ để nó trở thành công cụ tốt hơn
Hiện tôi vẫn chỉ dùng các chỉ dẫn khá đơn giản, nhưng Claude thường xuyên vi phạm những chỉ dẫn đầu tiên như “không commit vào git khi chưa được phép”, “không ký tên vào commit message”
Khi hỏi thì nó trả lời “đúng, có chỉ dẫn đó nhưng tôi đã bỏ qua”, và nếu chỉnh lại một cách lịch sự trong phiên làm việc thì nó hiểu, nhưng về sau đôi khi lại rơi vào trạng thái hoàn toàn không thể commit
Nếu bắt nó rà soát checklist 200 mục, rất có khả năng nó sẽ âm thầm bỏ sót khá nhiều mục trong đó
Nếu là kỹ sư con người, khi 200 test hiện có dùng một thư viện assertion thì hẳn sẽ không dùng một thư viện hoàn toàn khác cho test mới, nhưng Claude đã làm vậy nhiều lần
Vì thế tôi cứ phải thêm các mục như “trước khi viết, hãy xem xét quy ước test”
Ngược lại, những điều cơ bản như hàm là gì, hay test phải xử lý diff thay đổi, thì không cần phải nói; nhưng không có danh sách rõ ràng cho biết bên nào cần nói và bên nào thì ổn, nên cảm giác như đang thử sai để tạo ra một cách làm dùng được
Trường hợp của tôi thì thường tinh chỉnh qua lại với agent “cho đến khi thấy ổn theo mắt và gu của tôi”, nhưng vẫn chưa tạo một danh sách như vậy
Tùy dự án mà có thể cho phép các vấn đề nhỏ hoặc magic number, còn ở dự án khác lại bắt buộc hằng số có tên mang ý nghĩa như
SECONDS_IN_A_DAY = 24 * 60 * 60, nên rất phụ thuộc vào ngữ cảnhhttps://github.com/alibaba/open-code-review
https://layandreas.github.io/personal-blog/posts/beyond-vide...
Ví dụ, cho nó chọn N vai trò phù hợp nhất với thay đổi từ một danh sách vai trò dài như Senior Engineer, Security Engineer, WCAG specialist
Claude chạy các review đó song song rồi tổng hợp phản hồi
Vì tôi phát triển dựa trên đặc tả, nên tôi thêm các vấn đề phát hiện được vào đặc tả để lưu lại dấu vết của vấn đề và quyết định
Điều lạ là ở đây có rất nhiều kỹ sư lại chồng thêm một prompt khác
Theo kinh nghiệm của tôi, càng làm vậy thì càng tệ hơn: có trừu tượng hóa, nhưng lại tạo ra trừu tượng hóa sai; thêm chú thích quá mức, khiến cả những lần gọi LLM sau đó cũng bị rối
Trong một codebase tốt thì nó còn hoạt động tàm tạm, nhưng dần dần làm mã xấu đi; cứ dùng tiếp rồi đến một lúc nó không chạy nữa, bạn sẽ phải trả giá cho việc trước đó không tự tay tạo ra nó mà sửa chữa
Khi đưa agent vào một codebase mới, thường vẫn còn mô hình tinh thần về mã và mã cũng tương đối gọn, nhưng qua nhiều vòng lặp thì cả hai đều biến mất và hiệu năng của LLM cũng giảm
Vì vậy tôi dùng LLM cho khám phá và review, còn mã thì tự viết
Viết code cũng không tốn quá nhiều thời gian và còn là phần thú vị nhất, nên tôi khó hiểu vì sao lại muốn né tránh; thỉnh thoảng thử “đua debug” cùng AI bằng prompt
/bugthì AI cũng không phải lúc nào cũng nhanh hơnTrong vài năm gần đây, công việc phần mềm đã chuyển từ một trong những nơi trú ẩn kỹ thuật thực dụng cho những người thích mày mò tò mò và nghiện giải đố, thành một con đường sự nghiệp cho những người thông minh nhắm tới tiền bạc, giống như tài chính, luật hay y khoa
Nhiều người hiện mang chức danh “kỹ sư phần mềm” ngay từ đầu chưa từng thích công việc đó; họ chỉ thông minh, có trách nhiệm và đạt được những mục tiêu vừa phải mà nhà tuyển dụng giao
Chính những người như vậy mong AI agent nhất: để nó chặn bớt phần thiết kế nghiêm ngặt và việc giải đố, đồng thời cho phép họ tận dụng sự thông minh bẩm sinh theo cách lười hơn
Vì họ chưa nội hóa được các nguyên tắc coding và kỹ thuật, nên khi bị bao quanh bởi những đồng nghiệp cùng tâm thế, rất khó dự đoán cách làm này sẽ dẫn tới kết quả gì trong tương lai
Nếu bản thân việc coding ngay từ đầu đã là một trải nghiệm rất bực bội và nhiều ma sát, thì rất dễ cảm thấy AI nhanh hơn
Với code, chỉ đọc thôi là chưa đủ; phải trải qua một cách đau đớn thì mới nội hóa được
Agent thường bọc phòng thủ quanh mã cũ thay vì hỏi liệu đường đi hiện có còn nên tồn tại không, tạo ra hiệu ứng một lượng khổng lồ mã phòng thủ chồng lớp như búp bê Nga
https://softwaredoug.com/blog/2026/07/09/write-code
Opus 4.8 là bước ngoặt; đặc biệt với các vấn đề phức tạp, giờ tôi không thắng Opus 4.8 được nhiều nữa
Nếu mọi người đều dùng Opus 4.8 trở lên cho mọi tác vụ và câu hỏi, bầu không khí chung sẽ khác đi rất nhiều, và có lẽ sẽ không còn nhiều người hoài nghi AI
Vẫn tự tay viết code, dù không phải toàn bộ; một phần do Opus tạo ra
Có thể là một ý nghĩ lệch pha, nhưng cứ tự viết code là được
Trong thời đại AI, nghe có vẻ như một khái niệm khó tin, nhưng nếu đó là mã mà con người phải đọc và bảo trì, thì tốt hơn là tự viết vì những con người đó
Khi đọc những đoạn mã quá dài dòng, sao chép-dán, bạn sẽ bực mình; người khác cũng vậy
Nếu tự viết, bạn sẽ tự sửa và viết theo cách hợp lý để người khác bảo trì
Hoặc bạn cũng có thể dỗ dành agent và vòng lặp bằng cách tạo ra một mạng lưới phức tạp các file Markdown để chúng hiểu hình dạng mã mà người bảo trì tương lai kỳ vọng
Về dài hạn tôi không biết con đường nào dễ hơn, và tôi tò mò liệu đã có ai thừa hưởng rồi tìm hiểu một codebase do agent dẫn dắt dựa trên vòng lặp chưa
Tôi không chắc câu “lần sau khi bạn yêu cầu LLM một endpoint có cùng quy tắc truy cập, mô hình sẽ không suy nghĩ từ đầu mà bắt đầu từ bốn bản sao đã có trong repository” đúng đến mức nào
Thực tế có vẻ nó có một thiên kiến tích hợp sẵn là lặp lại cấu trúc cơ bản và ít tái sử dụng hay trừu tượng hóa hơn
Nếu pattern hiện có là như vậy thì trông như nó đang làm theo, nhưng thực ra khả năng cao là dù theo hướng nào nó cũng sẽ làm như thế
Ngay cả khi tôi dựng sẵn trừu tượng hóa nghiêm ngặt và ví dụ sử dụng, rồi chỉ rõ rằng nó chỉ được dùng API trừu tượng hóa cụ thể đó và phải sao chép cả cách tôi đã viết, nhiều LLM mới nhất vẫn không làm cả hai, mà tự triển khai lại cấu trúc cơ bản từ dưới lên, bỏ qua trừu tượng hóa một phần hoặc hoàn toàn
Tôi không biết chính xác vì sao, nhưng có lẽ vì trong dữ liệu huấn luyện có quá nhiều mã kiểu này, nên các trọng số “biết” rõ hơn cách tạo ra kết quả theo kiểu đó
Dù vậy, tôi vẫn nghĩ dùng LLM như một động cơ triển khai nhanh là ổn
Thách thức là khiến mô hình bộc lộ trước các quyết định triển khai này trước khi nó lao sai hướng
Sau những thay đổi lớn, tôi thu được kết quả tốt với prompt sau
“Bây giờ hãy kiểm tra mã lần cuối. Mọi thứ đã gọn gàng chưa và các component có tuân theo nguyên tắc tách biệt mối quan tâm không? Nó có ở trạng thái dễ hiểu và có thể bảo trì không? Có đang đưa ra giả định nào có thể không còn đúng nữa không? Có mã còn sót lại từ các lần chỉnh sửa hay thử nghiệm trước trong codebase không? Tài liệu có vẫn phản ánh trạng thái hiện tại của mã không?”
Khi đó nó thường suy luận ra những điều nêu trên và hơn thế nữa
Tuy nhiên điều tôi vẫn phải liên tục chỉ rõ là hãy xóa tất cả chú thích dùng để “theo dõi tiến độ”, và chỉ để lại những chú thích phù hợp cho bảo trì dài hạn
Claude hay để lại các chú thích như “việc nhấp nút giờ sẽ kích hoạt lưu và không còn dùng onBlur nữa”, trong khi mã thực tế chưa từng dùng onBlur; đó chỉ là dấu vết của việc trước đó trong cùng task/branch Claude định làm gì đó và tôi đã quay nó lại
Mô hình sẽ diễn giải theo ý nó, nhưng dù vậy thường vẫn tốt hơn là không làm gì
Đó là cách dạy AI mọi thứ rồi hỏi xem nó đã học đúng chưa, và kết quả tốt một cách bất ngờ
Tôi cũng đang làm theo các bước tương tự bài viết này
https://www.lucasfcosta.com/blog/backpressure-is-all-you-nee...
Có một câu ngạn ngữ cũ
“Hãy chú thích code như thể người bảo trì tiếp theo là một kẻ sát nhân biết nơi bạn sống”
Gần đây trong review PR, tôi gặp kiểu đó không biết lần thứ mấy và đã nổi cáu để lại comment, chính tôi cũng thấy ngạc nhiên
Tôi không biết mình có thể phản ứng như vậy
Tức là vì bản thân code không đủ rõ ràng nên mới có comment; điều đó đôi khi đúng, nhưng nói chung tôi nghĩ nhiều comment vẫn tốt hơn ít comment
Đặc biệt nếu chúng giải thích code liên hệ thế nào với nghiệp vụ thực tế hoặc yêu cầu tính năng, chứ không chỉ lặp lại việc code đang làm
Vài năm trước tôi thường viết comment trước
Tôi giải thích mục tiêu tổng thể, chia nó thành các routine và thứ tự công việc, rồi khi thấy ổn thì điền các block code vào giữa các comment
Nó hơi giống một dạng lập trình văn chương, nhưng tôi đã làm như vậy từ trước khi biết thuật ngữ đó, và nó gần với việc tự đưa prompt cho bản thân để hướng tới mục tiêu hơn
Nhược điểm là comment cuối cùng dễ chỉ dừng ở mức giải thích bằng tiếng Anh những gì code làm, nên có thể không hữu ích lắm cho người bảo trì trong tương lai
Code nên tự giải thích được chính nó, còn comment là để dùng ở nơi có rồng
Trong bối cảnh tương tự, prompt tôi thích là “Hãy review các test bạn đã viết. Những test này có thực sự kiểm tra điều chúng định kiểm tra không? Nếu code hỏng thì test có fail không?”
Thật đáng ngạc nhiên là LLM thường xuyên viết test rỗng không xác minh gì cả
Tôi tự hỏi liệu đến giờ vẫn còn phải thảo luận nghiêm túc những chuyện như thế này sao
Nếu đã “thử nghiệm” như vậy với LLM, chẳng phải bây giờ nên hiển nhiên chấp nhận rồi sao
Tôi tự hỏi đến khi nào chúng ta mới có thể nói về việc code tay mà không còn xem nó như điều cấm kỵ nữa
LLM hữu ích theo nhiều cách, nhưng khi thấy mọi người giao phó việc gõ toàn bộ source code cho agent, tôi thấy phát ngán
Cảm giác giống như được bảo rằng vì web tốt nên chúng ta phải hạnh phúc
Tôi đang liên tục chạy codebase qua nhiều model để tìm những “mùi” xấu như code trùng lặp
Việc này khá hiệu quả, và nếu không tiếp tục quản lý theo thời gian thì nó sẽ thành một đống lộn xộn, rồi cứ thế tích tụ
Chúng cũng có thể đưa vào build pipeline và hoàn toàn không tốn token
Hay quy trình review và đặt lại ngữ cảnh mới quan trọng hơn?
Tôi đã thấy rất nhiều kiểu trùng lặp như vậy, và cả những thứ tệ hơn, trong code được con người bảo trì suốt 20 năm
Thành thật mà nói, trong đa số trường hợp, code do con người viết và bảo trì còn tệ hơn những gì LLM tạo ra hiện nay
Đôi khi là do thiếu kinh nghiệm, đôi khi là do cố tình cẩu thả, nhưng nhìn chung là vì lịch trình quá gấp và áp lực phải hoàn thành ngay
Mọi người biết cách làm tốt hơn, nhưng thực tế không có thời gian và ngân sách để làm như vậy
LLM cũng đã học điều đó