Nguyen Le PhongNguyen Le Phong

Cognitive debt trong AI-assisted development: khi code lớn nhanh hơn mức team hiểu

AI coding tools có thể làm team sinh code nhanh hơn tốc độ team hiểu, review, debug và vận hành an toàn phần code đó. Bài viết giải thích cognitive debt, khác gì technical debt và intent debt, vì sao agentic coding làm khoản nợ này rõ hơn, và các cách giảm rủi ro: giới hạn batch size, bắt PR nói rõ why/invariant/rollback, giữ checkpoint con người, xem prototype AI là bản nháp, và dùng AI để trả nợ hiểu biết thay vì chỉ tạo thêm artifact.

Có lẽ bạn đã từng thấy kiểu pull request này. Một chiều cuối ngày, nó xuất hiện trong hàng chờ review với một dòng ghi chú rất nhẹ: AI hỗ trợ phần lớn, test đã xanh. Diff khá lớn. Tên biến nhìn ổn. Code compile. Unit test pass. Staging chạy được. Không có gì hỏng rõ ràng.

Nhưng khi đọc, trong bụng vẫn có một cảm giác căng nhẹ. Bạn chưa giải thích được edge case của authorization. Bạn không chắc vì sao cache TTL là năm phút. Fallback path nghe hợp lý, nhưng không ai nhớ user bị revoke quyền thì có được truy cập trong vài phút nữa không. Code có thể đúng. Vấn đề là team chưa hiểu nó đủ sâu để tự tin vận hành.

Đó là hình dạng rất đời thường của cognitive debt trong AI-assisted development. Mình có thể dịch là “nợ nhận thức”, nhưng trong công việc hằng ngày, cách gọi thực tế hơn là nợ hiểu biết hệ thống: khoảng cách giữa phần mềm đang tồn tại và mức độ team thật sự hiểu nó để sửa, mở rộng, debug và vận hành an toàn.

Cognitive debt là gì

Technical debt thì engineer nghe nhiều rồi. Team vay tương lai khi chấp nhận duplicate logic, tight coupling, test mỏng, thiết kế vội, hoặc một abstraction biết chắc sau này phải dọn. Khoản nợ này sống chủ yếu trong code và architecture.

Cognitive debt sống trong con người. Nó xuất hiện khi team không còn giữ được một mental model đáng tin về hệ thống. Code có thể typed tốt, format đẹp, test xanh, PR merged, nhưng team không giải thích được vì sao flow đó tồn tại, invariant nào đang bảo vệ nó, trade-off nào đã được chọn, hoặc sửa module này thì module kia có thể vỡ ở đâu.

Margaret-Anne Storey gần đây mô tả vấn đề này trong một triple debt model: technical debt ở code, cognitive debt ở shared understanding của team, và intent debt ở phần rationale được externalize để cả người lẫn AI agent có thể dùng lại về sau. Phân biệt này quan trọng. Một codebase có thể nhìn rất sạch nhưng vẫn khó thay đổi nếu lý do thiết kế phía sau nó đã biến mất.

Loại nợNằm ở đâuCâu hỏi bị hỏng
Technical debtCode, design, architectureCode này có dễ thay đổi không?
Cognitive debtMental model của teamTeam có hiểu đủ để thay đổi an toàn không?
Intent debtDecision record, spec, docs, prompt, rationaleTa có biết vì sao nó được thiết kế như vậy không?

Điểm khó chịu là cognitive debt hiếm khi làm CI đỏ. Nó không hiện ra như lỗi TypeScript hay lint warning. Nó thường xuất hiện muộn hơn, khi ai đó nói: đừng động vào chỗ đó, không ai biết nó hoạt động thế nào đâu.

Vì sao AI làm nó nặng hơn

AI thay đổi tỷ lệ giữa tốc độ sinh code và tốc độ hiểu code. Trước đây, khi developer tự viết, quá trình viết thường cũng là quá trình xây mental model. Mình phát hiện constraint trong lúc gõ, gặp edge case trong lúc test, và cảm được hình dạng hệ thống khi tự tay thay đổi nó.

Với AI coding assistant hoặc agent, developer có thể accept một patch lớn, một refactor, một SQL query, một integration layer, hoặc một workflow DevOps trước khi xây được mức hiểu tương ứng. Artifact lớn lên nhanh hơn mental model quanh nó. Team có velocity, nhưng không chắc có comprehension.

