Tác nhân AI và cuộc tái cấu trúc không bao giờ diễn ra
Bài viết phân tích một xu hướng đáng lo ngại: các kỹ sư đang dần từ bỏ thói quen tái cấu trúc mã nguồn khi hệ thống trở nên phức tạp, vì tác nhân AI không bao giờ "bị lạc" như con người. Từ đó, tác giả lập luận rằng việc giữ mã nguồn gọn gàng không chỉ tốt cho con người mà còn giúp AI hoạt động chính xác hơn và giảm chi phí token.
Làm việc với tác nhân AI mỗi ngày, tôi bắt đầu nhận ra một xu hướng khiến mình lo lắng. Các đội ngũ — bao gồm cả những kỹ sư giàu kinh nghiệm từng biết rõ điều gì là đúng — đã âm thầm ngừng việc thúc đẩy viết lại hoặc cấu trúc lại những phần rối rắm nhất trong hệ thống của họ.
Vấn đề không nằm ở chất lượng mã mà các tác nhân AI tạo ra. Vấn đề nằm ở một quyết định từng diễn ra gần như theo phản xạ nhưng giờ đây hiếm khi được đưa ra: quyết định dừng lại và nói rằng "hệ thống này đã trở nên khó quản lý, chúng ta cần tái cấu trúc trước khi đi tiếp".
Giới hạn bộ nhớ làm việc của con người
Một chiếc máy tính có thể chứa nhiều thông tin trong "bộ nhớ làm việc" hơn con người rất nhiều. Chúng ta không thể suy luận về một hệ thống phức tạp khi nó phân nhánh theo hàng chục hướng, mỗi nhánh lại có những tác động riêng và tất cả đều liên kết với nhau. Đơn giản là quá nhiều thứ để giữ trong đầu cùng một lúc.
Vì vậy, trong lịch sử, chúng ta đã làm điều duy nhất có thể: chia hệ thống thành các mô-đun đủ nhỏ để hiểu một cách độc lập, sau đó dành công sức kết nối các mô-đun đó với nhau bằng các giao diện mà chúng ta cũng có thể hiểu được. Tính mô-đun, tính đóng gói, tính phân lớp — những thứ này không phải là sở thích thẩm mỹ. Chúng là những nhượng bộ trước kích thước của bộ nhớ làm việc của con người. Chúng ta chia nhỏ hệ thống cho đến khi mỗi phần nằm gọn trong đầu một người, bởi vì đó là cách duy nhất để một người có thể suy luận về nó, thay đổi nó một cách an toàn và xem xét sự thay đổi của người khác.
Hệ thống hiếm khi bắt đầu trong trạng thái rối rắm. Một đoạn mã được viết khi yêu cầu còn đơn giản, và ban đầu nó đọc rất rõ ràng. Sau đó yêu cầu thay đổi. Một nhà phát triển thêm một nhánh cho trường hợp mới, rồi một nhánh khác cho ngoại lệ, rồi một trường hợp đặc biệt chồng lên ngoại lệ đó. Qua đủ các vòng lặp, "quy tắc" ban đầu mà mã thể hiện bị chôn vùi dưới các ngoại lệ — đôi khi yêu cầu đã thay đổi quá xa đến mức mã giờ chỉ còn là các ngoại lệ, không còn quy tắc rõ ràng nào cả.
Khoảnh khắc "bị lạc" từng là tín hiệu quan trọng
Có một khoảnh khắc mà mọi nhà phát triển giàu kinh nghiệm đều nhận ra: bạn đang gỡ lỗi một vấn đề, bạn theo dõi mã, và bạn bị lạc. Các nhánh không còn tạo thành một bức tranh bạn có thể giữ trong đầu. Trong lịch sử, cảm giác đó là một tín hiệu. Một kỹ sư cao cấp, khi bị lạc trong một phần của hệ thống, sẽ dừng lại và nói: phần này đã trở nên khó quản lý — trước khi tôi thêm bất cứ thứ gì khác, tôi cần viết lại hoặc tái cấu trúc để nó có thể hiểu được trở lại. Không phải vì sự thanh lịch, mà để họ và những người sau họ có thể suy luận về nó và an toàn khi xem xét các thay đổi trong tương lai.
Phản xạ đó — "tôi bị lạc, vì vậy đã đến lúc tái cấu trúc" — âm thầm là một trong những lực lượng quan trọng nhất giữ cho các hệ thống tồn tại lâu dài có thể bảo trì được. Và nó được kích hoạt bởi một giới hạn của con người: khoảnh khắc một người không còn có thể theo dõi mã.
Phải công bằng mà nói, phản xạ đó đã chịu áp lực từ lâu trước khi có tác nhân AI. Thời hạn, lộ trình, và các nhà quản lý hỏi "tại sao bạn lại viết lại thứ đang hoạt động?" luôn chống lại nó, và việc tái cấu trúc thường là thứ đầu tiên bị giảm ưu tiên. Các kỹ sư cao cấp đã dần ngừng phản đối mạnh mẽ như trước khi hệ thống trở nên khó quản lý. Tác nhân AI không tạo ra điểm yếu đó. Điều chúng làm là loại bỏ tín hiệu kích hoạt nội tại cuối cùng từng hoạt động bất chấp điều đó — trải nghiệm trực quan của một con người bị lạc.
Vấn đề: tác nhân AI không bao giờ bị lạc
Đây chính là vấn đề. Tác nhân AI không bị giới hạn bởi ngữ cảnh của con người theo cùng cách. Một tác nhân có thể đọc hàm rối rắm, truy vết mọi caller, và hiểu được mớ hỗn độn mà có thể khiến một con người phải dừng lại. Nó có thể thêm nhánh tiếp theo một cách chính xác, và nhánh sau đó nữa, làm việc tự tin bên trong mã mà không một con người nào trong đội còn hiểu đầy đủ.
Điều đó nghe có vẻ là một điểm mạnh, và trong ngắn hạn thì đúng vậy. Nhưng hãy chú ý điều còn thiếu: tác nhân không bao giờ bị lạc, vì vậy tín hiệu không bao giờ được kích hoạt. Tác nhân không có phản xạ nói rằng "hệ thống này đã trở nên khó quản lý, chúng ta nên dừng lại và tái cấu trúc." Nó chỉ tiếp tục thêm các nhánh vào đống mã. Trừ khi được hướng dẫn cụ thể — thông qua khung hoạt động, lời nhắc, hoặc tiêu chí đánh giá rõ ràng — để lùi lại và đặt câu hỏi về cấu trúc, nó sẽ vui vẻ duy trì một mớ hỗn độn vô thời hạn, bởi vì mớ hỗn độn đó không phải là vấn đề đối với tác nhân.
Kiểu thất bại không phải là tác nhân viết mã kém. Mà là điểm kiểm tra tự nhiên biến mất, và con người ngừng nhận thấy mã đã trôi dạt vượt quá sự hiểu biết của họ. Theo thời gian, bạn đạt đến một hệ thống mà:
- Không ai trên đội thực sự hiểu toàn bộ hệ thống
- Mọi thay đổi đều phải thông qua tác nhân AI để có thể thực hiện được
- Rủi ro của việc thay đổi tăng lên vì không ai có thể đánh giá độc lập
Tại thời điểm đó, bạn đã mất một điều quan trọng: khả năng suy luận về hệ thống của chính mình mà không cần tác nhân như một trung gian. Và bạn mất nó một cách dần dần, không có bất kỳ khoảnh khắc báo động đơn lẻ nào, bởi vì khoảnh khắc từng gióng lên hồi chuông cảnh báo — một con người bị lạc — đã âm thầm bị loại khỏi vòng lặp.
Lý do thực dụng để giữ mã nguồn ngăn nắp
Thật hấp dẫn khi đóng khung tất cả những điều này như một mối quan tâm thuần túy về nguyên tắc — chúng ta nên hiểu hệ thống của chính mình — và dừng ở đó. Nhưng có một lý do thực dụng, cứng rắn để giữ mã nguồn có tổ chức, và nó vẫn tồn tại ngay cả khi bạn hoàn toàn hài lòng để tác nhân AI làm công việc đó.
Một tác nhân không bao giờ bị lạc vẫn phải trả giá cho một mớ hỗn độn. Mã càng rối rắm và liên kết chằng chịt, tác nhân càng phải tải và giữ nhiều ngữ cảnh để thực hiện một thay đổi chính xác: nhiều file phải đọc hơn, nhiều nhánh phải truy vết hơn, nhiều token bị đốt hơn cho mỗi lần chỉnh sửa. Một hệ thống được xây dựng từ các mô-đun nhỏ, tự chứa và dễ suy luận không chỉ tốt cho con người — nó còn rẻ hơn để vận hành, vì mọi thay đổi trong tương lai sẽ tốn ít chi phí hơn để tác nhân hiểu.
Và không chỉ là vấn đề chi phí. Khi logic liên quan không nằm gọn trong một phần mạch lạc, có giới hạn, các tác nhân có nhiều khả năng mất mạch và bịa đặt (hallucinate) — giả định một nhánh làm điều gì đó mà nó không làm, hoặc bỏ sót một ngoại lệ bị chôn sâu ba cấp độ. Tính mô-đun giúp giữ hệ thống trong đầu con người cũng giữ mỗi thay đổi trong một ranh giới được xác định rõ mà tác nhân có thể suy luận một cách đáng tin cậy. Ranh giới sạch sẽ giảm sai sót cho cả hai phía, vì cùng một lý do.
Vì vậy, giữ mã nguồn có tổ chức không phải là một ân huệ chúng ta dành cho con người với chi phí của các tác nhân. Nó mang lại lợi ích cho con người, cải thiện độ chính xác của tác nhân, và giảm chi phí token cho mọi thay đổi chúng ta sẽ thực hiện đối với mã đó trong tương lai. Phản xạ tái cấu trúc mà chúng ta có nguy cơ đánh mất không bao giờ chỉ là về sự thoải mái của con người — hóa ra nó cũng là kinh tế tốt.
Giải pháp: đưa điểm kiểm tra trở lại một cách có chủ đích
Tôi không nghĩ câu trả lời là làm suy yếu các tác nhân. Câu trả lời là chúng ta phải đưa điểm kiểm tra trở lại một cách có chủ đích, vì nó không còn tự diễn ra nữa. Chúng ta phải tiếp tục đặt câu hỏi mà tác nhân sẽ không hỏi:
Hệ thống này có còn trong đầu tôi không? Đã đến lúc tái cấu trúc chưa?
Bạn cũng có thể đẩy một phần điều này vào khung hoạt động — hướng dẫn các tác nhân AI của bạn cờ (flag) khi một mô-đun đã vượt quá kích thước hợp lý hoặc độ phức tạp phân nhánh, đề xuất tái cấu trúc thay vì chỉ mở rộng, và chỉ ra khi một thay đổi đang trở nên khó suy luận. Điều đó có ích. Nhưng trách nhiệm cuối cùng vẫn thuộc về chúng ta, bởi vì chúng ta là những người cần hiểu hệ thống của mình, và chúng ta là những người sẽ mất khả năng đó nếu không chú ý.
Sự tiện lợi của một tác nhân không bao giờ bị lạc là có thật. Nhưng "tác nhân vẫn có thể hiểu được nó" không giống với "hệ thống khỏe mạnh." Điều đầu tiên nói về năng lực của tác nhân; điều thứ hai nói về năng lực của chúng ta. Hãy tiếp tục đặt câu hỏi liệu đã đến lúc tái cấu trúc chưa — bởi vì công cụ từng nhắc nhở bạn, bằng cách bị lạc, giờ đây không còn bị lạc nữa.