7 dấu hiệu repository của bạn bắt đầu mất kiểm soát khi dùng AI Coding
AI coding giống như gắn turbo vào quy trình phát triển phần mềm. Mọi thứ nhanh hơn. Feature ra nhanh hơn. Pull request xuất hiện nhiều hơn. Những việc trước đây mất nửa ngày giờ có thể ra bản nháp trong mấy chục phút. Cảm giác đó rất dễ nghiện, nhất là với những team đang bị backlog dí như trống hội.
Nhưng turbo có một mặt trái rất quen thuộc: nếu hệ thống lái, phanh và khung xe không theo kịp, bạn không chỉ đi nhanh hơn. Bạn còn có thể lao nhanh hơn vào đống rắc rối. Với repository cũng vậy. AI coding không tự động làm repo xấu đi, nhưng nó có thể làm mọi điểm yếu trong workflow lộ ra nhanh hơn, nhân lên nhanh hơn và trở nên đắt đỏ hơn.
Vấn đề là nhiều team không nhận ra repo đang mất kiểm soát ngay lúc đầu. Bề ngoài mọi thứ vẫn có vẻ ổn: velocity cao, nhiều ticket đóng, nhiều commit đều đều. Chỉ đến khi review mệt, bug lọt nhiều, onboarding chậm và ai cũng ngại đụng vào code cũ, team mới giật mình hỏi “hình như repo có gì đó hơi lạ”. Thực ra lúc ấy repo không mới lạ nữa, nó đã bắt đầu hỗn loạn một đoạn rồi.
Dưới đây là 7 dấu hiệu rất điển hình cho thấy repository của bạn bắt đầu mất kiểm soát khi dùng AI coding. Nếu bạn thấy một hai dấu hiệu thì chưa chắc đã đáng sợ. Nhưng nếu thấy nhiều dấu hiệu xuất hiện cùng lúc, đó là lúc nên xem lại workflow một cách nghiêm túc.
1. Pull request ngày càng dài
Đây thường là dấu hiệu sớm nhất và dễ thấy nhất. Ban đầu pull request chỉ vài chục dòng, sửa đúng một chỗ và reviewer đọc rất thoải mái. Sau một thời gian dùng AI coding, diff có thể phình lên vài trăm dòng chỉ để thêm một field, một endpoint hoặc một rule validation mới.
Lý do là AI có xu hướng sửa cả những thứ “trông có vẻ nên sửa thêm”: rename một ít biến, dọn một helper, chỉnh lại format của vài test, thay một đoạn mapping vì thấy “đẹp hơn”. Từng thay đổi nhỏ riêng lẻ có thể đều có lý. Nhưng cộng lại, pull request trở thành một đống rất khó review.
Khi pull request dài, reviewer thường gặp ba vấn đề:
- khó nhìn ra thay đổi cốt lõi của business logic
- khó phân biệt phần bắt buộc với phần sửa thêm
- dễ đọc lướt thay vì đọc kỹ
Và khi code review trở nên khó khăn, bug sẽ lọt vào production không phải vì mọi người kém, mà vì bộ não con người có giới hạn tập trung. Production thì lại rất thích tận dụng đúng chỗ đó.
2. Controller bắt đầu chứa quá nhiều logic
Một controller tốt thường chỉ xử lý request, gọi đúng tầng xử lý phía dưới và trả response. Nhưng khi AI liên tục sửa code trong nhiều context khác nhau, business logic có thể bắt đầu rò dần vào controller. Lúc đầu chỉ là một điều kiện nhỏ. Sau đó thêm một đoạn validation đặc thù. Rồi thêm một đoạn mapping. Rồi thêm vài rule xử lý lỗi. Cuối cùng controller trông như một dịch vụ thu nhỏ mang danh controller.
Đây là dấu hiệu kinh điển của architecture drift. Kiến trúc không vỡ ngay, nhưng bắt đầu lệch dần. Và vì lệch dần nên rất dễ bị bỏ qua. Hôm nay ai đó merge vì thấy “chạy được”. Tuần sau AI lại nhìn vào đúng file đó và thấy business logic ở controller là chuyện bình thường. Thế là nó tiếp tục viết theo pattern đã thấy. Repo tự huấn luyện AI sai theo thời gian. Nghe hơi đau, nhưng rất thật.
3. Cùng một logic xuất hiện ở nhiều nơi
AI rất giỏi viết lại một ý tưởng theo nhiều cách khác nhau. Nghe qua thì có vẻ linh hoạt. Nhưng trong codebase production, sự linh hoạt kiểu này thường đẻ ra:
- duplicate code
- logic phân tán
- nhiều biến thể của cùng một quy tắc
Ví dụ một rule kiểm tra quyền truy cập xuất hiện ở service A theo kiểu hàm helper, ở service B theo kiểu if lồng, ở module C theo kiểu middleware riêng. Tất cả đều chạy được. Nhưng đến lúc sửa bug hoặc đổi rule, team phải đi săn khắp repo như chơi trò truy tìm kho báu, chỉ có điều kho báu là bug và không ai muốn tìm.
Duplicate logic không chỉ làm code dài hơn. Nó làm repo mất khả năng tiến hóa mượt mà. Mỗi thay đổi nghiệp vụ từ đó trở đi đều đắt hơn.
4. Naming convention không đồng nhất
Mỗi prompt có thể tạo ra một cách đặt tên khác nhau. Hôm nay AI chọn createUser. Mai lại chọn create_user. Chỗ khác thì dùng addUser. Nếu codebase không có contract mạnh, lint rule rõ hoặc review đủ chặt, repo sẽ dần biến thành nơi nhiều dialect cùng tồn tại.
Người ngoài nhìn vào có thể nghĩ chuyện này nhỏ. Nhưng với hệ thống lớn, naming là một phần rất quan trọng của khả năng đọc và suy luận. Tên không đồng nhất làm tăng ma sát nhận thức. Mỗi lần mở file mới, developer phải tự học lại một tiểu quy ước cục bộ. Càng nhiều ma sát như vậy, tốc độ đọc code càng giảm, sai sót càng tăng.
Nói vui một chút, naming không đồng nhất giống việc cả thành phố mỗi quận tự đặt biển báo theo sở thích. Xe vẫn chạy được, nhưng người lái sẽ mệt rất nhanh.
5. Developer bắt đầu mất niềm tin vào code
Đây là dấu hiệu nguy hiểm nhất vì nó tác động trực tiếp tới tâm lý đội ngũ. Khi developer mở một pull request hoặc đọc một module cũ và tự hỏi:
AI có sửa gì ngoài ý muốn không? Chỗ này thật sự phản ánh business logic hay chỉ là hệ quả của một prompt nào đó?
Lúc đó niềm tin vào codebase đã giảm. Mà niềm tin giảm thì mọi việc đều chậm lại. Người ta đọc kỹ hơn vì sợ. Họ ngại refactor vì sợ. Họ ngại chạm vào chỗ không hiểu vì sợ. Không khí kỹ thuật từ đó bắt đầu chuyển từ chủ động sang phòng thủ.
Một repo tốt không phải repo không có bug. Nó là repo mà team còn tin rằng khi đọc code, họ có thể hiểu và dự đoán được nó. Mất điều đó là mất rất nhiều năng lượng vô hình.
6. Refactor ngày càng khó
Khi code structure không nhất quán, refactor trở nên khó khăn. Một thay đổi tưởng chỉ cần chạm vào một lớp lại kéo theo hàng loạt file liên quan vì logic bị rải rác, abstraction mọc theo lịch sử thay vì theo thiết kế, naming lệch nhau và dependency vòng vo hơn mức cần thiết.
Đến một lúc, team bắt đầu có xu hướng tránh refactor. Họ chọn giải pháp chắp vá thêm một lớp mới, một helper mới, một đường đi mới để đỡ phải động vào phần cũ. Đó chính là kỹ thuật “đẻ thêm nợ để né nợ cũ”. Ngắn hạn có vẻ hợp lý, dài hạn thì hơi… có tính nghệ thuật phá hoại.
Nếu bạn thấy repo của mình ngày càng nhiều câu kiểu “đừng đụng vào file đó”, “chỗ này cũ rồi”, “để sau refactor”, thì xin chia buồn, đây là dấu hiệu rất rõ là repo đang mất độ kiểm soát.
7. Onboarding developer mới mất nhiều thời gian
Khi codebase thiếu cấu trúc rõ ràng, developer mới cần rất nhiều thời gian để hiểu hệ thống. Họ không chỉ học business. Họ còn phải học các pattern cục bộ, các ngoại lệ lịch sử, các naming không thống nhất, những chỗ AI từng “sửa hộ” nhưng không ai còn nhớ vì sao.
Onboarding chậm không chỉ ảnh hưởng người mới. Nó làm chậm cả team vì senior phải giải thích nhiều thứ lẽ ra repo nên tự giải thích được. Một codebase tốt có khả năng hướng dẫn người đọc phần nào qua chính cấu trúc của nó. Một codebase mất kiểm soát thì đòi hỏi rất nhiều truyền miệng nội bộ để tồn tại.
Nếu mỗi lần có người mới vào team là cả hệ thống như mở khóa một lớp bí truyền mới, đó không phải nét đẹp văn hóa. Đó là món nợ tổ chức đội lốt bản sắc.
Vì sao 7 dấu hiệu này thường xuất hiện cùng nhau?
Bởi vì chúng không độc lập. Diff lớn làm review yếu đi. Review yếu đi làm logic lặp dễ lọt. Logic lặp làm refactor khó. Refactor khó làm kiến trúc drift nặng hơn. Kiến trúc drift làm onboarding chậm hơn. Onboarding chậm làm người cũ càng ngại thay đổi. Cả vòng tròn đó nuôi nhau rất tốt, chỉ tiếc là nuôi theo chiều xấu.
AI coding làm vòng lặp này diễn ra nhanh hơn vì nó giảm đáng kể ma sát tạo code ban đầu. Trong khi đó, review, kiến trúc và tiêu chuẩn team thường không tự trưởng thành nhanh cùng tốc độ. Kết quả là tốc độ đầu vào vượt quá khả năng giữ trật tự của hệ thống.
Điều này có nghĩa là không nên dùng AI?
Không. AI vẫn là một công cụ cực kỳ mạnh. Vấn đề không nằm ở việc có dùng AI hay không. Vấn đề nằm ở workflow. Nếu AI được dùng để sửa trực tiếp repository trên phạm vi rộng mà thiếu guardrail, các dấu hiệu trên rất dễ xuất hiện. Nếu AI được dùng ở tầng mô tả, contract, schema, code plan hoặc generator workflow, rủi ro sẽ thấp hơn nhiều.
Nhiều team bắt đầu chuyển sang cách làm bền hơn:
- AI hỗ trợ mô tả hệ thống và viết contract
- compiler sinh code từ contract theo cấu trúc ổn định
- review tập trung vào semantic change thay vì boilerplate
- generated code được tách rõ khỏi custom logic
Cách tiếp cận này không thần kỳ, nhưng nó giúp giữ cấu trúc code ổn định hơn rất nhiều. Và đôi khi trong engineering, “ổn định hơn” chính là lời khen lớn nhất có thể dành cho workflow.
Một checklist nhanh để tự soi repo của bạn
- PR trung bình có lớn dần dù ticket không lớn hơn không?
- Reviewer có thường hỏi “sao chỗ này cũng đổi?” không?
- Cùng một rule có đang được implement ở nhiều nơi không?
- Controller hoặc handler có đang ôm nhiều business logic hơn trước không?
- Người mới có mất quá lâu để hiểu pattern chung không?
- Team có bắt đầu ngại refactor vì sợ side effect không?
- Mọi người có còn tin rằng repo phản ánh kiến trúc một cách rõ ràng không?
Nếu trả lời “có” cho nhiều câu cùng lúc, repo của bạn không chỉ hơi rối. Nó đang gửi tín hiệu cầu cứu khá lịch sự.
Kết luận
Repository mất kiểm soát khi dùng AI coding không phải một tai nạn bất ngờ. Nó thường bộc lộ qua những dấu hiệu rất rõ: pull request phình to, controller ôm quá nhiều logic, duplicate code tăng, naming lệch chuẩn, niềm tin vào code giảm, refactor khó hơn và onboarding chậm hơn. Những dấu hiệu này càng xuất hiện cùng lúc, bạn càng nên xem lại workflow AI coding của team.
Điểm quan trọng nhất là đừng đợi repo cháy mới đi chữa. Khi các dấu hiệu mới ló ra, đó là lúc tốt nhất để chỉnh lại guardrail, review rule, contract workflow và cách AI được phép can thiệp vào codebase. Làm sớm thì hơi phiền một chút. Làm muộn thì thường phải mở thêm vài cuộc họp rất dài. Dân kỹ thuật ai cũng biết cái nào đau hơn.
Điều quan trọng nhất: đừng bình thường hóa sự hỗn loạn
Nhiều repo không sụp vì lỗi lớn, mà sụp vì cả team dần coi những dấu hiệu xấu là bình thường. PR to trở thành bình thường. Logic trùng lặp trở thành bình thường. Reviewer không hiểu hết diff cũng thành bình thường. Một khi cái xấu được bình thường hóa, chi phí sửa nó tăng lên rất nhanh. Bởi vậy, nhận ra sớm bảy dấu hiệu trên đã là một lợi thế lớn.
Nhận ra sớm sự hỗn loạn luôn rẻ hơn rất nhiều so với dọn dẹp sau này.