Ngành đang bắt kịp: spec phải chạy được thì code AI mới đáng tin

Dave Farley giải thích vì sao code do AI viết cần executable specification theo kiểu ATDD, mô hình test bốn lớp và ba quy tắc làm việc với agent.

Đã duyệt độc lập · cập nhật 25/10/2026 · 21 min

1. Một kết luận mà nhiều người cùng đi tới

Dave Farley mở đầu: anh có chính kiến (opinionated) về rất nhiều thứ, nhưng đặc biệt là về phát triển phần mềm. Và anh đang nhanh chóng đi tới kết luận rằng mình biết tương lai của phát triển phần mềm có AI hỗ trợ (AI-assisted software development) nhiều khả năng sẽ trông như thế nào (video đăng ngày 21/10/2026).

Điều thú vị là hoá ra rất nhiều người khác cũng đang đi tới đúng kết luận đó. Vậy nên có thể anh, và tất cả những người kia, đang nắm được một điều gì đó thật. Đó là chủ đề của video này, trên kênh Modern Software Engineering, do chính Dave Farley trình bày.

2. Bob Martin, Adam Tornhill, Sean Grove, Kent Beck, Emily Bache và Anthropic

Dave điểm qua một loạt tên tuổi trong ngành, mỗi người một câu (tất cả theo cách Dave thuật lại trong video đăng ngày 21/10/2026).

Bob Martin nói rằng ông không còn đọc code mà các agent của ông viết nữa. Thay vào đó, ông bao quanh các agent bằng những ràng buộc cực kỳ chặt (extreme constraints): unit test, Gherkin test, quy trình QA, các chỉ số chất lượng (quality metrics) và mutation testing (video đăng ngày 21/10/2026).

Bài đăng của Uncle Bob Martin về việc không đọc code do agent viết
Bài đăng của Uncle Bob Martin mà Dave dẫn, đề ngày 23/07/2026: ông bắt đầu code từ cuối thập niên 60, chiến lược của ông là không đọc code agent viết, mà bao quanh agent bằng unit test, Gherkin test, quy trình QA, quality metrics, mutation testing, test coverage và nhiều thứ khác.

Adam Tornhill, sau 25 năm làm test-driven development (TDD), đã bỏ vòng lặp red-green-refactor chi tiết khi làm việc với agent, nhưng vẫn giữ một quy tắc sống còn, theo lời ông mà Dave trích: "Tôi luôn dẫn dắt mọi thay đổi trong codebase bằng một test đang fail." Có điều, test của ông, giống hệt test của Dave, đã được nâng lên một tầng trừu tượng. Giờ ông định nghĩa chúng như những đặc tả hành vi end-to-end (specifications of end-to-end behavior), chứ không phải unit test gắn với chi tiết implementation (theo Dave thuật lại, video đăng ngày 21/10/2026).

Dave kể rằng chính anh đã làm việc theo cách này, dẫn dắt phát triển bằng acceptance test-driven development kiểu BDD, ít nhất 20 năm qua (tính tới lúc quay video đăng ngày 21/10/2026). Anh không biết điều này có phải là một phần trong cách Adam làm TDD trước đây không, nhưng giờ thì với cả hai người, những đặc tả này chính là chương trình.

Sean Grove của OpenAI đứng trên sân khấu AI Engineer World's Fair và nói với cả khán phòng: hãy làm cho specification chạy được (make the specification executable), đưa spec cho model, và test dựa trên spec (theo Dave thuật lại, video đăng ngày 21/10/2026).

Kent Beck gọi TDD là một "siêu năng lực" (superpower) khi làm việc với AI agent. Emily Bache nói rằng tất cả các loại test gộp lại tạo thành specification, bất kể ai là người viết từng loại. Và hướng dẫn của chính Anthropic cho Claude Code nói thẳng: nếu bạn không kiểm chứng được nó, đừng ship nó ("If you can't verify it, don't ship it"). Cả mấy câu này đều là lời các nhân vật đó theo Dave thuật lại trong video đăng ngày 21/10/2026.

3. Việc của con người: nói chính xác code phải làm gì

Những người này không đồng ý với nhau về mọi thứ. Một số người trong đó gần như chẳng đồng ý với nhau về điều gì cả. Nhưng theo Dave (video đăng ngày 21/10/2026), họ và anh đã đi tới, phần lớn là độc lập, cùng một kết luận: khi máy viết code, việc của con người là nói chính xác code phải làm gì, dưới một dạng có thể kiểm tra tự động.

