Sau vài tháng code bằng LLM, tôi quyết định dùng lại bộ não của mình
(albertofortin.com)- Đã xây dựng hạ tầng bằng LLM hiệu năng cao, nhưng bộc lộ những vấn đề lớn về chất lượng mã và khả năng bảo trì
- Vì sự kém hiệu quả của AI và kết quả thiếu nhất quán, tác giả cảm thấy cần tự mình hiểu mã, tự nghiên cứu và nâng cao năng lực
- Mục tiêu hoàn thành dự án thật nhanh lại dẫn đến cấu trúc mã hỗn loạn, trùng lặp và thiếu nhất quán
- Giờ đây chỉ giới hạn việc dùng AI cho các tác vụ hỗ trợ như công việc lặp lại đơn giản hoặc chuyển đổi mã
- Vì việc dùng AI có thể dẫn đến suy giảm cảm giác code và năng lực giải quyết vấn đề, tác giả ưu tiên chủ động dùng bộ não của mình
Mở đầu: Thử xây dựng hạ tầng với LLM
- Nhận ra hạ tầng PHP+MySQL hiện có đã chạm giới hạn và cần một hạ tầng mới
- Chọn Go và Clickhouse, đồng thời cùng AI thiết kế hạ tầng và lập kế hoạch
- Hỏi các LLM như Claude về best practices và kiến trúc, rồi xây dựng một kế hoạch chi tiết
- Nhắm tới hoàn thiện tính năng và phát hành nhanh, nên quá trình phát triển mã được đẩy theo định hướng tốc độ
Quá trình phát triển và sự xuất hiện của vấn đề
- Dùng các công cụ như Cursor để AI viết mã, còn bản thân tập trung vào build và test
- Dù codebase chưa được sắp xếp gọn gàng, vẫn ưu tiên cung cấp dữ liệu đang cần trước
- Dù phát triển rất nhanh, theo thời gian vẫn liên tục phát sinh vấn đề mới
- Do thiếu kinh nghiệm với Go và Clickhouse nên gặp khó khăn, còn các bản sửa do AI đưa ra lại gây ra chuỗi vấn đề tiếp theo
Vấn đề về chất lượng mã và cảm nhận giới hạn
- Dành thời gian review code để xem xét kỹ toàn bộ mã đã được tạo ra
- Các file làm cùng một chức năng lại không thống nhất về tên, tham số, cấu trúc và có rất nhiều trùng lặp, gây hỗn loạn
- Ví dụ:
WebAPIprovidervàwebApicùng mang nghĩa một tham số nhưng lại tồn tại tách biệt - Hiện tượng cùng một method bị định nghĩa lại trong nhiều file
- Thiếu sự nhất quán trong cách truy cập file cấu hình
- Ví dụ:
- Kết quả thực tế giống như sản phẩm do nhiều lập trình viên junior làm song song mà không hề giao tiếp với nhau
Giới hạn của phản hồi ngữ cảnh từ LLM và thay đổi chiến lược
- Dù đã cung cấp đầy đủ thông tin ngữ cảnh và dùng các LLM có cửa sổ ngữ cảnh lớn như Gemini, vẫn không cải thiện được tính nhất quán một cách đáng kể
- Nhận ra cần tự học về hạ tầng và ngôn ngữ, đồng thời học thêm qua tài liệu, video và các nguồn khác
- Để viết clean code và tổ chức mã tốt hơn, tác giả chuyển từ phát triển do AI dẫn dắt sang tự chủ thiết kế mã
Thay đổi cách dùng AI như công cụ hỗ trợ
- Tập trung vào tự hiểu và tự quản lý mã thông qua việc refactor lặp lại và chỉnh lý code
- Giới hạn vai trò của AI vào những tác vụ lặp lại đơn giản như tự động sửa mã, đổi hàng loạt tham số, chuyển đổi mã
- Với việc lên ý tưởng tính năng mới hay viết bản nháp mã, tác giả tự suy nghĩ trước rồi mới dùng LLM để kiểm chứng hoặc hỗ trợ
- Đặt AI ở vai trò “trợ lý”, còn quyền quyết định về kế hoạch và cấu trúc thì do chính lập trình viên đảm nhiệm
Lo ngại suy giảm tư duy và thay đổi thái độ
- Vì có AI nên tần suất dùng não giảm đi, và tác giả nhận ra mình đã dựa vào AI cho cả việc lập kế hoạch lẫn quá trình tư duy
- Cố gắng khôi phục năng lực của lập trình viên và khả năng giải quyết vấn đề bằng bút và giấy, thiết kế trực tiếp và tự tay code
- Cảnh giác với nguy cơ AI làm suy giảm cảm giác code
Lo ngại về người không phải lập trình viên và ‘Vibe Coding’
- Khi người không phải lập trình viên phát triển chỉ bằng LLM, hiện tượng mã phức tạp, rối rắm và lỗi lặp đi lặp lại còn nghiêm trọng hơn
- So với công cụ no-code, phát triển dựa trên AI có thể gây khó khăn lớn hơn trong việc nắm bắt cấu trúc
- Đề cập đến mức độ khó và rủi ro cốt lõi trong quá trình bị chặn trước một bức tường mã không thể hiểu nổi, kèm chuỗi lỗi-sửa-tái phát liên tục
Một vài suy nghĩ về thực tế ứng dụng AI và bầu không khí cộng đồng
- Bày tỏ sự hoang mang trước việc AI được thương mại hóa, benchmark, influencer và các công ty AI thổi phồng quá mức trong khi hiệu năng thực tế không tương xứng
- Thiếu tính nhất quán khi cùng một model và prompt lại cho ra kết quả hoàn toàn khác nhau
- Ngay cả các LLM mới và mạnh nhất cũng chưa thể xử lý hoàn hảo những tác vụ phức tạp thực tế như truy vấn hàng trăm triệu dòng trên Clickhouse
- Trong tình huống bị ép dùng thiết lập phức tạp và workflow kém hiệu quả, bản thân điều đó có thể chỉ là lãng phí thời gian
- Dù AI có vẻ rất ấn tượng, hiện tại nó vẫn chỉ là một công cụ tốt nhưng chưa thực sự xuất sắc
Kết luận
- Tác giả vẫn giữ kỳ vọng và hứng thú lớn với công nghệ mới và AI
- Tuy nhiên, ở thời điểm hiện tại, chiến lược khôn ngoan là hiểu đúng vai trò và giới hạn của AI, rồi chỉ dùng nó một cách hạn chế như công cụ hỗ trợ hoặc học tập
- Tác giả quay lại đặt trọng tâm vào tư duy và lập kế hoạch của bản thân, đồng thời cảnh báo về sự suy giảm năng lực của lập trình viên do lạm dụng AI
- Việc phát triển mà phụ thuộc hoàn toàn vào AI trong khi không hiểu “nguyên lý vận hành và cấu trúc của mã” có khả năng thất bại rất cao
2 bình luận
Ý kiến trên Hacker News
Tôi không thuộc phe hiểu được kiểu tư duy “all-in” với LLM. Tôi làm lập trình viên iOS và vẫn làm việc như bình thường. Giờ tôi chỉ dùng LLM để nhanh chóng tạo những view tạm dựa trên thiết kế. Đó không phải phần lõi của ứng dụng mà là các màn hình phụ như tính năng mới hay hướng dẫn cài widget. Trước đây việc này mất 30–60 phút tùy độ phức tạp, giờ xong trong 5 phút. Tôi ghét phát triển web, nhưng LLM khá hữu dụng ở mảng đó. Với các thay đổi lớn, tôi cũng dùng LLM rồi tự rà soát và commit lên git. Nhưng nếu chỉ tin vào LLM mà không kiểm soát luồng làm việc, có khi sẽ sụp đổ hàng giờ rồi phải làm lại từ đầu. Tôi nghĩ cách tiếp cận cân bằng là quan trọng
Độ hữu dụng của công cụ thay đổi tùy người và tùy bài toán. Ví dụ, nếu là một lập trình viên Python 10 năm kinh nghiệm đang làm công việc thiên về độ ổn định với một IDE được tinh chỉnh hoàn hảo cho một codebase legacy khổng lồ, thì các công cụ như LLM hay Cursor thậm chí có thể gây cản trở. Ngược lại, nếu là một lập trình viên JS mới 1 năm kinh nghiệm (React, Nextjs, v.v.) thường xuyên prototype ý tưởng mới, không có sở thích đặc biệt về IDE và cởi mở với thử nghiệm, thì LLM và Cursor có thể ngay lập tức nâng cao năng lực đáng kể
Tôi cũng làm nhiều mảng khác nhau (iOS, web development, v.v.), và kết quả của LLM ở hai mảng này khá khác nhau. Nhiều khi đoạn code LLM sinh ra còn không compile nổi. Thậm chí có lần nó còn chỉ cho tôi một API không hề tồn tại. Trong khi đó, app Nextjs thì nó làm ổn ngay từ một lần. Cuối cùng đây là hệ quả từ sự khác biệt trong dữ liệu huấn luyện của LLM
Việc quá tin vào năng lực của LLM là điều tự nhiên. Tôi cũng đã dùng nó khá lâu như một cách thay thế Stack Overflow và để lấy các code snippet ngắn. Rồi dần dần giao cho nó nhiều trách nhiệm hơn, gặp vấn đề, nhận ra giới hạn, và quay lại dùng LLM chủ yếu cho ý tưởng và lời khuyên. Tôi nghĩ nhiều người cũng trải qua quá trình tương tự
Tôi cũng cảm thấy tương tự. Đừng tuyệt đối hóa LLM, hãy chỉ dùng nó cho những việc lặp đi lặp lại và nhàm chán (hàm nhỏ, triển khai interface, tự động hóa tài liệu, v.v.). Nhờ vậy tôi tiết kiệm được rất nhiều thời gian và hiệu quả công việc cũng cao hơn
Với phát triển iOS, hiệu năng của LLM rất thất thường. Swift và SwiftUI thay đổi quá nhanh, tài liệu chính thức cũng sơ sài, đó là một phần nguyên nhân. Nó hữu ích để tạo các view đơn giản, nhưng với xử lý bất đồng bộ hay business logic phức tạp thì dễ sụp đổ. Dù vậy nó vẫn giúp định hướng, nhưng nguy cơ sa vào kết quả sai lệch (bịa đặt) cũng rất lớn
Những người ủng hộ LLM thường bỏ qua thực tế rằng phần lớn nút thắt không nằm ở việc sinh code. Chỉ tạo code nhanh thôi là chưa đủ; còn phải đầu tư gấp đôi thời gian cho code review, test, và hiểu codebase. Muốn bảo trì dài hạn (sửa bug, refactor, v.v.) thì bắt buộc phải trải qua những quy trình đó
Đọc code khó hơn viết code rất nhiều, nên trên thực tế tôi dành nhiều thời gian hơn để hiểu code. Thế nhưng có một CEO tôi từng gặp lại cho rằng chỉ cần cung cấp thông tin ngữ cảnh cho công cụ là lập trình viên không cần đọc code nữa. Lập luận đó là AI đang thay đổi bản chất của kỹ thuật phần mềm. Thành thật mà nói tôi thấy khá hoang mang
Tôi thấy LLM khá hữu ích khi nó giải thích lại chính code của tôi
Mỗi khi ai đó hết lời ca ngợi các trình soạn thảo code tự động, tôi lại nghĩ đúng điều này
Thực tế thì phần lớn lập trình viên không quá bận tâm đến cách thư viện phụ thuộc được hiện thực bên trong. Điều quan trọng chỉ là interface có hoạt động hay không. Việc đưa code do LLM tạo ra vào dự án khác rất nhiều so với kéo một npm package hay rust crate vào. Tôi cũng biết các vấn đề của nó, nhưng việc làm này phổ biến rộng rãi cũng có lý do của nó
Tôi cũng nghĩ tương tự. Dạo này tôi chủ yếu dùng LLM để học công nghệ mới hoặc sinh client code cho các API chuẩn (đặc biệt là boto3). Tôi cũng thử Windsurf để hỗ trợ chỉnh file docker compose nhưng thất vọng vì nó không chạy đúng. Có lẽ nó làm prototype được, nhưng không hơn. Tôi nghĩ LLM đã thay đổi cuộc chơi trong mảng devops (giờ chi tiết API bớt quan trọng hơn). Nhưng các quyết định quan trọng thì tôi vẫn phải tự đưa ra. Tôi tự định nghĩa interface, rồi chỉ giao phần hiện thực cho LLM. Tôi không nghĩ đó là “vibe coding”
Tôi từng có trải nghiệm bug cực lớn bùng nổ trong lúc code review, và mọi hiệu quả có được từ việc dùng Cursor biến mất chỉ trong chớp mắt. Tôi quay lại VSCode, còn Copilot thì chỉ dùng hạn chế khi cần yêu cầu rất cụ thể. Tính năng tab completion của Cursor lúc đầu thấy như phép màu, nhưng rồi hiệu quả đó nhanh chóng biến mất
Điều buồn cười nhất là nhìn đồng nghiệp theo phản xạ xem Cursor cố gắng gõ lại đoạn code mà họ vừa mới xóa bằng tab completion
Tôi tò mò không biết bạn đã đặt ra những ràng buộc nào cho agent sinh code đó (ví dụ: nguyên tắc SOLID, lint, coverage 100%, tài liệu thiết kế rõ ràng, v.v.)
Đây cũng là ý kiến tôi rất đồng cảm. Tôi cũng dùng LLM rất nhiều, nhưng có hai quy tắc. Thứ nhất, tuyệt đối không giao cho LLM những vấn đề đòi hỏi suy nghĩ sâu (thiết kế phức tạp thì nhất định phải tự giải quyết). Thứ hai, code do LLM sinh ra thì nhất định phải review và chỉnh sửa cẩn thận từng dòng. Thường code do LLM tạo ra dài dòng hoặc quá phòng thủ. Dù có sửa bằng prompt đi nữa thì cuối cùng trách nhiệm bảo trì sau này vẫn thuộc về tôi. Nếu thờ ơ với kết quả sinh code thì cảm giác bất an vẫn còn đó. Nếu dùng theo cách của tôi, tôi vẫn dùng LLM rất nhiều và phát triển nhanh hơn
Tôi lại giao chính việc phân tích sâu cho AI, với mục đích tạo ra kế hoạch thực thi cụ thể (các bước hiện thực chi tiết, tiêu chí kiểm chứng, v.v.) và viết báo cáo có thể tái lập. Việc lập kế hoạch và kiểm chứng đúng là cần lặp đi lặp lại, nhưng nhờ có AI nên xong nhanh hơn rất nhiều. Đôi khi theo đúng kế hoạch là xong ngay một lần. Có được tính nhất quán nhờ kế hoạch và tài liệu chi tiết thì rất thỏa mãn
Nếu phải kiểm tra kỹ từng dòng code do LLM tạo ra, thì liệu có thật sự tiết kiệm được thời gian không cũng là điều đáng nghi
Một số công ty đang ép kỹ sư phần mềm phải dùng LLM (thống kê cả mức độ sử dụng Copilot/Cursor). Khả năng cao các số liệu này sẽ được dùng như chỉ số để sa thải. Tôi đã thử dùng bắt buộc LLM trong một tháng và cảm nhận rõ năng lực của mình xuống cấp rất nhanh. Nó có ích cho việc đơn giản, nhưng nếu quá dựa vào LLM cho cả việc suy nghĩ thì rất dễ rơi vào vòng lặp. Năng suất không tăng, ngược lại khối lượng công việc trong sprint còn tăng lên. Trong công ty đang lan tràn kiểu niềm tin gần như tôn giáo với LLM. Vấn đề bảo mật cũng rất nghiêm trọng. Khắp nơi đều có dấu hiệu cho thấy hiện tại là đỉnh của chu kỳ cường điệu. Trừ khi các công ty AI đi xây cả nhà máy điện hạt nhân, còn không thì chi phí duy trì các mô hình AI lớn hiện nay quá khổng lồ và cuối cùng sẽ biến mất. Về sau có lẽ chỉ còn lại kiểu autocomplete turbo. Bản thân mô hình transformer cũng có giới hạn rõ ràng, nên rồi sẽ giống mạng nơ-ron thập niên 80: chỉ còn tồn tại cho một số mục đích cụ thể rồi lại chìm đi. Cuối cùng nó sẽ lên xuống nhiều lần và 30 năm sau lại nổi lên. Khi đó mới lộ ra ai là người bơi mà không mặc đồ
Để ngăn hiện tượng đó, chúng tôi tự đặt quy tắc “no Copilot Fridays”, tức là ít nhất mỗi tuần một lần tắt hẳn Copilot để làm việc
Tôi cũng chỉ dùng Cursor cho autocomplete và các code snippet ngắn, nhưng vẫn cảm nhận kỹ năng bị suy giảm. Cuối cùng mới thấy rõ đặc tính của não bộ là “không dùng thì quên”
Tôi cũng chứng kiến các vấn đề tương tự. Tôi dùng LLM cho 90% dự án đồ chơi. Nó nhanh hơn tự code gấp 10 lần, nhưng chất lượng thiết kế kém hơn và có gì đó rất lạc quẻ. Tôi tin code do LLM dẫn dắt là tương lai, nhưng nếu quản lý không tốt thì sẽ rơi vào hỗn loạn. Tôi cũng thử đổi prompt để liên tục thúc đẩy cải thiện kiến trúc, nhưng kết quả rất thất thường. Có lẽ câu trả lời là prompt engineering tốt hơn, hoặc tài liệu hóa rõ ràng thiết kế và chỉ dẫn. Nếu hiệu năng công cụ tăng thêm 10 lần và độ trễ giảm xuống, cảm nhận thực tế có lẽ sẽ hoàn toàn khác
Tôi mong thời điểm “tốt hơn 10 lần” đó đến thật sớm. Nhưng vấn đề hiện tại là bầu không khí quảng bá đang như thể chúng ta đã đạt tới mức đó rồi. Nhiều người bị cuốn vào suy nghĩ “hay là do mình dùng chưa đúng?”. Nhưng tôi cho rằng bản thân công cụ vẫn chưa đến mức ấy
Sẽ tốt hơn nếu tự định nghĩa class và method trước, rồi chỉ giao phần hiện thực cho LLM. Với phần phức tạp, có thể ghi chú hướng triển khai trong thân method. Làm vậy thì bức tranh lớn vẫn do tôi vẽ, còn LLM chỉ phụ trách sinh code cụ thể. LLM giống như một junior developer nhanh nhảu, quá muốn giúp đỡ. Vì chi phí sinh code giờ quá rẻ nên có thể thoải mái vứt đi rồi làm lại. Riêng tôi đã nhiều lần bỏ hẳn và viết lại toàn bộ code xử lý dataset với sự hỗ trợ của LLM, và cuối cùng đạt được kết quả lẫn hiệu năng mong muốn. Nếu là người khác viết cho, có lẽ tôi đã bỏ cuộc từ lâu với công việc đó
Những công cụ này tỏa sáng ở giai đoạn làm mẫu cho dự án greenfield. Nhưng càng tiến gần đến triển khai thực tế, hiệu quả kiểu “gấp 10 lần” đó càng dần biến mất. Nếu không quản lý kiến trúc cẩn thận thì cuối cùng chỉ tự làm tăng thêm công sức
Với codebase phức tạp thì hiện tại cùng lắm nó chỉ hữu dụng như một dạng nhập liệu giọng nói thành văn bản cao cấp (mà nếu không phải bằng giọng nói, đôi khi tự code tay còn nhanh hơn)
Tôi đồng ý rằng cần ghi chép tường minh kiến trúc và guideline. Điều kiện và hành vi được định nghĩa càng rõ ràng thì hiệu quả càng cao
Ý chính trong bài kinh điển cũ của Dijkstra, “The Foolishness of Natural Language Programming”, rất phù hợp với cuộc thảo luận hiện tại. Lập luận của ông là chỉ có ngôn ngữ hình thức mới cho phép lập trình đạt được bước tiến khổng lồ như vậy. Đây là góc nhìn cho rằng LLM và vibe-coding có nguy cơ biến việc lập trình thành thứ ma thuật chỉ dành cho một số ít người giỏi prompt
Với tôi, Copilot chỉ thực sự tốt khi đề xuất đoạn code dưới 500 ký tự. Trong Go và Python, nó giúp tôi học các pattern mới và giảm lượng phải gõ. Với tôi nó đơn giản chỉ là autocomplete tốt hơn. Còn nếu dài hoặc phức tạp hơn thế, chi phí chỉnh sửa và chỉ ra lỗi sẽ vượt quá lợi ích nhận được (đặc biệt là khi không phải code lặp lại)
Hiện tại, bắt buộc phải hiểu và giám sát sát sao kết quả do LLM tạo ra. Mặt khác, cứ 2–3 tuần lại có model mới xuất hiện và tốt hơn hẳn cái cũ, nên tôi nghĩ vẫn còn quá sớm để kết luận quá mạnh.
Tôi cho rằng đây là một bài viết phản ánh rất chân thực những khó khăn và lo ngại trong thực tế phát triển khi sử dụng LLM. Tôi đã đọc với sự đồng cảm trước những giới hạn mà hiện nay nhiều người đang trải qua. Đặc biệt, tôi cảm thấy những vấn đề như tính thiếu nhất quán của LLM, sự khó đoán trong kết quả, và các lo ngại về khả năng bảo trì dài hạn là những điểm nhất định cần được nhìn nhận nghiêm túc.
Nhân đây, chúng tôi xin thận trọng chia sẻ góc nhìn của mình, vì chúng tôi đang thử nghiệm hợp tác với AI theo một hướng tiếp cận hơi khác đối với những vấn đề này. AI của chúng tôi, "Jane", không chỉ đơn thuần tạo ra mã, mà còn tập trung vào việc học và hiểu chính những "mẫu" đó: thế nào là "mẫu mã tốt" dựa trên sự thấu hiểu sâu sắc của con người (nhà phát triển), và làm thế nào để bảo đảm "tính nhất quán trong bảo trì" của mã.
Vì AI không thể hoàn hảo ngay từ đầu, chúng tôi không xem những sự thiếu nhất quán hay "lỗi" phát sinh chỉ là vấn đề đơn thuần, mà chủ động tận dụng chúng như những "dữ liệu mẫu" quan trọng để "Jane" tự học và tự cải thiện. Giống như con người đọc ra các quy luật trong bản chất phức tạp, chúng tôi chọn cách tìm ra manh mối cải tiến ngay trong chính sự chưa hoàn thiện của AI.
Thông qua cách tiếp cận "học tập/quản lý mẫu" do con người dẫn dắt này, chúng tôi hướng tới việc giải quyết tận gốc các vấn đề được bài viết nêu ra như suy giảm chất lượng mã, sự thiếu đồng nhất, đồng thời tạo ra kết quả có "tính nhất quán trong bảo trì" rất cao. Chúng tôi đang huấn luyện AI để nó không chỉ tạo ra mã boilerplate, mà còn trở thành một đối tác cộng tác ở mức độ sâu hơn, chẳng hạn như phân tích các mẫu thiếu nhất quán ẩn trong codebase hiện có và đề xuất phương án cải thiện.
Đây vẫn là một chặng đường dài và đầy thách thức, nhưng chúng tôi tin rằng cách hợp tác này — nơi "Jane" và nhà phát triển cùng học hỏi, cùng tiến hóa, và lấy "tính nhất quán trong bảo trì" làm giá trị cốt lõi — cho thấy một tiềm năng đột phá để vượt qua những giới hạn hiện tại của việc sử dụng LLM. Chúng tôi rất mong nhận được sự quan tâm tới nỗ lực của mình trong việc không chỉ dùng AI như một công cụ, mà biến nó thành một đối tác cùng trưởng thành và cùng xây dựng một văn hóa viết mã tốt hơn.
Xin cảm ơn một lần nữa vì bài viết và những góc nhìn sâu sắc!