Bỏ qua điều hướng
Lập trình viên

Spec-driven development là gì? Cách đặc tả dẫn dắt AI

Spec-driven development là phương pháp dùng đặc tả chi tiết làm nguồn sự thật duy nhất dẫn dắt AI coding agent tạo code đúng, ít nợ kỹ thuật (technical debt).

Tuan Tran Van
9 phút đọc
Mục lục (9 phần)
  1. Spec-driven development là gì?
  2. Vì sao SDD xuất hiện: vibe coding và rủi ro nợ kỹ thuật
  3. Ba cấp độ của SDD: spec-first, spec-anchored, spec-as-source
  4. Một bản spec tốt gồm những gì?
  5. Quy trình SDD với AI coding agent
  6. Các công cụ SDD nổi bật
  7. Giới hạn và phản biện: Markdown Madness
  8. Khi nào nên dùng SDD?
  9. Tài liệu tham khảo

Viết và review code không còn là điểm nghẽn chính trong quy trình phát triển phần mềm hiện đại; vấn đề thực sự nằm ở sự mơ hồ khi giao tiếp với mô hình ngôn ngữ lớn (Large Language Model, LLM). Khi bạn dùng các công cụ như GitHub Copilot, Claude Code hay IBM Bob, việc chỉ dựa vào một prompt đơn lẻ thường cho kết quả thiếu ổn định. Spec-driven development (SDD) giải quyết đúng vấn đề đó. SDD là phương pháp viết một bản đặc tả (specification) chi tiết, được thống nhất và hoàn thiện trước khi bắt đầu viết code, đóng vai trò nguồn sự thật duy nhất (single source of truth) dẫn dắt AI agent.

Thay vì "vibe coding" — hy vọng AI tự hiểu ý đồ — SDD chuyển trọng tâm sang việc thiết kế các tài liệu kỹ thuật. Bạn không còn là người gõ phím thuần túy mà trở thành người điều phối các AI agent thông qua văn bản có cấu trúc. Cách làm này giữ được tính kỷ luật của kỹ thuật phần mềm truyền thống, trong khi vẫn tận dụng tốc độ của generative AI.

Bản đặc tả (spec) đóng vai trò bản thiết kế trung tâm, dẫn dắt AI coding agent sinh code cho một dự án phần mềm.

Spec-driven development là gì?

Spec-driven development (SDD) là phương pháp ưu tiên soạn thảo một bản đặc tả chi tiết trước khi AI tạo ra mã nguồn. Trong môi trường AI-assisted, spec là một ngôn ngữ chung có cấu trúc, hướng hành vi, giúp giảm tính không định hình (non-determinism) của LLM — không phải một tài liệu tĩnh nằm yên một chỗ. Đây cũng là điểm SDD kế thừa từ test-driven development (TDD) và behavior-driven development (BDD), nhưng đẩy yêu cầu lên mức đặc tả toàn bộ ý đồ triển khai.

Cần phân biệt rõ "spec" với "memory bank" (thường thấy ở các công cụ như Kiro hay Spec-kit). Nếu memory bank chứa các ngữ cảnh chung như quy ước coding style hay kiến trúc tổng thể của dự án, thì spec tập trung vào một task hoặc tính năng cụ thể. Một bản spec tốt là tài liệu có thể kiểm chứng (testable), mô tả chính xác hệ thống cần làm gì (intent) thay vì sa đà vào chuyện nó được triển khai ra sao (implementation).

Vì sao SDD xuất hiện: vibe coding và rủi ro nợ kỹ thuật

"Vibe coding" — lập trình dựa trên cảm hứng và các chu kỳ thử-sai với prompt ngắn — đang làm nợ kỹ thuật tích lũy rất nhanh. AI chỉ tốt bằng đúng chỉ dẫn mà nó nhận được. Khi thiếu một bản spec làm mỏ neo, codebase của bạn sẽ đối mặt với ba vấn đề quen thuộc:

  • Context drift: sửa bug ở module này nhưng vô tình làm hỏng tính năng ở module khác, do AI không nắm được logic toàn cục.
  • Fragmentation: mã nguồn mới không tuân theo các quy ước kiến trúc cũ, làm xói mòn khả năng bảo trì.
  • Chi phí vận hành: bạn có thể tốn hàng ngàn token và nhiều giờ để prompt đi prompt lại những lỗi mà một bản spec tốt đã ngăn được từ đầu.