Không phải một prompt. Không phải một tài liệu markdown. Mà là một specification chạy được, và kiểm chứng rằng hệ thống làm đúng những gì bạn muốn nó làm. Dave nói: nếu bạn còn chưa biết mình muốn nó làm gì, thì bạn chưa thực sự là lập trình viên; bạn chỉ đang ngồi cho có (just along for the ride). Cho nên việc tìm ra mình muốn hệ thống làm gì, rồi kiểm chứng rằng nó làm đúng điều đó, theo anh là, và vẫn luôn là, phần cốt lõi nền tảng trong công việc của người lập trình (video đăng ngày 21/10/2026).

Slide Programming Always và Programming Now with Added AI, mỗi dòng ba bước
Slide của Dave: "Programming - ALWAYS" gồm ba việc "Figure Out What it's Meant to do!", "Make it Do It!", "Check it Does it Properly!". Ở dòng "Programming - Now with Added AI", ô giữa (làm cho nó chạy) thu nhỏ lại, còn hai việc hai đầu vẫn nguyên.

Dave đã cổ vũ cho cách làm này từ rất lâu. Anh gọi nó là acceptance test driven development (ATDD), và anh đã dạy cách phát triển này từ trước khi bất kỳ ai ngoài các phòng nghiên cứu nghe tới large language model. Điều làm anh quan tâm lúc quay video (đăng ngày 21/10/2026) không phải là việc anh vẫn thấy cách này có giá trị, dù anh vẫn thấy vậy, mà là nó dường như đang trở thành tâm điểm của một đồng thuận ngày càng lớn.

Những người đang xây và dùng các công cụ AI đang tự mình khám phá lại cách tiếp cận dựa trên ý định (intent-based) mạnh mẽ này. Có thể mỗi người dùng một ngôn ngữ khác để mô tả, nhưng theo Dave, đó vẫn là cùng một ý tưởng (video đăng ngày 21/10/2026).

4. Ba bài toán khó của lập trình, và AI làm chúng khó hơn

Theo Dave, lập trình luôn bao gồm ba bài toán khó:

  1. Phải đặc tả (specify) chính xác thứ mình muốn.
  2. Phải kiểm chứng (verify) rằng mình đã có được thứ mình muốn.
  3. Phải tiến từng bước nhỏ, đủ nhỏ để biết khi nào mình đã đi chệch hướng và đang đi sai đường.

Mọi thứ khác, anh nói, thật ra chỉ là chi tiết. AI thay đổi bài toán kinh tế của đúng một hoạt động: sản xuất ra code. Nó không làm gì cho ba bài toán kia, những bài toán mà theo anh còn nền tảng hơn và khó hơn. Nếu có, thì nó còn làm mỗi bài toán tệ hơn (nhận định của Dave trong video đăng ngày 21/10/2026):

  • Một prompt mơ hồ hơn một chương trình, nên dễ bị diễn giải theo nhiều cách hơn, và quan trọng hơn là dễ bị diễn giải sai (video đăng ngày 21/10/2026).
  • Một model sẵn sàng thay đổi nhiều hơn những gì bạn yêu cầu. Vì vậy bạn không thể chắc rằng hệ thống vẫn tiếp tục làm những việc nó từng làm ở lần cuối bạn kiểm tra (video đăng ngày 21/10/2026).
  • Một công cụ sinh ra một nghìn dòng mỗi phút khiến bạn rất dễ bị cám dỗ bước những bước quá lớn. Điều đó có nghĩa là những thay đổi bạn cần biết, dù tốt hay xấu, sẽ bị chìm trong mớ nhiễu của những thay đổi bạn chẳng hề quan tâm (video đăng ngày 21/10/2026).
Slide ba bài toán: Specify what we want, Verify that we got it, Proceed in small safe steps
Ba bài toán trên slide, mỗi cái kèm lý do AI làm nó khó hơn: "Natural Language Prompts are too vague to be precise", "AI can change more than we asked for", "Humans can't keep up" (slide trong video đăng ngày 21/10/2026).

5. Verification mới là nút cổ chai

Dave dẫn lời Steve Yegge: theo Dave thuật lại (video đăng ngày 21/10/2026), Yegge nói ông sản xuất 12.000 dòng code mỗi ngày với các agent của mình. Không con người nào có thể review 12.000 dòng một ngày theo cách có ý nghĩa và sâu sắc.

Vậy câu hỏi thú vị thật ra không phải là chúng ta sinh code nhanh được tới đâu. Mà là chúng ta có thể biết nhanh tới đâu rằng code mình tạo ra đang làm đúng việc (video đăng ngày 21/10/2026).

