Spec-driven development với Claude Code: spec đến verify

Bạn gõ một câu cho Claude Code, nó code ào ào trong ba phút, và kết quả gần đúng nhưng thiếu vài edge case, đặt tên lung tung, đi lệch ý bạn ở chỗ thứ tư. Càng dự án lớn, kiểu “vibe coding” này càng trôi.

Có một cách làm ngược lại: viết rõ bạn muốn gì trước, rồi mới để Claude build. Người ta gọi là spec-driven development. Bài này giải thích nó là gì, cách làm cụ thể trên Claude Code, khác gì TDD, và thành thật về chuyện khi nào nó đáng làm, khi nào chỉ tổ mất công.

TL;DR: Spec-driven development (SDD) là viết một bản đặc tả (ý định, ràng buộc, tiêu chí chấp nhận) TRƯỚC khi để AI sinh code. Trên Claude Code, vòng thực dụng là: spec → plan mode → todo → implement → verify. Mục tiêu là bớt lệch ý so với vibe coding. Đáng cho dự án lớn, có thể overkill cho prototype nhỏ.

Đáng làm nếu: dự án lớn dần, nhiều người hoặc nhiều agent, hoặc bạn hay phải sửa đi sửa lại vì Claude hiểu sai. Overkill nếu: prototype nhỏ, hoặc bạn còn chưa rõ mình muốn gì.

Spec-driven development là gì, và vì sao xuất hiện?

Trả lời nhanh: một phương pháp viết đặc tả có cấu trúc trước khi sinh dòng code nào, để bản đặc tả đóng vai trò nguồn chân lý duy nhất. Trong giới gọi nó là spec-driven development, viết tắt SDD.

Hình dung như xây nhà. Vibe coding là vừa xây vừa nghĩ, tới đâu hay tới đó. Spec-driven là vẽ bản thiết kế trước: bao nhiêu phòng, chịu lực ra sao, dùng vật liệu gì, rồi mới đổ móng. Bản vẽ không phải để khoe, nó là cái để thợ và chủ nhà nhìn vào mà thống nhất.

Vì sao phương pháp này nổi lên đúng lúc này? Vì AI đã hạ rào sinh code xuống rất thấp, ai cũng prompt được. Nhưng code AI sinh ra mà không có nền thường bị trôi context, vỡ kiến trúc, thiếu edge case. SDD ép phần “suy nghĩ khó” lên trước: bản spec như một hợp đồng để các agent bám theo cùng một thiết kế, thay vì mỗi lần đoán một kiểu. (Định nghĩa theo IBMMicrosoft Developer, truy cập 30/06/2026.)

Ba mức spec-driven: Spec-First, Spec-Anchored, Spec-as-Source

Không phải spec-driven nào cũng giống nhau. Theo Martin Fowler (truy cập 30/06/2026), có ba mức nghiêm ngặt tăng dần, bạn chọn mức hợp với dự án.

  • Spec-First. Viết một spec kỹ trước, code xong thì spec có thể không cập nhật nữa. Đây là mức nhẹ nhất, chủ yếu để tránh prompt khởi đầu cẩu thả. Hợp việc nhỏ, một lần.
  • Spec-Anchored. Spec là tài liệu sống suốt vòng đời dự án. Khi đổi tính năng, bạn sửa spec trước, rồi cập nhật code cho khớp. Đây là mức nhiều team thực sự dùng.
  • Spec-as-Source. Spec là artifact chính. Người chỉ sửa spec, còn AI lo sinh và chạy code. Mức cao nhất, gần như coi spec là “mã nguồn thật”.
Ba mức spec-driven: Spec-First, Spec-Anchored, Spec-as-Source

Với phần lớn người đọc bài này, Spec-Anchored là điểm cân bằng tốt: đủ kỷ luật để giữ hướng, không cứng tới mức biến mọi thay đổi nhỏ thành thủ tục.

Làm spec-driven với Claude Code: 5 bước