Vibe coding không có spec dẫn tới nợ kỹ thuật: context drift, phân mảnh kiến trúc và chi phí vận hành tăng.

Hãy hình dung kịch bản áp lực deadline: bạn vội vã đẩy những thay đổi cuối cùng bằng AI cho một module Python. Code trông có vẻ chạy tốt, nhưng thực tế đã phơi bày vài lỗ hổng bảo mật (security vulnerabilities), xung đột dependency và bỏ quên hoàn toàn các edge case. SDD chính là chiếc phanh giữ cho quy trình đi đúng hướng.

Ba cấp độ của SDD: spec-first, spec-anchored, spec-as-source

SDD thường được phân loại thành ba cấp độ, dựa trên mức độ bảo trì và thẩm quyền của bản spec:

  1. Spec-first: bạn viết spec để AI tạo code cho một task, sau đó spec có thể bị bỏ rơi hoặc lạc hậu. Đây là điểm khởi đầu cho các team muốn thử SDD.
  2. Spec-anchored: spec tiến hóa song song với code. Khi requirements thay đổi, bạn cập nhật spec trước. Các automated test đóng vai trò cầu nối trong CI/CD, đảm bảo code luôn khớp với spec. Đây là mức thực dụng nhất cho phần lớn engineering team hiện nay.
  3. Spec-as-source: cấp độ cao nhất. Lập trình viên chỉ sửa spec, AI tự động cập nhật code, file code thường gắn tag @generated - Do not edit. Đổi lại, cấp độ này đòi hỏi pipeline kiểm soát cực kỳ chặt, vì AI vẫn mang tính không định hình.

Ba cấp độ của spec-driven development xếp trên một dải tăng dần: spec-first, spec-anchored, spec-as-source.

Một bản spec tốt gồm những gì?

Một bản spec chuẩn cần tập trung vào tính có thể kiểm chứng (testable), với bốn phần cốt lõi:

  • Overview: mục tiêu của tính năng.
  • Acceptance Criteria (AC): dùng định dạng Gherkin (Given/When/Then).
  • Data Schema: định nghĩa input/output rõ ràng.
  • Edge cases & Out of scope: giới hạn rõ những gì hệ thống không làm.

Bốn phần cốt lõi của một bản spec tốt: Overview, Acceptance Criteria, Data Schema, Edge cases và Out of scope.

Ví dụ một file SPEC.md cho tính năng đăng nhập:

markdown
# FEATURE: User Login
 
## OVERVIEW:
 
Cho phép người dùng đã đăng ký xác thực an toàn bằng email và password.
 
## ACCEPTANCE CRITERIA:
 
1. Form login nhận email và password.
2. GIVEN credentials hợp lệ, WHEN bấm login, THEN redirect tới dashboard.
3. GIVEN credentials không hợp lệ, WHEN bấm login, THEN hiển thị thông báo lỗi chung (không chỉ rõ field nào sai).
4. Lock tài khoản 15 phút sau 5 lần nhập sai liên tiếp.
5. Truyền password qua HTTPS — tuyệt đối không lưu dưới dạng plain text.
 
## EDGE CASES:
 
- Bắt lỗi field trống ở client-side trước khi submit.
- Session hết hạn phải redirect về trang login kèm thông báo.
- Form vẫn hoạt động nếu JavaScript bị tắt.
 
## OUT OF SCOPE:
 
- Social login (OAuth) và 2FA.
 
**Do not begin implementation until you have confirmed your understanding of the acceptance criteria.**

Quy trình SDD với AI coding agent

Một senior engineer thường dành phần lớn thời gian cho khâu lên kế hoạch để giảm thiểu việc phải làm đi làm lại. Quy trình thực thi gồm bốn bước:

  1. Lên kế hoạch: prompt về hành vi và ràng buộc; agent tạo ra Requirements → Design → Task List.
  2. Review: bạn kiểm tra design và task list. Nếu thiết kế kiến trúc chưa ổn, sửa spec ngay tại đây.
  3. Thực thi từng bước: chạy theo từng task nhỏ, độc lập (atomic task).
  4. Kiểm chứng: đối chiếu kết quả với AC.