Ví dụ, team bảo agent “làm payment retry robust hơn”. Nó thêm exponential backoff, tách shared retry helper, catch thêm vài lỗi từ provider, rồi update vài test. Diff nhìn giống một cải tiến reliability. Nhưng nếu không ai kiểm tra lỗi nào của provider thật sự được retry an toàn, mọi charge đã có idempotency key chưa, và rate limit của đối tác sẽ phản ứng thế nào khi retry dồn dập, team không chỉ sửa code. Team đã đổi một operational contract mà có thể chính mình chưa hiểu.

Vì vậy các số liệu gần đây nên được đọc rất cẩn thận. Báo cáo DORA về generative AI trong software development ghi nhận mức tăng 25% trong AI adoption gắn với giảm 1.5% delivery throughput và giảm 7.2% delivery stability, trong đó batch size lớn hơn được nêu như một cơ chế khả dĩ. Sonar cũng mô tả một verification gap đáng chú ý: 96% developer không hoàn toàn tin code AI-generated đúng về chức năng, nhưng chỉ 48% nói rằng họ luôn kiểm tra trước khi commit.

Những số liệu đó không có nghĩa AI xấu cho software. Chúng chỉ nhắc rằng speed không giống throughput, và generated code không giống understood code. Nếu AI chuyển bottleneck từ viết code sang verify code, thì process phải được thiết kế lại quanh việc kiểm chứng, thay vì giả vờ thói quen review cũ vẫn đủ.

Mặt con người: cognitive offloading

Dưới chuyện code còn có một mẫu hình nhận thức rộng hơn. Nghiên cứu năm 2025 của Michael Gerlich trên Societies, với 666 người tham gia, ghi nhận mối liên hệ mạnh giữa việc dùng AI, cognitive offloading và điểm critical thinking thấp hơn. Cách đọc công bằng không phải là cứ dùng AI thì con người kém đi. Cách đọc hữu ích hơn là: khi ta dùng AI như lối tắt để né phần suy nghĩ khó, cơ suy nghĩ sâu ít được luyện hơn.

Software engineering có phiên bản riêng của mẫu hình đó. Nếu assistant viết implementation, test, migration và cả lời giải thích, còn con người chỉ accept bundle cuối cùng, người đó có thể chưa xây mental model đủ dùng cho incident kế tiếp. Code tồn tại, nhưng hiểu biết đã bị outsource.

Một phân biệt công bằng

AI cũng có thể giảm cognitive debt nếu dùng đúng: tóm tắt dependency, tạo test matrix, draft ADR, liệt kê edge case, hoặc biến code thành diagram để team kiểm chứng. Rủi ro không nằm ở AI tự thân. Rủi ro nằm ở việc chỉ dùng AI để tăng output trong khi shared understanding đứng yên.

Một ví dụ cụ thể: authorization layer

Giả sử team dùng AI agent để sinh một authorization layer:

User -> Role -> Policy -> Resource -> Action

Demo chạy tốt. Middleware sạch. Có cache. Có vài test cơ bản. Nhưng không ai ghi lại những quy tắc vận hành thật:

  • Vì sao admin được bypass một số policy?
  • Vì sao cache TTL là năm phút?
  • User bị revoke quyền thì propagation delay bao lâu là chấp nhận được?
  • Policy nào là business-critical và phải fail closed?
  • Audit log cần chứng minh invariant gì khi có incident?

Sáu tháng sau có incident. Một user đã bị revoke vẫn truy cập được resource trong vài phút. Code không nhất thiết xấu. Failure nằm ở phần hiểu biết đã mất, hoặc chưa từng được tạo ra, quanh code. Team đã nhận một artifact chạy được nhưng không capture intent và invariant làm cho artifact đó an toàn để vận hành.

Dấu hiệu team đang mang cognitive debt