Slide hai câu hỏi: câu hỏi sai và câu hỏi đúng
Trên màn hình, câu hỏi được đặt hơi khác lời nói: "How fast can we generate code" bị đánh dấu là câu hỏi sai, còn "How fast can we generate releasable systems" (sinh ra hệ thống có thể release nhanh tới đâu) là câu hỏi đúng (slide trong video đăng ngày 21/10/2026).

Một người viết về việc chạy agent ở quy mô lớn đã nói điều này rất hay, theo Dave: bất cứ thứ gì không được test kỹ đều bị thoái hoá một cách ngẫu nhiên (stochastically degraded). Kent Beck còn nói hay hơn: khi một công cụ tuyên bố làm xong 80% một hệ thống tính lương (payroll system) chỉ trong một prompt, có thể nó nói đúng. Nhưng 80% của một hệ thống tính lương cũng chính là 0% của một hệ thống tính lương (lời Kent Beck theo Dave trích, video đăng ngày 21/10/2026).

Kết luận của Dave (video đăng ngày 21/10/2026): verification giờ là nút cổ chai.

6. Để AI tự viết test sau khi viết code thì không đủ

Một phản ứng phổ biến trước vấn đề này là: "Thì cứ scale lên bằng cách bảo AI viết hết test." Nhưng Dave chỉ ra: nếu ta bảo agent viết test sau khi nó đã viết code, thì đầu vào duy nhất của những test đó là chính đoạn code ấy (video đăng ngày 21/10/2026).

Một test sinh ra từ code chỉ có thể xác nhận rằng code làm đúng những gì nó vốn đang làm. Nó không thể cho ta biết code có làm điều gì hữu ích không, hay có làm đúng điều ta muốn không (video đăng ngày 21/10/2026).

Ý định (intent) phải đến từ một nơi khác. Nó phải đến từ chúng ta, và phải ở dạng mà ta dùng được để đo kết quả, để kiểm chứng rằng mình thật sự đạt được mục tiêu, dù mục tiêu đó là gì (video đăng ngày 21/10/2026).

Code do AI viếtTest sinh từ code"code làm đúng cái nó đang làm" Ý định của ngườiSpec chạy được"code làm đúng cái ta muốn" Test viết sau codeTest viết từ ý định, trước code
Hình 6.1Lập luận của Dave: test viết sau code chỉ có đầu vào là code, nên chỉ xác nhận lại chính nó; muốn đo code có đúng ý mình không thì ý định phải đến từ con người (video đăng ngày 21/10/2026).

7. Spec-driven development: chẩn đoán đúng, cách làm còn thiếu

Theo Dave, ngành đã nhận ra vấn đề này, và trong năm 2025 spec-driven development trở thành một câu trả lời thời thượng. Những gì anh kể (theo video đăng ngày 21/10/2026):

  • GitHub phát hành Spec Kit và tuyên bố rằng ý định (intent) là nguồn sự thật (source of truth), theo Dave (video đăng ngày 21/10/2026).
  • Amazon xây Kiro xoay quanh các tiêu chí chấp nhận có cấu trúc (structured acceptance criteria), theo Dave (video đăng ngày 21/10/2026).
  • Tessl đi xa hơn: đề xuất rằng spec, chứ không phải code, mới là artifact bạn bảo trì, còn code là một output có thể sinh lại (regeneratable), theo Dave (video đăng ngày 21/10/2026).
  • ThoughtWorks đưa cả ý tưởng này lên Technology Radar của họ, ở mức "assess", theo Dave (video đăng ngày 21/10/2026).
Trang chủ Kiro với tiêu đề Move beyond AI coding to agentic engineering
Trang chủ Kiro mà Dave đưa lên khi nhắc tới Amazon, tiêu đề "Move beyond AI coding to agentic engineering", mô tả biến prompt thành executable spec (theo màn hình trong video đăng ngày 21/10/2026).

Dave nghĩ những người này đúng về chẩn đoán, nhưng bỏ sót vài thứ ở phần thực thi. Không thể lái một agent bằng cảm tính (vibes), vì như vậy quá mơ hồ. Bạn cần một phát biểu rõ ràng về thứ mình muốn đạt được trước khi agent bắt đầu. Bạn cũng cần phát biểu rõ ràng đó tồn tại tiếp sau khi agent đã làm xong (video đăng ngày 21/10/2026).