Trên Claude Code, spec-driven không cần tool đặc biệt nào, bạn dùng đúng những thứ đã có. Vòng thực dụng gồm năm bước, và cái hay là Claude Code hỗ trợ sẵn gần hết.

  1. Viết spec. Mô tả mục tiêu, ràng buộc, tiêu chí chấp nhận (acceptance criteria) vào một file. Có thể là spec.md riêng, hoặc đưa các quy ước dài hạn vào CLAUDE.md để Claude luôn đọc. Càng rõ “đúng nghĩa là gì”, Claude càng ít đoán.
  2. Plan. Dùng plan mode để Claude đề xuất kế hoạch dựa trên spec trước khi đụng vào code. Bạn đọc kế hoạch, chỉnh chỗ lệch, rồi mới cho chạy. Đây là chốt chặn rẻ nhất để bắt sai sớm.
  3. Todo. Với task dài, Claude tự chia thành danh sách todo và làm tuần tự. Bạn nhìn todo là biết nó đang ở đâu so với spec, dễ thấy chỗ nó định bỏ sót.
  4. Implement. Để Claude code theo kế hoạch. Vì đã có spec và plan, phần này ít bất ngờ hơn nhiều so với prompt thẳng.
  5. Verify. Đối chiếu kết quả với spec: chạy thử, chạy test, kiểm acceptance criteria. Chưa đạt thì quay lại sửa spec hoặc kế hoạch, không chấp nhận code “nhìn có vẻ đúng”. Bước này là nơi spec-driven trả công cho bạn.

Một spec gọn cho tính năng nhỏ không cần dài. Ví dụ một spec.md ba bốn dòng cũng đủ để Claude biết “đúng” nghĩa là gì:

# Spec: nút Export CSV cho trang báo cáo
Mục tiêu: thêm nút "Export CSV" ở /reports, tải báo cáo tháng hiện tại.
Ràng buộc: chỉ user đã đăng nhập; tên file dạng reports-YYYY-MM.csv.
Acceptance:
- [ ] Bấm nút tải đúng file CSV của tháng hiện tại
- [ ] User chưa đăng nhập bị chặn (trả 401)
- [ ] File có dòng header cột + ít nhất 1 dòng dữ liệu

Có ba dòng acceptance đó, plan mode lập kế hoạch sát hơn và bước verify có cái để đối chiếu, thay vì đoán “vậy là xong chưa”.

Năm bước spec-driven trên Claude Code: spec, plan mode, todo, implement, verify

Mình thấy giá trị lớn nhất nằm ở bước 1 và bước 5: ép mình nói rõ “đúng nghĩa là gì” trước, rồi kiểm lại đúng cái đó sau. Phần giữa, Claude lo gần hết. Muốn dựng vòng nhiều bước bài bản hơn, xem dynamic workflows trong Claude Code.

Khác gì TDD, và ghép với nhau thế nào?

Câu hỏi này hay gặp, và câu trả lời ngắn là: hai cái không loại trừ nhau, chúng giải hai phần khác nhau của cùng bài toán “làm sao chắc code đúng”.

  • TDD (test-driven development) viết test trước, rồi code cho test pass. Nó chứng minh code chạy đúng ở mức từng hành vi cụ thể.
  • Spec-driven viết spec (ý định, ràng buộc, tiêu chí) trước, rồi để agent build theo. Nó định nghĩa “xây cái gì” và “đúng nghĩa là gì” ở mức cao hơn test.
Spec-driven và TDD bổ sung nhau: spec định xây gì, test chứng minh đã đúng

Ghép lại rất tự nhiên: spec nói xây gì, test và bước verify chứng minh đã đúng spec chưa. Trên Claude Code, bạn có thể yêu cầu Claude viết test từ acceptance criteria trong spec, rồi dùng chính test đó làm bước verify. Đây cũng là tinh thần goal-driven trong Claude Code: định nghĩa thành công đo được, rồi lặp tới khi đạt.

Muốn ép vòng red-green-refactor một cách kỷ luật thay vì nhắc tay mỗi lần, có thể dùng một Claude Code skill có sẵn: skill tdd của Matt Pocock (cài bằng npx skills@latest add mattpocock/skills) bắt Claude viết test fail trước rồi mới code cho pass, làm từng “vertical slice” một. Đây là skill cộng đồng, không phải của Anthropic, nhưng đúng tinh thần “nhịp feedback là giới hạn tốc độ” mà bước verify hướng tới.

Spec-driven có thực sự đáng không?

Đây là phần mình muốn thành thật, vì SDD đang bị hype lẫn bị chê khá gắt, và cả hai phía đều có lý.

Phía ủng hộ không nhỏ. Andrew Ng cùng JetBrains ra hẳn một khóa “Spec-Driven Development with Coding Agents”. Nhiều dev trên r/vibecoding gọi nó là “cách duy nhất để scale”. Lập luận chính: spec giữ context qua nhiều phiên, cho nhiều agent bám cùng một thiết kế, và buộc làm rõ acceptance trước khi code.