Dấu hiệu ban đầu thường rất bình thường.

  • Code chạy nhưng không ai muốn sửa. Mỗi thay đổi nhỏ cần hỏi ba người, đọc mười file, và chạy quá nhiều regression thủ công.
  • PR review biến thành nghi thức. Reviewer comment naming, style, snapshot test, nhưng không thật sự đánh giá được intent vì patch quá lớn hoặc quá lạ.
  • Onboarding chậm bất thường. Người mới đọc docs thấy một kiểu, đọc code thấy kiểu khác, hỏi team thì mỗi người giải thích một cách.
  • Debug phụ thuộc vào người nhớ chuyện cũ. Hệ thống có vài human router. Khi họ nghỉ, chuyển team, hoặc bận, delivery đứng lại.
  • Team hỏi AI để giải thích code mà không ai kiểm chứng được. Cách này có thể hữu ích, nhưng nguy hiểm nếu lời giải thích không được đối chiếu với test, telemetry, domain rule, hoặc design note.

Điểm chung không phải hệ thống phức tạp. Hệ thống hữu ích thường sẽ phức tạp. Vấn đề là theory of the system không còn sẵn trong đầu những người đang chịu trách nhiệm với nó.

Chậm lại là một engineering control

Rất dễ biến chuyện này thành khẩu hiệu: hãy chậm lại. Nhưng ý mình không phải hoài cổ về code viết tay, cũng không phải nghi ngờ công cụ. Ý chính xác hơn là: hãy chậm lại ở những điểm mà hiểu biết được tạo ra hoặc bị mất đi.

Một số ma sát không phải lãng phí. Viết một design note ngắn là ma sát. Giải thích assumption trong PR là ma sát. Chia một AI-generated change thành batch nhỏ hơn là ma sát. Bắt reviewer nói lại invariant là ma sát. Nhưng chính những điểm ma sát đó là nơi team xây lại mental model để có thể đi nhanh bền hơn sau này.

Một nguyên tắc đơn giản cho team: đừng merge phần code mà không có ai hiểu đủ để vận hành nó. Ít nhất một người thật phải giải thích được thay đổi là gì, vì sao có nó, nó có thể fail thế nào, phát hiện failure ra sao, và rollback bằng cách nào. Người đó không cần tự tay gõ từng dòng. Nhưng họ cần chịu trách nhiệm làm cho hệ thống dễ hiểu trở lại trước khi ship.

PR template cho thời AI

Nơi dễ bắt đầu nhất là pull request. Đừng chỉ hỏi what changed. Hãy bắt PR trả lời phần suy nghĩ giúp người sau kế thừa thay đổi an toàn hơn.

Checklist nhẹ

Với AI-assisted changes quan trọng, thêm các trường này vào PR: Why this change? Key assumptions. New or protected invariants. Failure modes. Rollback path. What AI generated or assisted. What was manually verified.

Khi điền thật sẽ trông thế nào

Với ví dụ authorization ở trên, một PR note có ích có thể viết: Why: quyền đã revoke phải ngừng hoạt động trong vòng 60 giây. Assumptions: policy cache có thể stale tối đa một phút; finance resources phải fail closed. Invariants: mọi access decision đều ghi audit event. Rollback: tắt cache bằng feature flag. Manual verification: revoke một user trên staging, thử truy cập lại resource, rồi kiểm tra audit trail.

Đây không phải bureaucracy cho đẹp. Đây là capture intent. Nó cho con người tương lai và AI agent tương lai một thứ tốt hơn việc khảo cổ code.

Sáu thực hành để giảm cognitive debt

  1. Giới hạn batch size của AI-generated changes. Nếu patch quá lớn để reviewer reasoning, nó quá lớn để merge an toàn. Hãy bắt agent tạo bước nhỏ hơn.
  2. Xem AI prototype là bản nháp có thể bỏ. Dùng nó để explore, rồi refactor lại theo architecture, naming, constraint và test strategy của hệ thống.
  3. Review để kiểm tra hiểu biết, không chỉ kiểm tra đúng sai. Hỏi reviewer có thể giải thích lại change này không. Nếu chưa, review chưa xong.
  4. Externalize intent. Viết ADR, decision log, domain glossary, sequence diagram, runbook, threat model, migration note khi change đủ quan trọng.
  5. Dùng AI để trả nợ. Yêu cầu AI tạo test matrix, liệt kê edge case, tóm tắt dependency, so sánh implementation với spec, hoặc draft tài liệu để con người kiểm chứng.
  6. Bảo vệ checkpoint con người. Architecture, public API, security boundary, data migration và thao tác không đảo ngược vẫn phải là quyết định do người chịu trách nhiệm.