Anh nói như vậy đã tốt hơn nhiều so với kiểu "mô tả mục tiêu rồi nhận về một khối code lớn mà bạn phải tự review bằng tay". Nhưng hãy nhìn xem spec được làm từ gì: văn xuôi markdown (markdown prose), có khi là văn xuôi có cấu trúc, nhưng vẫn là văn xuôi (video đăng ngày 21/10/2026).

8. Spec bằng prose chỉ là một prompt dài hơn

Theo Dave (video đăng ngày 21/10/2026), những người dùng thử các công cụ này cứ vấp mãi vào cùng một loại vấn đề. Anh dẫn ba người:

Gojko Adzic, người đúng nghĩa đen đã viết cuốn sách về specification by example, dùng thử Spec Kit và thấy rằng spec markdown thiếu vô số chi tiết. Spec thật rốt cuộc lại nằm trong unit test và integration test (theo Dave thuật lại, video đăng ngày 21/10/2026).

Birgitta Böckeler ở ThoughtWorks làm việc với ba công cụ như vậy và kể rằng: ngay cả với đủ các file, template, prompt, workflow và checklist, chị vẫn thường xuyên thấy agent rốt cuộc không làm theo hết các chỉ dẫn. Bài viết của chị trên trang Martin Fowler có câu này, gần như nguyên văn (đọc ngày 25/10/2026).

Câu trích của Birgitta Böckeler về việc agent không theo hết chỉ dẫn
Câu trích của Birgitta Böckeler trên màn hình: "Even with all of these files, templates, prompts, workflows and checklists, I frequently saw the agent ultimately not follow all the instructions." (màn hình trong video đăng ngày 21/10/2026)

Colin Eberhardt ở Scott Logic thì nói thẳng hơn: code là luật, vì nó là một ngôn ngữ hình thức (formal language) mà bạn có thể lập luận về nó. Bạn test được nó. Bạn chứng minh được nó đúng hay sai. Còn specification, hay ít nhất là những spec viết theo định dạng markdown của Spec Kit, thì thiếu tính hình thức này (lời ông theo Dave trích, video đăng ngày 21/10/2026).

Dave nói: đó là toàn bộ vấn đề gói trong một đoạn. Một specification bằng văn xuôi là một prompt với số chữ nhiều hơn. Agent có thể đọc nó, tạo ra thứ gì đó không làm đúng điều spec nói, nhưng agent không báo cho bạn, thậm chí không biết là có gì sai, vì chẳng có gì fail, chẳng có gì chuyển đỏ. Bạn lại quay về đọc code, bắt chéo ngón tay và hy vọng mọi thứ sẽ ổn. Và theo Dave, nhiều khả năng là sẽ không ổn (video đăng ngày 21/10/2026).

Markus Eisele, viết cho O'Reilly, đã nhìn ra lối thoát, theo Dave (video đăng ngày 21/10/2026): behavior driven development, khi làm tốt, gộp việc viết spec và việc kiểm chứng spec vào cùng một artifact.

9. Executable specification: spec và kiểm chứng là cùng một thứ

"Chính xác là vậy", Dave nói. Specification và phần kiểm chứng rằng code đáp ứng specification đó nên là cùng một thứ. Khi chúng là một, spec không thể trôi lệch (drift) khỏi code, vì ngay khoảnh khắc nó lệch, build sẽ vỡ (video đăng ngày 21/10/2026).

Một executable specification là một ví dụ về việc hệ thống làm điều gì đó hữu ích, viết bằng ngôn ngữ của miền bài toán (language of the problem domain). Nhưng nó cũng là thứ chạy được trên hệ thống thật, và sẽ fail cho tới khi hành vi được mô tả thực sự tồn tại (định nghĩa của Dave, video đăng ngày 21/10/2026). Dave đưa ra một ví dụ:

Buy Books
Given a customer with a book in their basket
When they apply the discount code SUMMER
Then the basket total is reduced by 10%
Thẻ Buy Books với Given, When, Then về mã giảm giá SUMMER
Ví dụ executable specification của Dave dạng Given/When/Then: khách có một cuốn sách trong giỏ, áp mã giảm giá SUMMER, tổng giỏ hàng giảm 10%.

Hãy để ý những gì không có trong đó: không nhắc tới HTTP, không có nút nào được bấm, không có bảng database, không có tên class. Nó nói hệ thống phải làm gì và không nói gì cả về cách hệ thống làm điều đó. Dave nhấn mạnh: đó không phải tình cờ, cũng không phải chuyện văn phong. Đó là toàn bộ ý nghĩa.

