Nợ kỹ thuật, nợ nhận thức, nợ ý định
(martinfowler.com)- Trong môi trường LLM tạo mã hàng loạt, không chỉ chất lượng của bản thân mã bị suy yếu mà cả hiểu biết chung của nhóm và việc ghi lại mục tiêu hệ thống cũng dễ mai một, khiến nhu cầu xử lý theo ba lớp nợ kỹ thuật · nợ nhận thức · nợ ý định ngày càng lớn
- Technical debt làm hạn chế khả năng thay đổi trong tương lai, Cognitive debt làm suy yếu khả năng suy luận của nhóm khi thay đổi hệ thống, còn Intent debt làm mờ nhạt hồ sơ về mục tiêu và ràng buộc, từ đó cản trở sự tiến hóa liên tục của cả con người lẫn AI agent
- Lý thuyết Tri-System đặt AI là System 3 phân biệt hiện tượng cognitive surrender — tin tưởng vô điều kiện vào suy luận nhân tạo từ bên ngoài và bỏ qua quá trình suy xét — với cognitive offloading, tức việc ủy nhiệm nhận thức một cách có chiến lược
- Khi chi phí viết mã giảm xuống, thứ trở nên đắt đỏ là verification; tiêu chuẩn của tính đúng đắn và thành công thay đổi theo từng bối cảnh như ETA giao thông, điều phối tài xế hay vận hành hàng trăm microservice, nên phán đoán của con người và thiết kế hệ thống kiểm chứng càng trở nên quan trọng
- Trục trung tâm của kỹ thuật phần mềm dịch chuyển từ khối lượng triển khai sang verification, và về sau con người vẫn sẽ tiếp tục giữ vai trò nắm bắt ý nghĩa của hệ thống qua việc tạo ra các trừu tượng hữu ích, đặt tên, thiết kế acceptance criteria và test harness
Ba loại nợ và sức khỏe hệ thống
- Trong môi trường LLM tạo ra lượng lớn mã, các nhóm rất dễ mất đi hiểu biết về việc hệ thống thực sự đang làm gì, và ngày càng có nhiều góc nhìn xem đây là Cognitive Debt
- Ba lớp sức khỏe hệ thống chia nợ thành các chiều mã, con người và artifact
- Technical debt tồn tại trong mã, tích lũy khi các quyết định triển khai làm tổn hại khả năng thay đổi trong tương lai và giới hạn cách hệ thống có thể tiến hóa
- Cognitive debt tồn tại ở con người, tích lũy khi hiểu biết chung về hệ thống suy giảm nhanh hơn tốc độ được bổ sung, từ đó hạn chế khả năng của nhóm trong việc suy luận về thay đổi
- Intent debt tồn tại trong artifact, tích lũy khi các mục tiêu và ràng buộc lẽ ra phải dẫn dắt hệ thống không được ghi lại hoặc duy trì đúng cách, từ đó hạn chế việc phản ánh liên tục mục tiêu ban đầu, cũng như khả năng để con người và AI agent tiếp tục phát triển hệ thống một cách hiệu quả
- Góc nhìn này còn bao gồm cả các phần chẩn đoán và giảm thiểu cho từng loại nợ, đồng thời bàn về cách ba loại nợ tương tác với nhau
- Các nhóm cần cùng thực hiện những hoạt động chung để kiểm soát cả ba loại nợ này
Lý thuyết Tri-System và sự đầu hàng nhận thức
- Bài báo bổ sung LLM vào mô hình tư duy hai hệ của Kahneman mở rộng khung nhận thức bằng cách đặt AI vào vai trò System 3
- System 1 đưa ra quyết định nhanh bằng trực giác, còn System 2 là giai đoạn suy nghĩ có chủ đích về vấn đề
- Để tiết kiệm năng lượng, con người mặc định có xu hướng dựa vào trực giác, và vì vậy có thể bỏ lỡ những yếu tố vốn sẽ được phát hiện nếu suy xét kỹ hơn
- Từ System 3 xuất hiện hiện tượng cognitive surrender, được định nghĩa là trạng thái tin tưởng một cách thiếu phê phán vào suy luận nhân tạo được tạo ra từ bên ngoài, qua đó bỏ qua System 2
- Bài báo phân biệt điều này với cognitive offloading
- cognitive offloading được xem là hành vi ủy nhiệm nhận thức một cách chiến lược trong quá trình suy xét
- Bài báo này triển khai chi tiết Tri-System theory of cognition và cũng xác minh bằng nhiều thí nghiệm mức độ hiệu quả của lý thuyết này trong việc dự đoán hành vi, ít nhất là trong môi trường phòng thí nghiệm
Ký hiệu <> như một biểu tượng mã nguồn
- Gần đây một số minh họa dùng ký hiệu “<>” như biểu tượng của mã, nhưng cách biểu diễn này trông khá lạ nếu xem như ký hiệu bao quanh các thành phần của ngôn ngữ lập trình
- Lý do “<>” được dùng thay vì các ký hiệu khác như “{ }” có vẻ là vì nó gợi nhớ đến HTML hoặc XML
- Khi dùng đến dạng “</>” thì liên tưởng tới HTML còn trực tiếp hơn, nhưng HTML lại không được xem là ngôn ngữ mà lập trình viên dùng để viết chương trình
Khi viết mã trở nên rẻ, thứ đắt lên là verification
- if coding agents make coding free, what becomes the expensive thing cho rằng khi coding agent làm giảm chi phí viết mã, yếu tố trở nên đắt đỏ là verification
- Tiêu chuẩn của tính đúng đắn liên tục thay đổi theo từng bối cảnh
- Thuật toán ETA trong giao thông Jakarta và thuật toán ETA trong giao thông Thành phố Hồ Chí Minh có thể có ý nghĩa khác nhau về “correct”
- Trong điều phối tài xế, cần đồng thời cân bằng công bằng về thu nhập, thời gian chờ của khách hàng và tỷ lệ sử dụng xe, nên định nghĩa “successful” không chỉ có một mà là nhiều định nghĩa
- Trong môi trường hàng trăm kỹ sư liên tục triển khai khoảng 900 microservice, “correct” không còn là một định nghĩa duy nhất mà phân hóa thành hàng nghìn định nghĩa, tất cả đều luôn thay đổi và phụ thuộc ngữ cảnh
- Đây là dạng phán đoán được đặt vào nhóm công việc mà agent không thể làm thay
- Agent đặc biệt hoạt động tốt hơn trong các luồng công việc nơi kết quả có kiểm chứng tốt, và nếu có thể thì tự động hóa
- Những luồng như vậy khuyến khích Test Driven Development
- Dù vậy lượng kiểm chứng vẫn còn rất lớn, nên cần nhiều nỗ lực hơn vào các cách giúp con người dễ hiểu được phạm vi kiểm thử rộng hơn
- Với hiện đại hóa hệ thống legacy, cũng có một số ý kiến khác biệt được nêu ra
- Kỳ vọng rằng agentic coding cuối cùng sẽ giải quyết dứt điểm việc hiện đại hóa legacy là đang bị đánh giá quá cao
- Tuy vậy, có bằng chứng mạnh cho thấy LLM rất hữu ích ở khía cạnh hiểu legacy code đang làm gì
Tái tổ chức theo hướng lấy verification làm trung tâm
- Khi agent đảm nhiệm việc thực thi, công việc của con người chuyển sang thiết kế verification system, định nghĩa quality, và xử lý những trường hợp mơ hồ mà agent không giải quyết được
- Cấu trúc tổ chức cũng cần thay đổi để phù hợp với sự chuyển dịch này
- Câu hỏi trong buổi standup sáng thứ Hai sẽ chuyển trọng tâm từ “đã deploy gì” sang “đã verification điều gì”
- Thay vì theo dõi sản lượng đầu ra, tổ chức sẽ theo dõi liệu kết quả có chính xác hay không
- Một nhóm 10 kỹ sư từng xây tính năng có thể được tái cấu trúc thành 3 kỹ sư cùng với 7 người phụ trách định nghĩa acceptance criteria, thiết kế test harness và giám sát outcome
- Sự tái cấu trúc này có thể gây cảm giác khó chịu, vì nó làm giảm vị thế của hành vi tạo ra thứ gì đó và nâng cao vị thế của hành vi phán đoán
- Văn hóa kỹ thuật không kháng cự sự thay đổi này có nhiều khả năng sẽ làm tốt hơn
Tương lai của mã nguồn và ngôn ngữ thân thiện với LLM
- Trong làn sóng xem LLM như lập trình viên, chính tương lai của mã nguồn cũng trở thành một câu hỏi
- several views of the future of code tổng hợp nhiều góc nhìn khác nhau về tương lai của mã
- Một số bên đang thử nghiệm những ngôn ngữ hoàn toàn mới được thiết kế với LLM trong đầu
- Một số khác lại cho rằng các ngôn ngữ hiện có, đặc biệt là những ngôn ngữ kiểu tĩnh nghiêm ngặt như TypeScript và Rust, có thể phù hợp với LLM hơn
- Bài viết này có nhiều trích dẫn và ít phân tích riêng, nhưng vẫn đáng đọc như một tài liệu tổng quan về toàn bộ cuộc thảo luận
Trừu tượng hóa và đặt tên là phần việc của con người
- Ngay cả khi xây dựng phần mềm cùng LLM, con người vẫn sẽ tiếp tục đảm nhiệm vai trò tạo ra những trừu tượng hữu ích để có thể nói về việc mã đang làm gì
- Điều này gắn với Ubiquitous Language trong DDD
- growing a language bàn về cách phát triển ngôn ngữ cùng với LLM
- Lập trình không chỉ là nhập cú pháp mã hóa để máy tính có thể hiểu và thực thi, mà còn là công việc định hình lời giải
- Người làm phần mềm chia vấn đề thành các phần tập trung, gói dữ liệu liên quan và hành vi với nhau, rồi chọn những cái tên bộc lộ ý định
- Tên gọi tốt cắt tỉa sự phức tạp và biến mã thành một sơ đồ mà mọi người đều có thể theo dõi, đồng thời kết nối rõ ràng giữa cấu trúc vấn đề và cấu trúc lời giải
3 bình luận
Thuật ngữ nợ ý định là thuật ngữ mà trước đây tôi từng tự mình định nghĩa theo cách riêng, nên khi thấy lại thế này cảm giác thật vui. Có lẽ cách con người suy nghĩ đều khá giống nhau.
Bài blog: https://brunch.co.kr/@limjk/2
Việc nhanh chóng tiến hành tái cơ cấu tổ chức để thích ứng với thay đổi cũng khiến tôi có cảm giác hơi bảo thủ nên thấy không mấy thiện cảm.
Ý kiến trên Hacker News
Nếu bạn là kiểu người chỉ thấy yên tâm khi hiểu sâu mọi thứ mình triển khai, thì những thay đổi kiểu này sẽ khiến bạn thấy khá bất an
Giờ đây, ngay cả một dự án hiện đại hóa vốn trước kia mất 2 tháng cũng có thể xong trong khoảng một tuần nếu tập trung thiết kế tốt ranh giới và giao diện, thay vì đào hết logic nghiệp vụ lên để sao chép y nguyên
Và như bài viết nói, chỉ cần dựng test harness tốt để kiểm chứng tính tương đương nhiều nhất có thể
Ban đầu tôi cũng giằng co khá nhiều, nhưng nghĩ kỹ lại thì ngay cả với những hệ thống khác tôi bảo trì hằng ngày, tôi cũng đâu thực sự hiểu rõ đến thế về triển khai bên trong hay logic nghiệp vụ của chúng
Với những đoạn mã tôi viết từ vài năm trước rồi gần như không đụng tới, mỗi khi cần thay đổi gì thì rốt cuộc tôi vẫn phải tin vào test suite hoặc lần theo cấu trúc mã để xác định một hành vi cụ thể
Tôi đã nhiều lần thấy rằng trong các đợt cắt giảm nhân sự hay thắt chặt chi phí, những người có nhiều dạng kiến thức đó thường trụ lại lâu hơn những người không có
Không rõ tôi đang bỏ sót điều gì
Không phải LLM không có đức tính lười biếng
Nếu đưa một base prompt phù hợp với chủ đích, tôi đã khá thành công trong việc khiến agent dùng Claude giảm thiểu thay đổi mã, chạy các lượt loại bỏ trùng lặp, và thể hiện những hành vi trông rất giống bản năng của một lập trình viên kỳ cựu
Tôi nghĩ không phải mô hình chưa từng học được tri thức đó, mà chỉ là trong cấu hình mặc định thì nó không được đưa ra phía trước
Chắc ai cũng từng thấy kiểu mô hình chỉnh sửa quá tay, đụng chạm loạn vào cả codebase mà chẳng hề bận tâm đến thay đổi của người khác hay nguy cơ thất thoát tri thức
Chuyện tạo và kiểm chứng tài liệu rốt cuộc cũng khá giống bài toán locking truyền thống, và vốn đã có những lời giải truyền thống cho nó
Agent hoàn toàn có thể đọc git để hiểu điều gì xảy ra trước, và liệu theo thông lệ có đang ở trạng thái cần đợi thay đổi khác hay không
Tôi cũng khá senior, và thậm chí từng thực sự làm cùng đội với vài người được nhắc đến trong bài này
Tôi không nghĩ họ sẽ nghi ngờ tiêu chuẩn kỹ thuật của tôi
Thế nhưng trong workflow với LLM của tôi, tôi gần như không thấy kiểu debt đó, mà còn có cảm giác chất lượng dự án tốt hơn cả 5 năm trước hay 10 năm trước ngay cả nếu đánh giá theo tiêu chuẩn cũ
Không có gì thần kỳ cả, chỉ cần vận hành tốt các agent cùng chia sẻ ưu tiên về chất lượng như vậy
Và tôi đang làm được nhiều việc thực tế hơn là cố gây chú ý ở các hội nghị
Chỉ là đoạn nói rằng ngay cả theo chỉ số chất lượng phần mềm truyền thống thì vẫn tốt hơn 5 năm trước, 10 năm trước nghe hơi mơ hồ
Tôi muốn biết cụ thể hơn là anh dùng những chỉ số nào, và code của 10 năm trước, 5 năm trước, và bây giờ được so sánh ra sao
Nếu không có giải thích đó thì thông điệp lại thành ra bị loãng và lệch khỏi trọng tâm
Nếu còn gì chia sẻ thêm thì tôi khá tò mò
Thậm chí có thể viết sách với tiêu đề kiểu Practical LLM Coding
Tôi nghĩ phần bị đánh giá thấp nhất ở đây là cách đóng khung bằng intent debt
Cognitive debt hay technical debt ít ra còn để lại dấu vết trong code, còn intent debt thì vô hình
Vì vậy nó chỉ lộ ra khi có một thay đổi nhìn cục bộ thì có vẻ hợp lý nhưng xét toàn cục lại sai
Vì những ràng buộc ban đầu không còn được lưu lại trong bất kỳ hiện vật nào
Trường hợp khó nhất là trong các hệ thống doanh nghiệp, khi ràng buộc đó là yêu cầu tuân thủ, nhưng đã âm thầm thay đổi từ 3 năm trước và chẳng ai cập nhật code
Test vẫn cứ pass nên lại càng dễ bỏ qua
Chỉ riêng test suite thì không thể khôi phục được ý định
Tôi không nghĩ Martin hoàn toàn sai, nhưng lập luận này có vẻ là thứ lúc nào cũng có thể nói ra mỗi khi tầng trừu tượng tăng lên
Theo định nghĩa của ông ấy thì ngay cả việc đi từ Assembly sang Python cũng tạo ra rất nhiều intent debt và cognitive debt
Vì ta đã giao cho interpreter xử lý thay vì tự suy nghĩ xem phải thao tác bit thế nào
Phản biện của tôi là cái gọi là ý định kỹ thuật mà ông ấy nói đến rốt cuộc xuất hiện vì con người phải dịch ý định của mình sang machine code
Bản thân việc suy nghĩ sâu về vấn đề không nhất thiết phải gắn với việc dựng các trừu tượng hướng miền ngay trong code
Bạn có thể suy nghĩ sâu bằng mind map, viết journal, hay dán giấy nhớ lên tường
Trừu tượng hướng đối tượng tự nó không phải phép màu
Trong quá trình đó, sự mơ hồ, những chi tiết chưa được tính tới, thậm chí cả việc cần nghĩ lại cách tiếp cận cũng thường lộ ra
Viết bằng ngôn ngữ tự nhiên cũng có thể là công cụ tư duy, nhưng việc ép tư duy vào một ngôn ngữ hình thức không cho phép mơ hồ thì có một yếu tố rất khác về bản chất
Cũng giống như làm toán chỉ bằng ngôn ngữ tự nhiên mà không có ký hiệu toán học thì vừa rườm rà vừa dễ sai
Chỉ là đang làm điều đó bằng một ngôn ngữ dễ hiểu hơn với con người
Có một ánh xạ trực tiếp giữa ý định và triển khai
Vì ánh xạ đó được xác định rõ và có tính quyết định
Mục đích của trừu tượng là để bạn có thể tin rằng việc mình vừa làm vẫn đúng mà không cần nhìn xuống bên dưới nữa
Điều đó khả thi vì tôi hoặc ai đó mà tôi tin tưởng đã trả chi phí đó một lần
Còn với LLM thì mỗi lần sinh ra đầu ra lại phải kiểm chứng, tức là phải trả khoản debt ấy lại từ đầu
Vì vậy rất khó gọi đây là một tầng trừu tượng
Bài này thực sự viết rất hay
Hôm qua tôi cũng vừa ghi trong ghi chú cá nhân rằng, nếu không liên tục phát triển mã một cách hữu cơ thì khó mà nói mình thực sự sở hữu nó
Giống như xe tự lái, trước đây ít nhất còn nhớ phong cảnh trên đường đi, còn giờ thì như bị dịch chuyển tức thời sang nơi khác rồi chỉ được cho xem lại bản ghi
Kiểu review này kém hiệu quả
Với các công cụ nhỏ thì dạng ghosted code này có thể còn chấp nhận được, nhưng với các hệ thống như cơ sở dữ liệu thì tôi thực sự lo ngại
Vì vậy giờ tôi hầu như không cấp quyền ghi cho agent nữa, và quay lại thiên về QA thủ công như 2 năm trước
Xét cả lượng token lẫn kết quả thì hóa ra cách đó còn hiệu quả hơn
Tất nhiên đây chỉ là trải nghiệm cá nhân của tôi
Đáng tiếc là phần lớn bài báo Wharton mà anh ấy dẫn có vẻ như được tạo bằng AI, và hiện vẫn chưa qua peer review
Tôi biết giờ nhiều nhà nghiên cứu dùng AI để hỗ trợ viết lách, nhưng khi chủ đề bài báo lại chính là cognitive surrender thì thật khó để nghiêm túc tiếp nhận nội dung đó
not merelytới tận 7 lầnTôi cũng không chắc LLM có lặp đúng một cụm đến mức đó không, nên biết đâu lại là tác giả đã hình thành thói quen viết như LLM
Martin không hẳn sai hoàn toàn, nhưng tôi đã trực tiếp thấy AI tạo ra mã lười biếng, và khi đó đáp án đúng lại là viết nhiều code hơn
Cụ thể, có những model Python định nghĩa schema cơ sở dữ liệu cho một tập khái niệm logic nào đó
Sau đó người ta thêm một khái niệm mới rất giống với tập logic sẵn có, và Claude kết luận rằng chỉ cần tái sử dụng nguyên bộ model cũ là được
Trên lý thuyết thì chạy được, nhưng ở phía consumer thực tế lại phải dùng đủ kiểu cách lách vì suy luận kiểu ở runtime
Nó hoạt động, nhưng là một ví dụ bắt sai hoàn toàn tầng trừu tượng
Con người thì thích trừu tượng, nhưng đôi khi lặp lại lại phù hợp hơn
Nếu máy là bên viết và bảo trì code, thì tầng trừu tượng bổ sung như trước đây có thể không còn thật sự cần thiết nữa
Ngày xưa người ta dùng Duff's device và tự unroll loop để trực tiếp tạo mã trùng lặp
Giờ thì compiler hiểu ý định và tự sinh ra assembly lặp, còn chúng ta chẳng mấy bận tâm đến sự trùng lặp đó
Gần đây tôi cần vài đoạn mã hình học tính toán khá không tầm thường bằng LLM; trước đây hẳn tôi sẽ phải đi tìm thư viện, xin phê duyệt compliance, rồi chịu thêm chi phí chuyển cấu trúc dữ liệu miền của mình sang định dạng mà thư viện yêu cầu
Dù chi phí đó có rẻ hơn tự triển khai thì cũng chẳng hề nhỏ
Giờ thì LLM có thể chỉ viết đúng phần tôi cần, và dùng luôn định dạng dữ liệu tôi đang lưu
Không cần kéo vào một thư viện lớn, cũng không cần chuyển đổi cấu trúc dữ liệu
Xét theo chính thống thì đúng ra nên dùng geometry library để tránh trùng lặp, nhưng trong trường hợp này một hàm tự chứa là đủ chạy tốt
Đây thực sự là một trong những thứ hay nhất tôi đọc trên Hacker News từ rất lâu rồi
Tôi đồng cảm mạnh
Chính vì cognitive debt như Simon Willison nói, và vì quan điểm rằng “công việc của bạn là chỉ triển khai mã mà bạn đã chứng minh là chạy đúng”, nên tôi bắt đầu làm một dự án theo hướng Intent-Driven Development
Ý định ban đầu dường như lúc nào cũng mờ dần khi thay đổi tích lũy lên
Có lẽ tôi sẽ hệ thống hóa nó thành một giao thức thực sự rồi đăng lên Hacker News sau
Nếu anh chưa xem các bài viết của tôi thì nên tìm đọc thử
Tóm lại là thế này
Hiện tại cách tôi hình dung vấn đề gần với sơ đồ này hơn: https://excalidraw.com/#json=y1fSSx2z8-0nFs7CDnqhp,d9Di8JdGU...
Tôi nghĩ nút thắt nhận thức trong kỹ nghệ phần mềm không nằm bên trong code nhiều bằng nằm giữa các hiện vật
Code chỉ là một trong số đó
outcome → requirements → spec → acceptance criteria → executable proof → review
Tôi đang làm một bộ công cụ thử nghiệm để tự động hóa các phần nhàm chán giữa những lần chuyển tiếp này, và để con người tập trung vào việc xác minh xem ý định có còn sống sót qua từng bước hay không
Có một tầng nữa tôi muốn thêm vào đây là proxies/metrics
Trong các hệ thống nặng về phân tích, tổn thất thực sự nhiều khi không xảy ra ở spec → code mà ở question → proxy
Một khi proxy đã bị đóng đinh vào acceptance criteria, dashboard hay eval, con người sẽ tối ưu nó, và dần quên mất rằng đó chỉ là chỉ số thay thế
Trên điện thoại, cứ định pan, zoom hay scroll là tôi lại vô tình di chuyển các phần tử trên canvas