Quy trình spec-driven development với AI coding agent: Requirements, Design, Tasks, Implementation kèm vòng review và kiểm chứng.

Việc chia nhỏ dự án thành các dự án con gần như là bắt buộc. Ví dụ, khi xây một interceptor cho AgentCore Gateway trên AWS, bạn nên tách thành Stack 1 (Lambda interceptor, dùng SAM để test cục bộ) và Stack 2/3 (Gateway và MCP server, dùng CloudFormation). Xây dựng từng bước như vậy giúp bạn dễ khoanh vùng lỗi ở từng tầng hạ tầng.

Các công cụ SDD nổi bật

Ba công cụ spec-driven development đặt trên dải từ spec-first tới spec-as-source: Kiro, Spec-kit và Tessl.

Ba công cụ dưới đây minh họa rõ dải cấp độ đó, mỗi công cụ nghiêng về một điểm khác nhau từ spec-first đến spec-as-source.

Kiro

Công cụ nhẹ, tích hợp trong VS Code, hợp cho task nhỏ. Quy trình tuyến tính: Requirements (user story/Gherkin) → Design → Tasks.

Spec-kit (GitHub)

CLI mạnh, xoay quanh khái niệm Constitution (hiến pháp) — tập nguyên tắc bất biến của dự án, đóng vai trò tệp quy tắc (rules file). Spec-kit tạo ra một workspace chuyên biệt kèm các checklist để theo dõi tiến độ và đảm bảo agent không vi phạm constitution.

Tessl

Tập trung vào spec-as-source. Tessl dùng các tag @generate@test để điều khiển agent. Điểm mạnh là khả năng đóng gói ngược (reverse engineering):

bash
tessl document --code src/auth.js

Lệnh này giúp bạn chuyển code cũ (brownfield) thành spec để bắt đầu quản lý theo SDD.

Giới hạn và phản biện: Markdown Madness

SDD có thể trở thành một phiên bản khác của mô hình Waterfall, với vài cái giá rõ rệt:

  • Quan liêu (bureaucracy): quy trình ba bước (Requirements → Design → Tasks) có thể quá nặng nề cho các thay đổi nhỏ.
  • Markdown Madness: lập trình viên mất phần lớn thời gian đọc các file Markdown dài dằng dặc, dài dòng, thay vì thực sự suy nghĩ về giải pháp.
  • Kiểm duyệt code hai lần (double code review): bạn phải review mã nguồn trong design spec, rồi review lại lần nữa code thực tế đã sinh ra — làm tăng gấp đôi chi phí kiểm duyệt.
  • Bẫy over-engineering: nếu bạn tốn ba tuần chỉ để tranh luận về tên một JSON key trong spec cho tính năng có thể bị xóa sau một tháng, thì bạn đã đi chệch mục đích.

Khi nào nên dùng SDD?

  • Nên dùng: dự án greenfield (làm mới từ đầu), các tính năng quan trọng về bảo mật (security-critical) như auth, payment, hoặc khi dùng các autonomous agent cần chỉ dẫn cực kỳ khắt khe.
  • Không nên dùng: bug fix cực nhỏ hoặc prototyping nhanh theo kiểu "Natural Language Development" (Agile + vibe). Với dự án cũ (brownfield), việc nạp ngữ cảnh từ một codebase khổng lồ vào spec vẫn là thách thức lớn về chi phí token lẫn độ chính xác.

Khi nào nên dùng SDD: hợp với dự án greenfield và tính năng security-critical; không hợp với bug fix nhỏ và dự án brownfield.

Nguyên tắc chốt lại: chi phí tinh chỉnh spec phải luôn thấp hơn chi phí sửa lỗi trong code. Nếu SDD làm bạn chậm lại mà không đổi lại được sự an toàn tương ứng, hãy giản lược nó.

Tài liệu tham khảo

Đọc tiếp

Chia sẻ bài viết

X / TwitterFacebookLinkedIn