Một specification mô tả lời giải thì không phải specification. Nó là một bản design, và nó sẽ vỡ ngay khi ai đó, hoặc thứ gì đó, tìm ra một design tốt hơn. Loại specification về hành vi này đúng một cách sâu sắc hơn: nó đúng bất kể ta hay AI của ta chọn implement lời giải nào (video đăng ngày 21/10/2026).

Nó vẫn đúng ngay cả khi ta thay đổi thứ gì đó làm test fail. Lúc đó test đang nói với ta, đang hét vào mặt ta, rằng code của bạn không làm điều bạn đã nói nó phải làm. Miễn là một implementation đáp ứng mọi specification của nó, tức là pass mọi executable test đại diện cho các specification đó, thì nó hợp lệ. Dave thêm một điều kiện: với giả định là ta đặc tả đủ chi tiết thứ mình muốn.

Còn khi ta không đặc tả đủ thì sao? Theo Dave, cũng y như viết code ngày xưa: ta học từ sai lầm khi phát hiện ra nó, rồi thêm specification, giống như ngày trước ta sẽ thêm code.

10. Thế hệ lập trình tiếp theo và mô hình bốn lớp

Dave nghĩ rằng sự đồng thuận anh mô tả ở đầu video thực chất đang mô tả thế hệ lập trình tiếp theo. Ta chuyển từ việc đặc tả một lời giải duy nhất sang việc đặc tả ý định của mình cho hệ thống, đủ chi tiết để kiểm chứng được rằng mình thật sự có được thứ mình muốn (video đăng ngày 21/10/2026).

Làm việc theo cách này có nghĩa là, theo Dave (video đăng ngày 21/10/2026), AI có viết lại toàn bộ hệ thống bên dưới ta cũng không sao, miễn là phiên bản mới vẫn pass mọi specification và vì thế vẫn đáp ứng ý định về hành vi của ta.

Để một ví dụ như cái anh đưa lúc trước chạy được, Dave và các trợ lý AI của anh dựng test theo bốn lớp (theo video đăng ngày 21/10/2026):

  1. Test case: bản thân các test case, viết bằng ngôn ngữ của miền bài toán.
  2. DSL: bên dưới là một domain-specific language, nhằm giúp test dễ viết và chạy nhất quán. DSL biến những ý tưởng hành vi như "áp mã giảm giá" (apply the discount code) thành một thao tác dùng lại được.
  3. Protocol driver: nằm dưới lớp DSL, biết cách nói chuyện với hệ thống thật qua UI, qua API, hay qua bất cứ thứ gì hệ thống phơi ra.
  4. System under test: lớp cuối cùng là chính hệ thống được test.
Sơ đồ bốn lớp: Test Case, DSL, Protocol Driver, System Under Test
Mô hình bốn lớp của Dave: một hàng test case ở trên cùng, một lớp DSL, ba protocol driver, và system under test ở dưới đáy.

Specification nằm ở trên cùng. Mọi sự phụ thuộc kỹ thuật (technical coupling) nằm ở dưới đáy. Thay cả implementation, đổi web framework, viết lại bằng một ngôn ngữ khác, thì specification vẫn đứng vững và vẫn nói cho bạn sự thật về điều hệ thống phải làm (video đăng ngày 21/10/2026).

Một test Java shouldAddBookToShoppingBasket viết bằng DSL
Một test case viết qua lớp DSL, trong IDE: mỗi dòng là một thao tác nghiệp vụ (thêm khách, thêm sách, vào cửa hàng, tìm sách, chọn sách, thêm vào giỏ, thanh toán, kiểm tra đã mua), không có chi tiết UI hay HTTP nào.

Đoạn code trên màn hình (bỏ các gợi ý tên tham số mà IDE hiển thị chèn vào):

@Test
public void shouldAddBookToShoppingBasket()
{
    shopping.addCustomer("name: somePerson");
    inventory.addBook("title: Continuous Delivery",
            "author: David Farley", "price: 20.00");

    shopping.goToStore();
    shopping.searchForBook("title: Continuous Delivery");
    shopping.selectBook("author: David Farley");

    shopping.addSelectedItemToShoppingBasket();
    shopping.checkOut("price: 20.00");

    shopping.assertItemPurchased("item: Continuous Delivery");
}

Đây không phải ý tưởng mới. Dave kể (video đăng ngày 21/10/2026) rằng họ đã xây một hệ thống phức tạp, tinh vi theo đúng cách này ở LMAX năm 2007, với hàng chục nghìn specification như vậy chạy trên mỗi commit.

