Vì sao AI Coding bắt đầu “toang” khi repo bước vào production
AI coding đang tạo ra một cảm giác rất dễ nghiện: gõ prompt một lúc, quay đi lấy cốc trà đá, quay lại thấy code, test, thậm chí cả phần comment đã nằm sẵn trong pull request. Với team nhỏ hoặc giai đoạn thử ý tưởng, đây đúng là cảm giác “đời nở hoa”. Nhưng khi repository đã bước vào production, mọi thứ không còn được đánh giá bằng tốc độ sinh mã nữa, mà bằng độ ổn định, độ dễ review, khả năng bảo trì và mức độ tôn trọng kiến trúc hệ thống.
Nói ngắn gọn: AI coding rất giỏi giúp bạn tăng tốc, nhưng production lại đòi hỏi khả năng giữ làn. Xe chạy nhanh mà không giữ được làn thì sớm muộn cũng leo vỉa hè. Cái khó ở đây là nhiều team chỉ nhận ra vấn đề sau khi đã dùng AI để sửa code trên một codebase đủ lớn, đủ nhiều người cùng làm và đủ nhiều ràng buộc nghiệp vụ. Lúc đó git diff đã phình ra như bánh mì nhúng nước, reviewer bắt đầu cau mày, còn kiến trúc thì từ “layer rõ ràng” biến thành “chỗ nào tiện thì nhét vào”.
Bài viết này không nhằm chê AI coding. Thật lòng mà nói, với góc nhìn của một CTO, tôi thấy AI coding là một công cụ cực kỳ mạnh. Vấn đề là nhiều đội đang dùng nó như một cây búa thần, trong khi production là một cái đồng hồ cơ. Đập vào đâu cũng được thì nhanh thật, nhưng sau đó muốn ráp lại cho chạy đúng giờ thì hơi vã mồ hôi.
AI coding hoạt động tốt nhất khi codebase còn nhỏ và mục tiêu còn linh hoạt
Khi repository còn nhỏ, ít phụ thuộc chéo và business rule chưa quá dày đặc, AI coding gần như là một trợ lý chăm chỉ, khỏe mạnh, không xin nghỉ phép và không than deadline. Bạn cần dựng một API mẫu, một trang landing page, một script import dữ liệu, một bài test smoke test cơ bản, AI thường làm rất ổn.
- Viết hàm nhanh khi phạm vi bài toán hẹp
- Tạo CRUD hoặc endpoint mẫu rất lẹ
- Sinh unit test cơ bản để lấp chỗ trống
- Refactor cục bộ khi kiến trúc chưa nhiều ràng buộc
Ở giai đoạn prototype, chúng ta ưu tiên trả lời các câu hỏi kiểu: “Ý tưởng này có chạy được không?”, “Luồng này có hợp với người dùng không?”, “Demo cho khách xem được chưa?”. Những câu hỏi này thiên về tốc độ học hỏi hơn là độ tinh khiết của kiến trúc. Cho nên AI coding rất hợp. Nó giúp team bắn thử nhiều phương án nhanh hơn, bỏ cái sai sớm hơn, và có cái để thảo luận thay vì chỉ nói bằng slide.
Thực tế mà nói, lúc repo còn nhỏ, thi thoảng AI viết hơi khác style một chút cũng không phải đại họa. Một hàm hơi dài hơn mong muốn, một file đặt tên chưa thật đẹp, một chỗ validate lặp lại nhẹ, tất cả vẫn còn trong ngưỡng sửa được bằng một cốc cà phê và một buổi chiều tỉnh táo.
Cho nên nếu bạn đang dùng AI coding để tăng tốc giai đoạn khám phá, xin chúc mừng: bạn đang dùng nó đúng sân. Vấn đề chỉ xuất hiện khi team vô thức mang cùng cách làm đó sang production, nơi mỗi thay đổi nhỏ đều có thể ảnh hưởng đến hiệu năng, bảo mật, logging, backward compatibility, migration dữ liệu, monitoring, rollback plan và tâm trạng của người trực on-call lúc 2 giờ sáng.
Khi repo vào production, định nghĩa của “code tốt” thay đổi hoàn toàn
Nhiều bạn nhìn AI coding và nghĩ: “Code chạy được, test pass, vậy là ổn chứ?”. Trong production, câu trả lời là: chưa chắc. Code chạy được mới chỉ là điều kiện cần. Điều kiện đủ còn bao gồm chuyện code đó có dễ hiểu với người khác không, có phá kiến trúc hiện tại không, có tạo thêm rủi ro vận hành không, và có khiến lần sửa sau trở nên khó hơn không.
Prototype chấp nhận được kiểu “miễn chạy đã”. Production thì không. Production cần:
- Tính ổn định qua nhiều lần thay đổi
- Khả năng lặp lại kết quả một cách nhất quán
- Kiểm soát chặt phạm vi sửa đổi
- Tôn trọng ranh giới kiến trúc và quy ước của team
- Dễ review, dễ rollback, dễ audit
Đây là chỗ AI coding hay bị hiểu lầm. Nó không thật sự “hiểu hệ thống” như cách một kỹ sư già dặn hiểu. Nó không sống cùng repo đủ lâu để cảm nhận chỗ nào là quyết định chủ đích, chỗ nào là nợ kỹ thuật tạm chấp nhận, chỗ nào là vùng cấm vì dính compliance, và chỗ nào chỉ cần chạm nhẹ là dashboard lỗi đỏ rực như cây thông Noel.
AI rất giỏi tạo ra lời giải hợp lý cục bộ. Production lại cần lời giải hợp lý toàn cục.
Sự khác biệt này chính là nguồn gốc của hiện tượng “lúc demo thì mê, lúc lên production thì mệt”. Không phải AI coding đột nhiên dở đi. Chỉ là bài toán đã đổi luật chơi.
Vấn đề số 1: Git diff phình to và làm mờ mục tiêu thật của thay đổi
Dấu hiệu đầu tiên mà nhiều team cảm nhận được là git diff lớn bất thường. Bạn định thêm một endpoint, AI lại tiện tay chỉnh controller, service, DTO, validation, test, config, một ít helper, và đôi khi bonus thêm vài chỗ rename “cho đồng bộ”. Nghe qua có vẻ hợp lý. Nhưng reviewer nhìn vào diff dài vài trăm dòng sẽ có cảm giác rất thật: “Ủa, rốt cuộc ticket này đang sửa cái gì?”
Git diff lớn không chỉ là vấn đề về mặt thẩm mỹ. Nó làm hỏng khả năng kiểm soát thay đổi. Một pull request tốt trong production thường có mục tiêu rõ, phạm vi rõ và lý do rõ. Khi diff quá rộng, ba thứ đó bắt đầu nhòe đi. Reviewer khó tách đâu là phần cần thiết cho business, đâu là phần AI tự suy diễn để “cải thiện” code theo logic riêng của nó.
Vì sao AI coding hay tạo git diff lớn?
Lý do nằm ở cách mô hình suy luận theo ngữ cảnh. Khi nhận prompt, AI có xu hướng tìm lời giải sao cho toàn bộ đoạn code xung quanh trông nhất quán hơn theo mô hình mà nó suy diễn được. Nghĩa là nếu nó thấy một lớp service có thể “đẹp hơn” khi đổi tên hàm, nó sẽ đổi. Nếu nó thấy cấu trúc DTO có thể gọn hơn, nó đổi luôn. Nếu test hiện tại trông chưa đồng đều, nó sửa tiếp. Với AI, đó là tối ưu hóa tự nhiên. Với production, đó là mở rộng phạm vi thay đổi ngoài kế hoạch.
Vấn đề là mỗi dòng thay đổi thêm đều làm tăng chi phí review và tăng xác suất lọt bug. Không phải vì code mới chắc chắn sai, mà vì con người có giới hạn tập trung. Reviewer nào cũng có ngày đẹp trời và ngày ngáp liên tục. Một diff 30 dòng và một diff 600 dòng không tạo ra cùng mức tin cậy, kể cả khi người review là senior rất cứng.
Git diff lớn kéo theo những hệ quả gì?
- Code review chậm hơn vì phải đọc nhiều ngữ cảnh hơn
- Dễ bỏ sót bug ở phần “AI tiện tay sửa thêm”
- Khó rollback vì commit chứa quá nhiều thay đổi trộn lẫn
- Khó truy nguyên nguyên nhân nếu production phát sinh lỗi
- Team mất dần kỷ luật giữ pull request nhỏ và rõ ràng
Trong thực chiến, tôi từng thấy nhiều ticket cực nhỏ nhưng pull request lại mang dáng dấp của một cuộc cải tổ mini. Những PR kiểu này làm team kiệt sức rất nhanh. Người viết thì nghĩ AI giúp tiết kiệm thời gian, người review thì âm thầm mất thêm thời gian gấp ba. Cả hệ thống tổ chức cuối cùng trả giá bằng sự chậm chạp và thiếu chắc chắn.
Vấn đề số 2: Kiến trúc hệ thống bị lệch mà không ai nhận ra ngay
Nếu git diff lớn là triệu chứng dễ thấy, thì architecture drift là căn bệnh âm thầm hơn. Nó không nổ ngay trong ngày hôm nay. Nó tích tụ. Mỗi lần AI coding chen thêm một chút logic vào controller, lặp lại một chút validation ở service khác, bypass qua một abstraction cho “nhanh”, hệ thống mất đi một ít độ trong trẻo. Mỗi lần chỉ một ít thôi, nên không ai hoảng. Sáu mươi lần như vậy thì repo bắt đầu giống một căn phòng nhiều người ở chung: không bẩn đến mức báo công an, nhưng chẳng ai còn biết cái kéo nằm ở đâu.
AI không có cảm nhận sâu về chủ đích kiến trúc. Nó không tự biết rằng team của bạn cố ý giữ controller mỏng vì muốn business rule tập trung trong use case. Nó cũng không tự biết repository pattern hiện tại tồn tại vì hệ thống chuẩn bị thay database trong quý tới. Nó chỉ nhìn vào bề mặt code có sẵn và sinh tiếp thứ trông có vẻ hợp lý.
Những dạng lệch kiến trúc thường gặp khi dùng AI coding
- Business logic chảy từ service sang controller cho tiện thao tác dữ liệu request
- Validation lặp ở nhiều lớp khác nhau vì AI cố “an toàn” ở từng điểm
- Helper hoặc utility trở thành bãi đáp cho mọi thứ không biết nhét đâu
- Domain rule bị pha loãng bởi các đoạn xử lý trực tiếp ở tầng giao tiếp
- Convention đặt tên và phân chia module dần dần mất nhất quán
Điều nguy hiểm là các thay đổi này thường không làm ứng dụng chết ngay. App vẫn chạy. Test cơ bản vẫn pass. Khách hàng vẫn bấm được nút. Cho nên team rất dễ tự trấn an rằng mọi chuyện ổn. Nhưng sau vài tháng, mỗi lần chạm vào một feature cũ là thấy “sao chỗ này lại xử lý kiểu khác chỗ kia?”. Đó là lúc chi phí bảo trì bắt đầu lộ diện.
Với góc nhìn CTO, tôi rất ngại loại chi phí này vì nó không hiện lên dashboard tài chính ngay lập tức. Nó xuất hiện dưới dạng team mệt hơn, estimation ngày càng khó đoán, onboarding lâu hơn, bug vặt nhiều hơn và vận tốc phát triển giảm mà không ai chỉ được một thủ phạm cụ thể. Thủ phạm thật ra là sự lệch chuẩn tích tụ từng chút một.
Vấn đề số 3: Code generation không ổn định, trong khi production rất ghét sự bất định
Một đặc điểm ít được nói đủ nhiều là AI coding không phải máy photocopy. Bạn có thể dùng gần như cùng một prompt, trên gần như cùng một bối cảnh, nhưng kết quả vẫn khác nhau về cấu trúc, cách đặt tên, cách chia hàm, thậm chí cách tổ chức kiểm tra lỗi. Không nhất thiết đoạn nào cũng sai. Nhưng sự khác nhau đó khiến hệ thống khó đoán hơn theo thời gian.
Production lại sống nhờ sự nhất quán. Bạn muốn lần sửa thứ hai có thể dự đoán được ảnh hưởng từ lần sửa thứ nhất. Bạn muốn khi một kỹ sư khác mở lại module cũ, họ nhận ra pattern quen thuộc chứ không phải mỗi file là một “vũ trụ song song”. Sự bất định trong code generation khiến team khó xây dựng một cảm giác trật tự bền vững.
Sự không ổn định biểu hiện như thế nào?
- Cùng một bài toán nhưng mỗi lần AI chọn một pattern hơi khác
- Đặt tên hàm, tên biến, tên lớp thiếu tính hệ thống
- Mức độ trừu tượng thay đổi thất thường giữa các module
- Phong cách xử lý lỗi hoặc logging không đồng đều
- Test được sinh ra không thống nhất về cách tổ chức và mức bao phủ
Con người cũng có lúc viết code không nhất quán, điều đó đúng. Nhưng con người làm việc trong một nền văn hóa kỹ thuật, có code review, có lịch sử trao đổi, có chủ đích nghề nghiệp, có ký ức về những lần đau thương cũ. AI coding thì không tích lũy trải nghiệm kiểu đó theo cùng nghĩa. Nó tạo ra câu trả lời từ xác suất và ngữ cảnh hiện có, chứ không từ trách nhiệm sống chung dài hạn với codebase.
Nói vui một chút, AI coding giống một đồng nghiệp rất năng suất nhưng mỗi sáng đi làm lại thay đổi cá tính. Hôm nay theo phong cách tối giản, mai thích chia class, mốt chuyển sang thích functional. Làm chung vài hôm đầu thì vui, làm chung sáu tháng thì team lead sẽ bắt đầu tìm thuốc đau đầu.
Vấn đề số 4: Code review trở thành nơi team “trả nợ” cho sự nhiệt tình của AI
Khi git diff lớn, kiến trúc bị nới lỏng và pattern sinh mã thiếu ổn định, code review nghiễm nhiên trở thành tuyến phòng thủ cuối cùng. Đây là lúc nhiều team bắt đầu thấy nghịch lý: AI coding giúp người viết code nhanh hơn, nhưng lại làm cả team chậm hơn ở bước review. Năng suất cá nhân tăng, năng suất hệ thống giảm. Nghe buồn cười, nhưng rất thật.
Reviewer lúc này không còn chỉ review business logic. Họ phải làm thêm ba việc:
- Tách thay đổi cần thiết ra khỏi thay đổi phụ
- Kiểm tra xem có dấu hiệu lệch kiến trúc hay không
- Đánh giá rủi ro vận hành của những chỉnh sửa nhìn qua tưởng vô hại
Nếu reviewer làm kỹ, review sẽ chậm. Nếu reviewer làm nhanh, bug và drift sẽ lọt. Cả hai đều không vui. Đó là lý do nhiều đội dùng AI coding một thời gian rồi bỗng cảm thấy “sao release vẫn chậm mà mọi người lại mệt hơn?”. Câu trả lời thường nằm ở chỗ chi phí đã được chuyển từ lúc viết sang lúc review và bảo trì.
Một pull request do AI hỗ trợ thường làm reviewer lo gì?
- Logic nào thực sự được yêu cầu bởi ticket?
- Đoạn nào chỉ là AI tự tối ưu cho vui?
- Thay đổi này có phá convention đã thống nhất không?
- Có side-effect ở module lân cận mà người viết chưa để ý không?
- Nếu có lỗi production, rollback phần nào là đủ?
Code review vốn là hoạt động đòi hỏi nhiều năng lượng nhận thức. Khi phải review một PR rộng, không đồng nhất và hơi “tăng động”, chất lượng review rất dễ giảm dần theo thời lượng. Người review không ngu đi; họ chỉ mệt đi. Và production thì thường tận dụng rất tốt những lúc con người mệt.
Prototype và production khác nhau ở đâu mà AI coding từ “thần trợ lý” thành “ca khó”?
Khác biệt lớn nhất là mục tiêu tối ưu. Prototype tối ưu cho tốc độ thử nghiệm. Production tối ưu cho độ tin cậy và khả năng vận hành lâu dài. Khi tối ưu khác nhau, cùng một công cụ sẽ cho cảm nhận rất khác nhau.
| Khía cạnh | Prototype | Production |
|---|---|---|
| Mục tiêu chính | Thử nhanh, học nhanh | Ổn định, kiểm soát, mở rộng |
| Chấp nhận sai số | Cao hơn | Thấp hơn rất nhiều |
| Phạm vi thay đổi | Có thể linh hoạt | Cần nhỏ, rõ, có chủ đích |
| Ưu tiên kiến trúc | Đủ dùng | Nhất quán và bền vững |
| Chi phí bug | Tương đối thấp | Có thể rất đắt |
Khi đặt AI coding vào prototype, bạn tận dụng điểm mạnh của nó là tốc độ. Khi đặt AI coding vào production mà không có cơ chế kiểm soát, bạn lại phóng đại điểm yếu của nó là xu hướng mở rộng phạm vi, thiếu chủ đích kiến trúc dài hạn và khó giữ tính nhất quán tuyệt đối. Thành ra công cụ không đổi, nhưng sân chơi đổi nên kết quả đổi.
Vậy có nên dùng AI coding cho production không?
Có, nhưng phải dùng như một công cụ có lan can, chứ không phải một tay lái tự động thả rông. Câu hỏi đúng không phải “AI coding có nên viết code production không?”, mà là “team có đủ cơ chế để bó phạm vi, giữ kiến trúc và kiểm soát chất lượng khi AI tham gia không?”. Nếu có, AI coding vẫn rất hữu ích. Nếu không, tốc độ ban đầu sẽ biến thành nợ kỹ thuật với lãi suất khá chát.
Một số nguyên tắc thực tế mà team production nên nghĩ tới:
- Yêu cầu AI chỉ sửa trong phạm vi file hoặc module xác định rõ
- Tách thay đổi chức năng và thay đổi refactor thành các PR riêng
- Giữ rule review nghiêm hơn với PR có AI hỗ trợ mạnh
- Có convention kiến trúc và coding guideline đủ cụ thể để AI bám theo
- Xem AI là người viết nháp nhanh, không phải người quyết kiến trúc cuối cùng
Đây là điểm nhiều platform như MidiCoder có thể tạo khác biệt: không chỉ giúp AI sinh code nhanh, mà còn giúp quá trình sinh code bám đúng contract, đúng phạm vi, đúng cấu trúc mà team định nghĩa. Nói cách khác, bài toán lớn không còn là “làm sao viết ra nhiều code hơn”, mà là “làm sao để code được sinh ra ít phá hệ thống hơn”. Nghe bớt hào nhoáng, nhưng đó mới là tinh thần production thật sự.
Dấu hiệu cho thấy team đang dùng AI coding quá vô tư trong production
Nếu bạn đang tự hỏi đội mình đã đến mức đáng lo chưa, đây là vài dấu hiệu tương đối điển hình:
- PR thường xuyên dài hàng trăm dòng cho các ticket rất nhỏ
- Reviewer phải hỏi lại nhiều lần “phần này sửa để làm gì?”
- Cùng một loại logic nhưng mỗi module viết theo một kiểu
- Controller, service, helper ngày càng phình mà không ai nhận trách nhiệm
- Bug không quá lớn nhưng lặp lại đều vì thay đổi lan sang vùng không cần thiết
- Team thấy viết rất nhanh nhưng velocity release không tăng tương ứng
Nếu có từ ba dấu hiệu trở lên, khả năng cao không phải team thiếu người giỏi, mà là công cụ đang được dùng sai chế độ. Giống bật điều hòa 16 độ rồi lấy chăn trùm kín, vẫn mát đấy, nhưng hóa đơn cuối tháng sẽ dạy ta một bài học rất Việt Nam.
Kết luận
AI coding không “toang” khi repo vào production vì nó dở. Nó “toang” vì production là môi trường đòi hỏi kiểm soát cao hơn nhiều so với những gì prompt thông thường có thể đảm bảo. Khi codebase còn nhỏ, AI giống một trợ lý tăng tốc rất đáng yêu. Khi hệ thống đã lớn, nhiều module, nhiều người cùng làm và nhiều ràng buộc vận hành, AI coding cần được đặt trong một khung kiểm soát chặt hơn: phạm vi sửa rõ ràng, kiến trúc rõ ràng, review rõ ràng.
Nếu không, bạn sẽ gặp đúng bộ ba kinh điển: git diff ngày càng lớn, kiến trúc ngày càng lệch, code review ngày càng mệt. Và đó là lúc lợi thế tốc độ ban đầu bị bào mòn bởi chi phí bảo trì về sau. Dân kỹ thuật có một chân lý khá buồn cười: cái gì giúp nhanh quá mà không có kỷ luật đi kèm, sớm muộn cũng quay lại xin thêm thời gian.
Câu hỏi đáng giá nhất không phải “AI có viết code được không?”, mà là “AI viết code kiểu gì để production vẫn yên ổn và team không bạc tóc sớm?”.
Đó cũng là nơi những cách tiếp cận như contract coding, code generation có kiểm soát và workflow dành riêng cho production bắt đầu trở nên quan trọng. Và vâng, đây chính là câu chuyện đáng để đi tiếp ở bài sau.