Khác biệt thực tế là thế này: đừng bảo agent “modernize toàn bộ auth module” rồi merge một diff rất ấn tượng. Hãy bắt nó thêm characterization tests quanh behavior hiện tại trước. Sau đó mới extract policy lookup. Sau đó thêm cache đằng sau feature flag. Sau đó document revoke semantics. Mỗi bước chỉ để reviewer phải giải thích một ý, thay vì giả vờ hiểu năm thay đổi đan vào nhau cùng lúc.

Vai trò của leader: cho phép team chậm lại đúng lúc

Những team rủi ro nhất không nhất thiết là team dùng AI dở. Đôi khi đó là team dùng AI rất hào hứng trong khi leadership chỉ âm thầm thưởng cho output nhìn thấy được. Nếu con số duy nhất được khen là code sinh ra nhanh hơn bao nhiêu, mọi người sẽ tối ưu cho code volume và giấu chi phí hiểu biết.

Leader cần nói rõ một quyền khác: chúng ta không cố làm tất cả những gì AI có thể làm. Chúng ta cố làm những việc quan trọng với đủ hiểu biết để sở hữu kết quả. Điều đó nghĩa là phải có chỗ cho deep work, design review, knowledge sharing, và những cuộc trò chuyện thật về nơi AI đang giúp, cũng như nơi nó đang tạo áp lực.

Một team có thể đi nhanh với AI. Nhưng team đó nên đi ở tốc độ của verified understanding, không phải tốc độ của generated text.

Key takeaways

  • Cognitive debt là khoảng cách giữa hệ thống và mức hiểu biết của team về hệ thống đó. Code có thể compile, test có thể pass, nhưng team vẫn không đủ tự tin thay đổi an toàn.
  • Technical debt chủ yếu nằm ở code; cognitive debt nằm ở con người; intent debt nằm ở rationale bị thiếu. Ba loại nợ này tương tác mạnh trong AI-assisted development.
  • AI làm rủi ro rõ hơn vì generation có thể vượt quá comprehension. Patch đến nhanh hơn mental model của team kịp hình thành.
  • Bottleneck chuyển từ writing sang verification. Nếu thói quen review không đổi, AI dễ tạo batch lớn hơn và khó reasoning hơn.
  • Một số ma sát là cần thiết. Design note, PR nhỏ, invariant rõ và rollback path không phải chậm vì thích chậm. Chúng là cách team xây lại shared understanding.
  • Dùng AI để trả nợ, không chỉ tạo artifact. Hãy để nó draft test matrix, dependency map, runbook, ADR, rồi con người kiểm chứng.
  • Đừng merge thứ không ai vận hành được. Ít nhất một người thật cần hiểu change đủ sâu để debug nó lúc 2 giờ sáng.

Tư thế hữu ích nhất với AI coding không phải là sợ hãi, cũng không phải giao hết tay lái. Nó là stewardship: để máy draft, tìm kiếm, so sánh và tăng tốc, nhưng giữ hiểu biết của team đủ gần với hệ thống mà team đang sở hữu. Codebase tương lai sẽ không được bảo trì bởi prompt đã tạo ra nó. Nó sẽ được bảo trì bởi những người phải hiểu thứ đã được xây, vì sao nó được xây, và thay đổi nó thế nào mà không làm vỡ thế giới xung quanh.

Bạn thấy bài viết thế nào?

Câu hỏi thường gặp

Cognitive debt trong software engineering là gì?
Cognitive debt là khoảng cách giữa phần mềm đang tồn tại và mức hiểu biết chung của team về cách sửa, debug, mở rộng và vận hành phần mềm đó một cách an toàn.
Cognitive debt khác gì technical debt?
Technical debt thường nằm ở code và architecture, như duplicate logic, tight coupling hoặc thiếu test. Cognitive debt nằm ở mental model của team: mọi người không còn hiểu hệ thống đủ sâu để thay đổi tự tin.
AI-generated code có luôn tạo cognitive debt không?
Không. AI có thể giảm cognitive debt nếu được dùng để giải thích dependency, draft tài liệu, tạo test matrix và tìm edge case. Rủi ro xuất hiện khi AI làm output tăng nhanh hơn khả năng kiểm chứng và hiểu của team.
Một nguyên tắc đơn giản cho team dùng AI coding tool là gì?
Đừng merge code mà không có người thật hiểu đủ để vận hành. Ít nhất một người phải giải thích được intent, assumption, invariant, failure mode và rollback path.