11. Tách what khỏi how: đúng cái hợp đồng mà agent cần

Cái mới, theo Dave, là ai được lợi. Việc tách "cái gì" (what) khỏi "như thế nào" (how), vốn nằm sẵn trong cách tiếp cận này, hoá ra lại chính xác là cái hợp đồng (contract) mà một AI agent cần (nhận định của Dave, video đăng ngày 21/10/2026).

Agent khi đó có toàn quyền tự do về cách nó implement mọi thứ, nhưng không có chút tự do nào về việc hệ thống phải làm gì. Spec là fitness function của nó: thứ nó bắt buộc phải thoả mãn, và cũng là thứ dùng để đo nó. Và hai thứ đó là cùng một artifact (video đăng ngày 21/10/2026).

WHAT: hệ thống phải làm gìcon người giữ, agent không được đổi HOW: implement thế nàoagent toàn quyền tự do Executable spec = fitness function = thước đo
Hình 11.1Hợp đồng mà Dave mô tả: agent tự do hoàn toàn về how, không có tự do nào về what; executable spec vừa là thứ agent phải thoả mãn vừa là thứ dùng để đo nó (video đăng ngày 21/10/2026).

12. Phát triển phần mềm là một chuỗi phép dịch

Dave nói (video đăng ngày 21/10/2026) phát triển phần mềm xưa nay luôn là một phép dịch (translation). Một mong muốn mơ hồ (vague wish) trở thành một user story. Story trở thành một ví dụ cụ thể. Ví dụ trở thành executable specification, và specification trở thành phần mềm chạy được. Mỗi bước thêm vào độ chính xác. Và nếu bạn kẹt ở bước nào, điều đó nói với bạn một điều cụ thể và quan trọng.

Vòng dịch: Vague Wish, Story, Example, Executable Specification, Code and Tests, Working Software
Chuỗi dịch trên màn hình: Vague Wish, Story, Example, Executable Specification, rồi Code & Tests và Working Software.

Nếu bạn không nghĩ ra được một ví dụ, thì bạn chưa hiểu bài toán đủ rõ. Việc agent làm là bước cuối cùng. Con người điều khiển mọi thứ bằng cách làm chủ ba bước đầu (cách chia việc của Dave, video đăng ngày 21/10/2026).

Theo Dave (video đăng ngày 21/10/2026), đây là một thay đổi lớn, nhưng là thay đổi về trọng tâm (emphasis), không thật sự về bản chất (kind). Người làm phần mềm vốn dĩ luôn phải làm việc này. Nhiều team đã bỏ qua nó, viết code thẳng từ story, rồi trả giá về sau.

Giờ thì cái giá của việc bỏ qua đến sớm hơn, vì thứ viết ra code không hề biết bạn thật sự muốn nói gì (nhận định của Dave, video đăng ngày 21/10/2026).

13. Ba quy tắc thực hành

Dave nói: làm theo ba quy tắc thực hành sau và bạn sẽ có kết quả tốt hơn với lập trình có AI hỗ trợ (lời khuyên của anh trong video đăng ngày 21/10/2026).

Slide For Each Feature với ba quy tắc
"For Each Feature...": viết spec TRƯỚC khi agent viết code, chạy nó và xem nó fail, làm theo từng bước nhỏ (slide trong video đăng ngày 21/10/2026).

Quy tắc 1: viết spec trước khi agent bắt đầu. Mỗi lần một scenario. Xem nó fail. Rồi mới để agent làm nó pass. Theo Dave, "đỏ trước" (red first) không phải nghi thức cho có. Với một agent, màu đỏ là bằng chứng rằng specification của bạn có khả năng bắt được một câu trả lời sai (video đăng ngày 21/10/2026).

Quy tắc 2: giữ spec ngoài tầm với của agent. Theo Dave (video đăng ngày 21/10/2026), Kent Beck đang gặp khó trong việc ngăn AI agent xoá test để làm cho chúng pass. Emily Bache cũng kể về cùng thói quen tệ hại đó: agent xoá test đang fail thay vì sửa. Trong cách tiếp cận này, acceptance test là hợp đồng; chúng là chương trình. Hãy đặt chúng ở chỗ agent không sửa được, hoặc coi mọi thay đổi trên chúng là một thay đổi hợp đồng mà con người phải duyệt. Theo Dave, agent swarm của Bob Martin có hẳn một vai trò specifier riêng; Dave thì muốn vai trò đó là một con người, hoặc tối thiểu là có một con người ký duyệt output của nó.

