- Về tuyên bố rằng với agentic coding thì "có thể thay thế mã bằng tài liệu đặc tả", bài viết chỉ ra một giới hạn mang tính nền tảng: nếu đặc tả trở nên đủ chính xác, cuối cùng nó buộc phải hội tụ về cùng một hình thức với mã
- Nhìn vào dự án Symphony của OpenAI, có thể thấy SPEC.md đó không phải là đặc tả mà trên thực tế là mã giả ở định dạng Markdown
- Thực tế, khi thử triển khai bằng Haskell dựa trên đặc tả của Symphony, đã phát sinh nhiều lỗi và các vấn đề về độ tin cậy như agent chờ vô hạn
- Công việc viết đặc tả vốn đòi hỏi tư duy sâu hơn cả lập trình, nhưng trong xu hướng tối ưu hóa tốc độ hiện nay của ngành, đang hình thành một cơ chế sản sinh hàng loạt các bản đặc tả chất lượng thấp do AI tạo ra
- Nguyên tắc "garbage in, garbage out" cũng áp dụng nguyên vẹn cho coding agent; với những tài liệu thiếu rõ ràng và chi tiết thì không thể tạo ra mã đáng tin cậy
Hai ngộ nhận về agentic coding
- Những người ủng hộ agentic coding đang dựa vào hai ngộ nhận cốt lõi
- Ngộ nhận 1: Tài liệu đặc tả đơn giản hơn mã tương ứng — một góc nhìn kiểu thuê ngoài, cho rằng có thể biến kỹ sư thành người quản lý viết tài liệu đặc tả rồi giao việc cho một nhóm agent
- Ngộ nhận 2: Viết đặc tả nhất định sâu sắc hơn viết mã — cho rằng đi qua bước tài liệu đặc tả sẽ cải thiện chất lượng và thúc đẩy các thực hành kỹ thuật tốt hơn
Mã giả làm đặc tả: phân tích trường hợp Symphony
- Dự án Symphony của OpenAI được giới thiệu là một bộ điều phối agent được tạo từ tài liệu đặc tả (SPEC.md), nhưng nội dung thực tế của SPEC.md lại gần với mã giả ở định dạng Markdown hơn là đặc tả
- Các loại nội dung có trong SPEC.md:
- Bản dump văn xuôi của lược đồ cơ sở dữ liệu — liệt kê các trường như
session_id, thread_id, codex_input_tokens
- Chuyển mã sang văn xuôi — các biểu thức như
available_slots = max(max_concurrent_agents - running_count, 0) cho điều khiển đồng thời, công thức backoff khi retry (delay = min(10000 * 2^(attempt-1), agent.max_retry_backoff_ms)) v.v.
- Các mục trùng lặp như "Config Fields Summary (Cheat Sheet)" được thêm vào một cách tường minh để hỗ trợ mô hình sinh mã
- Mục "Reference Algorithms" về thực chất chính là mã nguồn như hàm
start_service()
- Vừa khẳng định tài liệu đặc tả là thứ thay thế mã, nhưng bản thân tài liệu đó lại đọc như mã là điều đánh tráo khái niệm
- Muốn làm tài liệu đặc tả đủ chính xác thì không thể tránh khỏi việc biến nó thành hình thức mã, hoặc viết nó bằng thứ tiếng Anh hình thức có cấu trúc rất cao
Lập luận về "giao diện hẹp" của Dijkstra
- Trích dẫn Dijkstra để nhấn mạnh rằng việc chọn giao diện không chỉ là phân chia lao động đơn thuần; nó còn kéo theo chi phí cộng tác và giao tiếp khi phải vượt qua giao diện đó
- Bài viết nêu các ví dụ lịch sử: toán học Hy Lạp từng trì trệ khi chỉ dừng ở hoạt động ngôn ngữ và thị giác; đại số Hồi giáo suy tàn khi quay lại phong cách tu từ; còn Tây Âu đã thoát khỏi "nỗ lực đạt độ chính xác ngôn ngữ viển vông" của kinh viện trung cổ và phát triển nhờ các hệ ký hiệu hình thức của Vieta, Descartes, Leibniz, Boole
- Các agentic coder không thể né tránh "giao diện hẹp" (= mã) mà lao động kỹ thuật đòi hỏi; họ chỉ có thể chuyển hóa lao động đó sang một hình thức bề ngoài có vẻ khác nhưng vẫn đòi hỏi cùng mức độ chính xác
Tính bất ổn: vấn đề độ tin cậy của việc sinh mã từ đặc tả
- Làm theo khuyến nghị trong README của Symphony và yêu cầu Claude Code triển khai bằng Haskell, kết quả là không chạy được
- Xuất hiện nhiều lỗi, cần sửa thông qua prompt (có thể thấy trong lịch sử commit)
- Ngay cả khi có vẻ "chạy" mà không báo lỗi, agent
codex vẫn đứng chờ vô hạn mà không có tiến triển nào với một ticket Linear đơn giản ("tạo một git repository trống")
- Mượn cách diễn đạt của Dijkstra, có thể thấy "nỗ lực đạt độ chính xác ngôn ngữ viển vông" của Symphony rốt cuộc vẫn không tạo ra được triển khai đáng tin cậy
- Vấn đề này không chỉ riêng Symphony — ngay cả các đặc tả như YAML, vốn cực kỳ chi tiết, được dùng rộng rãi và còn có cả bộ kiểm thử tính tương thích, thì đa số các triển khai YAML vẫn không tuân thủ đầy đủ spec
- Đặc tả của Symphony đã dài bằng 1/6 bản triển khai Elixir đi kèm; nếu còn mở rộng thêm nữa thì sẽ chạm tới tình huống như truyện ngụ ngôn "On Exactitude in Science" của Borges — tấm bản đồ có kích thước bằng cả đế chế và vì vậy trở nên vô dụng
- Trước phản biện rằng "nếu sinh bằng ngôn ngữ mainstream hơn thì kết quả sẽ tốt hơn", bài viết cho rằng nếu agent gặp khó khi sinh mã Haskell thì điều đó cho thấy khả năng khái quát hóa vượt ra ngoài dữ liệu huấn luyện còn yếu
Slop: vấn đề chất lượng của đặc tả do AI tạo ra
- Công việc viết đặc tả vốn dĩ phải khó hơn viết mã; mục đích của nó là buộc người ta nhìn dự án bằng góc nhìn suy xét và phê phán trước khi bắt đầu lập trình
- Nhưng trong xu hướng ngành công nghệ muốn cắt giảm và hạ thấp giá trị lao động, nếu xuất phát từ tiền đề rằng "viết đặc tả dễ hơn viết mã" thì thất bại đã được định sẵn
- Không thể vừa theo đuổi tối ưu hóa tốc độ giao hàng vừa thực hiện được công việc khó khăn và khó chịu mà việc viết đặc tả đòi hỏi
- Section 10.5 của SPEC.md trong Symphony (
linear_graphql extension contract) là một ví dụ điển hình của slop — kiểu đầu ra của agent gồm những câu trông giống đặc tả nhưng thiếu nhất quán, thiếu mục đích và thiếu hiểu biết về bức tranh tổng thể
- Ví dụ, các quy tắc rời rạc như
query phải là chuỗi không rỗng, phải chứa đúng một thao tác GraphQL, v.v. được liệt kê ra nhưng không có ngữ cảnh tổng thể
- Ngay cả khi do con người viết, loại tài liệu đặc tả này cũng tất yếu trở thành slop — vì nó được tối ưu cho thời gian giao hàng chứ không phải cho tính nhất quán hay độ rõ ràng
- Việc các đoạn mã bị chú thích là
text mà không có syntax highlighting cũng là dấu hiệu của tài liệu do AI tạo ra — nhiều khả năng là hệ quả của việc mô hình làm theo câu chữ bề mặt thay vì hiểu đúng ý định của yêu cầu
Kết luận
- Đặc tả vốn không được thiết kế như một công cụ tiết kiệm thời gian
- Nếu mục tiêu là tối ưu thời gian giao hàng, thì viết mã trực tiếp sẽ có lợi hơn so với đi qua một tài liệu đặc tả trung gian
- Nguyên tắc "garbage in, garbage out" vẫn áp dụng nguyên vẹn — nếu đầu vào là những tài liệu thiếu rõ ràng và chi tiết, thì không tồn tại một thế giới nào mà coding agent có thể lấp đầy những thiếu hụt đó một cách đáng tin cậy
- Coding agent không phải thực thể biết đọc suy nghĩ; mà kể cả có thế đi nữa, nếu bản thân tư duy đã hỗn loạn thì chúng cũng chẳng thể làm gì
6 bình luận
Có vẻ giống hệt như khi phát triển hướng mô hình vậy.
Chẳng phải phát triển dựa trên đặc tả SDD vốn dĩ đã có từ trước rồi sao.
Có vẻ như với các giải pháp dựa trên Python hoặc JavaScript, chỉ cần tài liệu đặc tả chi tiết thôi cũng có thể hiện thực được khá như ý. Tôi làm ở mảng game/y tế dựa trên C/C++, mà dạo này càng thấy rằng không chỉ chuyện giao phó cho FULL AI AGENT là còn xa, mà ngay cả việc tự động hóa chỉ bằng tài liệu đặc tả chi tiết thôi cũng là một canh bạc quá mạo hiểm.
Ý kiến trên Hacker News
Tôi không đồng ý với ý rằng nếu đưa vào tài liệu không rõ ràng thì tác nhân lập trình cũng không thể tự điền phần chi tiết
LLM về bản chất là một cỗ máy nội suy/ngoại suy ngôn ngữ, nên rất giỏi trong việc lấp đầy những chi tiết còn thiếu
Có nhiều trường hợp chỉ với mô tả ngắn gọn, súc tích mà vẫn tạo ra được mã chạy được
Tuy nhiên, kiểu bổ sung chi tiết này không phải lúc nào cũng đúng, và để đảm bảo độ tin cậy thì cần ràng buộc tường minh những phần quan trọng
Hiện nay có văn hóa viết code, nhưng văn hóa viết đặc tả siêu chính xác thì gần như không tồn tại ngoài những nơi như NASA
Code càng ngắn và càng phổ biến thì càng hoạt động tốt, nhưng với mô tả phức tạp thì rất dễ sụp đổ
Rốt cuộc, việc thừa nhận rằng “phần chi tiết bổ sung có thể sai” cũng có nghĩa là việc sinh ra kết quả đáng tin cậy là khó
Ví dụ có các ngôn ngữ tổng hợp chương trình như Synquid
Chúng cho thấy những giới hạn của việc sinh chương trình từ đặc tả chính xác về mặt toán học
Vấn đề được gọi là specification gap, tức là việc chứng minh chương trình có thực sự triển khai đúng đặc tả hay không mới là nhiệm vụ cốt lõi
Ngôn ngữ tự nhiên quá mơ hồ nên không phù hợp để định nghĩa chương trình
Việc LLM điền vào các chi tiết có vẻ hợp lý không có nghĩa là khoảng cách đó được giải quyết
Ngôn ngữ đặc tả toán học thì chính xác, nhưng đường cong học tập cao và khó, tốn công hơn rất nhiều so với chỉ viết prompt bằng Markdown
Mô hình có thể nhớ mối quan tâm của tôi, hoặc tự dùng tri thức của nó để lấp chỗ trống và tạo ra một ứng dụng, trò chơi hay whitepaper hoàn chỉnh
Có lúc đó là “đúng chính xác thứ tôi muốn”, có lúc lại là “đúng cái cảm giác tôi đang muốn nói đến”
Khả năng xử lý ý nghĩa, ngữ cảnh và sắc thái có những mặt còn vượt cả con người
AI đang ngày càng thông minh và có năng lực hơn
Tức là nó gần với việc kéo từ dữ liệu huấn luyện ra hơn là sáng tạo nên những chi tiết hoàn toàn mới
Tôi đồng cảm với câu “đặc tả đủ chi tiết thì chính là code”
Điều này giống với lập luận trong No Silver Bullet của Brooks
Nhưng đa số mọi người không muốn đi tới mức chi tiết như vậy
Khi bảo “hãy làm cho tôi một ứng dụng to-do bằng AI”, thực chất ý là “hãy làm một ứng dụng tốt hơn thứ tôi tưởng tượng”
Nhưng cách tiếp cận này không dễ mở rộng sang các loại phần mềm khác
Cuối cùng, bạn vẫn phải biểu diễn điểm khác biệt đó dưới dạng đặc tả
Nhưng ở các lĩnh vực như cơ sở dữ liệu, hệ thống tệp, tính toán song song, nơi độ chính xác và hiệu năng là tối quan trọng, thì việc triển khai khó hơn đặc tả rất nhiều
Việc AI tạo ra code vượt qua được kiểm chứng hình thức trong các lĩnh vực này là một thách thức lớn
Muốn kiếm tiền hoặc cạnh tranh thì phải có yêu cầu cụ thể
Nếu nhìn vibe coding dưới góc độ lý thuyết thông tin, thì đó là giả định rằng tồn tại một bộ giải mã có thể phục hồi không gian chương trình hữu ích từ một không gian prompt nhỏ
Lúc này, tỷ lệ nén chính là lợi ích của vibe coding
Một prompt như “ứng dụng giao tiếp nhóm dựa trên kênh IRC” là không thể giải mã nếu không biết Slack
Vì vậy, điều quan trọng là nhận ra cái gì đang bị thiếu
Muốn code với AI hiệu quả thì nên chia prompt thành các đơn vị ngắn, đồng thời cung cấp kèm tài liệu hiện có hoặc đoạn code đã thử
Theo Algorithmic Information Theory, lượng thông tin của một chuỗi bằng độ dài của biểu diễn tự hoàn chỉnh được nén nhất của nó
Tuy nhiên, điều kiện “tự hoàn chỉnh” chỉ đúng khi trọng số của mô hình đóng vai trò như một codebook
Con người giả định ngữ cảnh chia sẻ nhiều hơn LLM rất nhiều, nên thường đánh giá quá cao giới hạn của bộ giải mã
Nhưng với một hệ thống có ràng buộc mạnh và trọng tâm rõ ràng, có vẻ tỷ lệ nén của vibe coding có thể tăng bùng nổ
Ngôn ngữ tự nhiên mang lại một giao diện mới cho những người cảm thấy ngôn ngữ lập trình khó tiếp cận hơn
LLM không suy nghĩ thay bạn, nhưng nó mở ra một con đường mới để biến ý tưởng thành hệ thống hoạt động được
Có lẽ sắp tới con người sẽ tạo ra một phương ngữ tiếng Anh kỹ thuật kiểu LLMSpeak để tối ưu hiệu năng mô hình và hiệu quả token
Kiểu như giảm mơ hồ, tiết kiệm token, và nén các khái niệm phức tạp vào một từ
Về mặt ngữ pháp, có lẽ cũng sẽ xuất hiện các quy tắc như Oxford comma để tăng độ rõ ràng
Nếu đã đặc tả chi li như vậy thì chẳng còn lý do gì để dùng prompt nữa
Cuối cùng vẫn phải định nghĩa lại bằng ngôn ngữ con người, nên hiệu quả tiết kiệm token là có hạn
Xem wiki Lojban, video người nói Lojban
Những nỗ lực tạo phương ngữ nhân tạo có khả năng thất bại giống Esperanto
Những ngôn ngữ như vậy có khi lại hữu ích hơn khi dùng giữa các LLM với nhau
Và ngôn ngữ lập trình từ lâu đã đóng vai trò đó rồi
Spec là một kiểu phong bì (envelope) bao trùm mọi chương trình thỏa điều kiện đó
Việc tạo ra phong bì này còn khó hơn viết ra một chương trình đơn lẻ
Cũng như việc LLM sinh ra code khác nhau mỗi lần, đặc tả cho phép cả triển khai tốt lẫn triển khai kém
Trên thực tế, khi một triển khai được chấp nhận thì nó sẽ trở thành đặc tả trên thực tế cho phiên bản kế tiếp
Trong môi trường có code sẵn từ trước (brownfield), đặc tả không còn sạch sẽ nên LLM khó ứng phó tốt
Có một bùng nổ tổ hợp khi phải cân nhắc một dòng đặc tả sẽ tương tác thế nào với các dòng khác
Nhưng từ góc nhìn của compiler thì code cũng chỉ là đặc tả mà thôi
Cuối cùng, chuyện “code dễ hơn đặc tả” chỉ là tương đối
Một đặc tả như “lưu thông tin xác thực người dùng” có thể bao gồm từ bcrypt cho tới cookie lưu plaintext
Con người có trực giác rằng “cái đó thì không được làm”, nhưng tác nhân thì sẽ không biết nếu không ghi rõ
Vì vậy, muốn đảm bảo bảo mật thì phải đặc tả cả những điều không được làm
Nếu hiệu năng hay bảo mật là quan trọng thì phải nêu rõ các thuộc tính đó
Ví dụ, câu “chương trình này phải là O(n)” đơn giản hơn triển khai rất nhiều
Có vẻ mỗi người đang dùng từ spec với nghĩa khác nhau
Với tôi, spec là thứ định nghĩa “làm gì (what)”, plan là “làm như thế nào (how)”, còn build packet là “các bước chi tiết”
Trong đa số trường hợp, phần quan trọng là “làm gì”
Việc viết thành đặc tả rằng dữ liệu đi từ A sang B, qua C, được bảo toàn ở D và được biểu diễn dưới dạng F tại E, dễ hơn nhiều so với triển khai nó bằng code Rust
Khi làm agentic engineering, nhiều khi tài liệu đặc tả dài hơn cả code
Ngôn ngữ tự nhiên thì không hoàn chỉnh, nhưng code thì chính xác
Mục đích của đặc tả là giữ nguyên chức năng qua nhiều vòng lặp phát triển
Với tôi, tài liệu thiết kế kiểu waterfall hiệu quả hơn test hay comment
Theo cách này, tôi cũng đã refactor trơn tru các dự án vibe coding hoàn chỉnh hoặc đổi ngôn ngữ cho chúng
Bây giờ có cảm giác như đang quay lại quy trình phát triển của thập niên 70–80
Những câu như “hãy triển khai giao diện TCP” ngắn hơn code thực tế rất nhiều
Cuối cùng, nếu có thể ánh xạ sang một schema rõ ràng, thì ngôn ngữ tự nhiên cũng có thể rất cô đọng
Hướng Spec → LLM là không hiệu quả và lãng phí
Ngược lại, LLM → Spec thực tế hơn
Nếu đặc tả tồn tại ở dạng có thể biên dịch, thì LLM có thể nhận phản hồi đó để sinh ra code tốt hơn
Những nỗ lực tạo ra “tiếng Anh được kiểm chứng (validated English)” chỉ làm tăng thêm độ phức tạp
Cuối cùng, thứ quan trọng vẫn là code thực sự chạy được
Code chứa nhiều thứ hơn đặc tả rất nhiều
Phần lớn dự án có 90% là code framework hoặc hạ tầng, chỉ 10% là logic nghiệp vụ
Đặc tả không xử lý chi tiết ngôn ngữ hay framework nên ngắn gọn hơn nhiều
Làm như vậy sẽ tạo ra code gần như ở cùng mức với đặc tả
Chuyên gia miền nghiệp vụ cũng đọc được và việc kiểm thử cũng dễ hơn
Nhưng code thực tế sẽ thay đổi khá nhiều
Sự xung đột giữa cách nhìn đặc tả như công cụ quản lý và như công cụ kỹ thuật tạo ra cảm giác bất hòa nhận thức
Nhà quản lý xem đặc tả như một ticket để giao việc, còn lập trình viên dùng nó như công cụ tư duy để tinh luyện suy nghĩ
Một số lập trình viên ban đầu thuận tiện nên cũng tiếp cận theo kiểu của quản lý, nhưng rồi sớm nhận ra
Có thể sống nhờ hype hay các buổi gặp nhà đầu tư trong một thời gian, nhưng rốt cuộc người dùng vẫn muốn sản phẩm thật
Tiếp theo chắc lại tái phát minh cả Waterfall với Agile nữa nhỉ
Là một lập trình viên embedded C, tôi tạo đặc tả sao cho gần như mọi luồng của Feature/Subfeature đều có thể được kiểm tra bằng biểu đồ.
Sau khi xem xét đặc tả kỹ lưỡng trong thời gian dài và chốt bản cuối cùng,
tôi tạo ra đoạn mã tương ứng hoàn toàn 1:1 với đặc tả để sử dụng.
Khi rà soát bằng đặc tả thì khả năng đọc hiểu vượt trội hơn hẳn so với rà soát mã.