Nhưng lời chê cũng đáng nghe. Allen Holub gọi spec-driven (kiểu AI) là “waterfall trá hình”, vì một bản spec đầy đủ trước khi làm thì gần như không bao giờ chính xác. Một dev khác, Jan-Niklas Wortmann, kể đúng cái bẫy: “hai tiếng viết spec, Claude khớp hoàn hảo trong ba phút, rồi nhận ra spec tả sai vấn đề”. SDD giả định bạn hiểu vấn đề TRƯỚC khi build, mà điều đó không phải lúc nào cũng đúng.

Khi nào spec-driven đáng làm và khi nào overkill

Theo mình, đáp án không phải “có” hay “không” mà là “khi nào”:

  • Đáng làm khi dự án lớn dần, có nhiều người hoặc nhiều agent, hoặc bạn đụng codebase legacy cần giữ ràng buộc. Lúc đó cái giá viết spec rẻ hơn cái giá để code trôi.
  • Overkill khi bạn làm prototype nhỏ, hoặc còn đang dò xem vấn đề thật là gì. Lúc đó viết spec to là tự khóa mình vào một hiểu lầm. Vibe coding để khám phá, rồi mới spec hóa khi đã rõ, là một đường hợp lý.

Sai lầm hay mắc khi spec-driven

Phần lớn thất bại với spec-driven không phải vì phương pháp sai, mà vì áp sai liều hoặc bỏ nửa chừng.

  • Viết spec quá to và quá cứng. Spec 10 trang cho một tính năng nhỏ là tự trói. Bắt đầu gọn, để spec lớn dần theo dự án (tinh thần Spec-Anchored).
  • Spec tả sai vấn đề mà không kiểm. Đây là bẫy “hai tiếng spec sai” ở trên. Trước khi viết spec dài, kiểm lại bạn có thật sự hiểu vấn đề chưa; với cái mơ hồ thì thử nhanh trước.
  • Viết spec rồi quên verify. Spec mà không có bước đối chiếu cuối thì chỉ là tài liệu đẹp. Bước 5 mới là chỗ nó trả công.
  • Nhầm spec-driven là waterfall. Không phải. Spec là tài liệu sống, sửa được khi hiểu biết thay đổi, không phải bản hợp đồng đóng băng từ đầu.

FAQ

Spec-driven khác TDD và BDD chỗ nào?
TDD viết test trước rồi code cho pass; BDD mô tả hành vi theo ngôn ngữ nghiệp vụ. Spec-driven ở mức cao hơn: viết đặc tả ý định, ràng buộc, tiêu chí chấp nhận trước khi build. Chúng bổ sung nhau: spec định “xây gì”, test/BDD chứng minh “đúng chưa”.

Có cần dùng spec-kit không?
Không bắt buộc. GitHub spec-kit là một toolkit mã nguồn mở giúp dựng quy trình spec, nhưng spec-driven là một cách làm, không phải một tool cụ thể. Trên Claude Code bạn làm được bằng file spec, plan mode và todo có sẵn.

Spec viết ở đâu?
Tùy phạm vi. Quy ước dài hạn của dự án thì để trong CLAUDE.md để Claude luôn đọc. Spec cho một tính năng cụ thể thì để một file riêng như spec.md rồi trỏ Claude tới nó.

Dự án nhỏ có nên spec-driven không?
Thường là không cần mức nặng. Một spec ngắn vài dòng (mục tiêu + 2-3 tiêu chí chấp nhận) đã đủ ích cho việc nhỏ; viết cả tài liệu dài cho prototype là overkill.

Plan mode có phải spec-driven không?
Plan mode là một bước trong đó, không phải toàn bộ. Spec-driven bắt đầu từ việc viết spec; plan mode là chỗ Claude biến spec thành kế hoạch trước khi code. Thiếu bước viết spec thì plan mode chỉ là kế hoạch cho một prompt, chưa phải spec-driven.

Kết luận

Spec-driven development, gọn lại, là chịu khó nói rõ “đúng nghĩa là gì” trước khi để Claude code, rồi kiểm lại đúng cái đó sau. Trên Claude Code, vòng spec → plan mode → todo → implement → verify dùng đúng những công cụ bạn đã có.

Nhưng đừng theo nó như một tín điều. Nó đáng cho dự án lớn, đa-agent, hoặc legacy; có thể thừa cho prototype nhỏ hay khi bạn còn chưa rõ vấn đề. Chọn liều theo dự án, giữ spec sống chứ đừng đóng băng, và đừng bao giờ bỏ bước verify.

Muốn đi sâu phần cơ chế, đọc plan mode trong Claude Code cho bước plan, và dynamic workflows khi bạn muốn dựng vòng nhiều bước tự động.



Similar Posts