Quy tắc 3: làm theo từng bước nhỏ. Một scenario: red, green, review, commit. Không phải vì agent cần bước nhỏ cho bản thân nó, mà vì bước nhỏ là cách ta phát hiện mình sai ở đâu trong lúc việc sai vẫn còn rẻ. Nếu một agent sinh ra 3.000 dòng từ một brief mơ hồ, nó đã bước một bước rất lớn, và code review ở quy mô đó sẽ không cho ta biết đó là một bước tốt hay một cú vấp. Ta cần một cách kiểm chứng chắc chắn hơn việc nhìn chằm chằm vào hàng nghìn dòng code do thứ khác viết (nhận định của Dave, video đăng ngày 21/10/2026).

14. Phản biện thứ nhất: waterfall đội lốt, và chuyện có đọc code hay không

Dave nói cách này vẫn là một dạng spec-driven development, và có vài phản biện với nó. Phản biện phổ biến nhất là đây chỉ là "waterfall khoác áo trench coat" (waterfall in a trench coat). Nếu bạn viết toàn bộ spec cho hệ thống ngay từ đầu thành một tài liệu markdown, thì đó là một lời phê bình công bằng (video đăng ngày 21/10/2026).

Nhưng với acceptance test-driven development thì điều đó hoàn toàn không đúng, theo Dave. Một scenario chỉ vài dòng. Bạn viết nó, nó chuyển đỏ, agent làm nó xanh, rồi bạn viết specification tiếp theo. Đó là lặp (iteration), và còn chi tiết hơn mức hầu hết các team đang làm được lúc video đăng (21/10/2026). Nhưng nó hoàn toàn khả thi, hoàn toàn thực tế, kể cả với những hệ thống rất lớn, rất phức tạp. Thực ra, theo anh, kiểu làm tăng dần (incrementalism) này là cách duy nhất trong thực tế để xây những hệ thống lớn và phức tạp.

Birgitta Böckeler từng băn khoăn rằng những gói việc nhỏ (small work packages) dường như đi ngược với ý tưởng của spec-driven development. Nhưng theo Dave (video đăng ngày 21/10/2026), gói việc nhỏ thật ra chính là toàn bộ ý tưởng đằng sau ATDD.

Theo Dave thuật lại (video đăng ngày 21/10/2026), Emily Bache đã khảo sát những người làm TDD đang làm việc với agent và thấy rằng phần lớn họ có đọc code, và lo lắng về món nợ nhận thức (cognitive debt) khi họ ngừng đọc. Bob Martin thì nói ông hoàn toàn không đọc. Dave nghĩ mình ở đâu đó giữa hai bên, và cho rằng đó là một chỗ đứng hợp lý.

Không đọc codeBob Martin Đọc khi rủi ro đángDave Farley Đọc codephần lớn người làm TDD(khảo sát của Emily Bache)
Hình 14.1Ba vị trí Dave nêu về chuyện đọc code agent viết; executable specification biến việc đọc code thành một lựa chọn chứ không còn là nghĩa vụ (video đăng ngày 21/10/2026).

Executable specification không ngăn ta đọc code. Nó biến việc đọc code thành một lựa chọn ta đưa ra khi rủi ro đáng để làm vậy, thay vì một nghĩa vụ tự áp lên mình là phải đọc từng dòng AI tạo ra. Dave cho rằng (video đăng ngày 21/10/2026) đây là khác biệt giữa một cách làm theo kịp tốc độ sinh code của AI và một cách làm không theo kịp.

15. Phản biện thứ hai: acceptance test chậm, giòn, ít assertion

Phản biện tiếp theo: acceptance test thì chậm, giòn (brittle) và ít assertion. Dave đồng ý một phần: acceptance test được làm tệ có thể mang tất cả những đặc điểm đó, và acceptance test làm tệ còn tệ hơn là không có. Martin Fowler nói đúng rằng chúng thường không có nhiều assertion, khiến ta có cảm giác an toàn giả tạo (theo Dave dẫn, video đăng ngày 21/10/2026). Và chắc chắn đúng là test gắn chặt vào UI sẽ vỡ mỗi lần UI thay đổi.

Câu trả lời của Dave: đừng gắn test chặt vào UI. Hãy làm như anh đã nói: test case, DSL, protocol driver. Đây chính là thứ mà cách tách bốn lớp sinh ra để sửa. Và đó cũng là lý do anh thấy giá trị của việc ghép acceptance testing với mutation testing, như cả Bob Martin lẫn Martin Fowler đều khuyên (theo Dave, video đăng ngày 21/10/2026). Nếu một mutant sống sót, specification của bạn có một lỗ hổng.

Thêm một điểm: "Nếu AI viết test thì đó không phải TDD", Ian Cooper nói vậy. Theo Dave, Ian đã nêu điểm này từ nhiều năm trước và ông ấy đúng. Đó là lý do một con người viết, hoặc ít nhất làm chủ và duyệt, các acceptance test. Agent có thể soạn nháp một cái, agent có thể soạn nháp mười cái, nhưng không cái nào được tính là specification cho tới khi một người, một con người hiểu bài toán, nói rằng nó là specification (video đăng ngày 21/10/2026).

Slide phân vai giữa con người và AI trong quy trình ATDD
Phân vai trên slide: con người viết acceptance test (spec); AI implement test theo mô hình bốn lớp, đưa test vào deployment pipeline và viết code cho test pass; test chạy trên mỗi commit (kiểu CD), nằm ngoài quyền kiểm soát của AI, và kiểm chứng kết quả (slide trong video đăng ngày 21/10/2026).

16. Ngành đang bắt kịp: spec phải chạy được

Dave tóm lại bằng một câu: spec-driven development là acceptance test-driven development nhưng bỏ đi phần chạy được (executable). Nhưng giờ thì, theo anh (video đăng ngày 21/10/2026), ngành dường như đang bắt kịp, từng bài blog một, và nhận ra rằng specification phải chạy được.

Anh nói mình mừng vì điều đó (video đăng ngày 21/10/2026). Anh thà để mọi người tới được một ý tưởng tốt bằng con đường khác còn hơn là không tới. Nhưng chẳng cần phát minh lại nó. Mô hình bốn lớp, ngôn ngữ của miền bài toán, kỷ luật "đỏ trước xanh" (red before green), việc tách what khỏi how: theo Dave, tất cả đã được hoàn thiện, đã được kiểm nghiệm ở quy mô lớn và đã được viết ra từ nhiều năm trước.

Chúng được thiết kế để điều khiển những hệ thống thay đổi ngay bên dưới ta, và để nói cho ta sự thật về chuyện gì đang diễn ra sau mỗi thay đổi nhỏ. Hoá ra, theo Dave, đó cũng chính xác là thứ ta cần để điều khiển một trợ lý lập trình AI (video đăng ngày 21/10/2026).

Vibe codingkhông có spec Spec markdownprose, không ai chạy Executable specfail cho tới khi đúng "The spec must be executable."
Hình 16.1Kết luận của Dave (video đăng ngày 21/10/2026): vibe coding chưa phải là mức tốt nhất ta làm được, một file markdown chứa spec cũng vậy; spec phải chạy được.

Theo Dave (video đăng ngày 21/10/2026), vibe coding không phải là mức tốt nhất mà chúng ta có thể làm được. Một file markdown chứa spec cũng không phải. Spec phải chạy được. Anh cảm ơn mọi người đã xem và chào tạm biệt.

Nguồn và liên kết 9 nguồn

  1. Tên gốc: The Industry Is Catching Up: The Only Way to Generate AI Code That Works
  2. Sự kiện: YouTube
  3. Video gốc: https://www.youtube.com/watch?v=EkH_uoybj8k youtube.com
  4. Kênh YouTube Modern Software Engineering (Dave Farley): youtube.com/channel/UCCfqyGl3nq_V0bo64CjZh8g youtube.com
  5. GitHub Spec Kit, bộ công cụ cho spec-driven development mà Dave nhắc tới (đọc ngày 25/10/2026): github.com/github/spec-kit github.com
  6. Kiro của Amazon (đọc ngày 25/10/2026): kiro.dev kiro.dev
  7. Bài công bố framework spec-driven development và registry của Tessl (đọc ngày 25/10/2026): tessl.io/blog/tessl-launches-spec-driven-framework-and-registry tessl.io
  8. Thoughtworks Technology Radar, mục Spec-driven development, xếp ở mức Assess từ số Nov 2025 (đọc ngày 25/10/2026): thoughtworks.com/radar/techniques/spec-driven-development thoughtworks.com
  9. Birgitta Böckeler, "Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl", bài có câu trích về agent không theo hết chỉ dẫn (đọc ngày 25/10/2026): martinfowler.com/articles/exploring-gen-ai/sdd-3-tools.html martinfowler.com