---
title: "Phát triển theo đặc tả: viết đặc tả trước khi để AI làm"
url: https://www.thinnd.site/ky-thuat/phat-trien-theo-dac-ta/
language: vi
author: "Nhu Duy Thin (Thinnd)"
published: 2026-10-29
updated: 2026-10-29
section: "Kỹ thuật phần mềm"
tags: ["spec-driven development", "đặc tả", "AI agent", "quy trình", "Spec Kit", "Kiro"]
summary: "Phát triển theo đặc tả là viết ra hành vi mong muốn của một tính năng trước, rồi để AI làm dựa trên đó. Martin Fowler chia ba mức: viết đặc tả trước rồi có thể bỏ (spec-first), giữ đặc tả để bảo trì (spec-anchored), và coi đặc tả là nguồn chính còn mã chỉ là sản phẩm sinh ra (spec-as-source). Ông cũng nêu hạn chế thực tế: cùng một quy trình nặng cho việc nhỏ, nhiều tệp lặp lại khó duyệt, và tác nhân vẫn có lúc bỏ qua đặc tả. Cách dùng thực dụng là đặc tả nhẹ cho việc vừa và lớn, bỏ qua cho việc nhỏ."
license: "Cite with the author name and the canonical URL above."
---

# Phát triển theo đặc tả: viết đặc tả trước khi để AI làm

> Dành cho lập trình viên và người làm sản phẩm đang dùng AI để viết code. Từ kỹ thuật nào cũng có giải thích ngắn.
>
> Phần mô tả ba mức độ, ba công cụ và các hạn chế dựa vào bài phân tích của Martin Fowler (mình đọc trực tiếp). Phần "đặc tả nhẹ năm mục" và ví dụ là **gợi ý của mình**, chưa được kiểm chứng trên nhiều dự án. Ví dụ "tính năng hoàn tiền" được dựng lại cho dễ hình dung.

---

## Tóm tắt nhanh

- **Phát triển theo đặc tả (spec-driven development, SDD)** là viết trước điều cần làm, rồi để AI làm dựa trên đó.
- Martin Fowler chia **ba mức**: **spec-first** (viết trước, có thể bỏ sau), **spec-anchored** (giữ lại để bảo trì), **spec-as-source** (chỉ sửa đặc tả, mã là sản phẩm sinh ra).
- Hầu hết cách làm hiện nay mới ở mức **spec-first**.
- Có **hạn chế thật**: quy trình nặng cho việc nhỏ, nhiều tệp lặp lại khó duyệt, và tác nhân vẫn có lúc bỏ qua đặc tả.
- Cách thực dụng: **đặc tả nhẹ năm mục** cho việc vừa và lớn, bỏ qua cho việc nhỏ.

---

## Từ khó, nói dễ

| Thuật ngữ | Nói dễ hiểu |
|---|---|
| **Đặc tả (spec)** | Bản mô tả có cấu trúc về hành vi mong muốn của một tính năng, viết bằng ngôn ngữ thường. |
| **Tác nhân lập trình (coding agent)** | AI không chỉ trả lời mà còn tự đọc, sửa tệp và chạy lệnh để làm việc. |
| **Tiêu chí chấp nhận (acceptance criteria)** | Những điều phải đúng để coi tính năng là xong, thường viết thành ví dụ cụ thể. |
| **Bộ nhớ chung (memory bank)** | Tệp ngữ cảnh áp dụng cho mọi lần làm việc, như quy tắc và mô tả dự án. |
| **Mã có sẵn (brownfield)** | Dự án đã chạy lâu, khác với dự án mới tinh. |
| **Không xác định (non-deterministic)** | Cùng đầu vào nhưng mỗi lần ra một kết quả hơi khác. |

---

## 1. Vì sao có chuyện đặc tả

Khi nhờ AI bằng một câu ngắn, bạn trao cho nó quyền **tự điền những chỗ trống**. Với việc nhỏ thì không sao. Với việc lớn hơn, chỗ trống nào cũng là một lần AI đoán, và bạn chỉ biết nó đoán sai khi đọc kết quả.

Một ví dụ từ chính blog này: khi người dùng báo "tính năng tìm kiếm không hoạt động", agent kiểm tra phần logic và thấy đúng, trong khi vấn đề thật là kết quả nằm bên dưới màn hình đầu nên người dùng không thấy gì thay đổi (xem bài [Ba tiếng làm việc với một AI agent](https://www.thinnd.site/ky-su/nhat-ky-ai-agent-du-an-that/)). Nếu có một dòng đặc tả như "gõ xong, kết quả phải hiện ra mà không phải cuộn", lỗi đó **có thể** đã được bắt sớm. Mình nói "có thể" vì đó là suy luận sau sự việc, không phải kết quả thử nghiệm.

Ý tưởng của phát triển theo đặc tả là biến những dòng như vậy thành một bước chính thức **trước khi** để AI làm.

---

## 2. Ba mức độ

Theo Martin Fowler:

| Mức | Ý nghĩa | Đặc tả sau khi làm xong |
|---|---|---|
| **Spec-first** | Viết đặc tả trước, dùng nó để hướng dẫn việc làm | Có thể bỏ |
| **Spec-anchored** | Giữ đặc tả lại, dùng nó để phát triển và bảo trì tính năng | Giữ và cập nhật |
| **Spec-as-source** | Đặc tả là sản phẩm chính, con người chỉ sửa đặc tả, không sửa mã | Là nguồn, mã được sinh ra |

Ông ghi nhận phần lớn các cách làm SDD hiện nay chỉ ở mức **spec-first**, và kế hoạch giữ đặc tả về lâu dài thường còn mơ hồ.

Ông cũng phân biệt đặc tả với **bộ nhớ chung**: bộ nhớ chung (quy tắc, mô tả sản phẩm và mã) áp dụng cho mọi phiên làm việc, còn đặc tả chỉ áp dụng cho tính năng đang làm hoặc đang đổi. Vì vậy tệp như AGENTS.md (xem bài [Sổ tay cho AI](https://www.thinnd.site/ky-thuat/so-tay-cho-ai-agents-md/)) và đặc tả bổ sung cho nhau.

---

## 3. Ba công cụ, theo bài của Fowler

Fowler xem xét ba công cụ. Mô tả dưới đây là phần tóm tắt của mình.

| Công cụ | Quy trình | Ghi chú của Fowler |
|---|---|---|
| **Kiro** | Yêu cầu, thiết kế, việc cần làm. Có tính năng "steering" làm bộ nhớ chung | Nhẹ hơn, chủ yếu spec-first |
| **Spec Kit (GitHub)** | Nguyên tắc chung, đặc tả, kế hoạch, việc cần làm, rồi triển khai, mỗi bước ra tệp Markdown | GitHub nói hướng tới spec-anchored, nhưng Fowler thấy nó vẫn là spec-first vì tạo một nhánh cho mỗi đặc tả |
| **Tessl (bản thử riêng)** | Nhắm rõ tới spec-anchored và thử spec-as-source. Tệp sinh ra được đánh dấu là không sửa tay | Fowler thấy kết quả không xác định từ cùng một đặc tả |

Các công cụ này mới và đổi nhanh, nên đừng coi mô tả trên là bản chốt.

---

## 4. Những quan sát và lời phê bình của Fowler

Điều mình thấy đáng đọc nhất là Fowler **không chỉ ca ngợi**. Ông nêu ra:

- **Một quy trình cho mọi cỡ việc.** Kiro biến một lỗi nhỏ thành bốn câu chuyện người dùng và 16 tiêu chí chấp nhận. Spec Kit làm ông thấy là quá tay cho một tính năng cỡ vừa trong mã có sẵn, nơi viết thẳng với AI sẽ nhanh và dễ kiểm soát hơn.
- **Gánh nặng duyệt.** Spec Kit sinh nhiều tệp Markdown lặp lại, dài dòng, mệt để duyệt. Ông thà duyệt mã.
- **Cảm giác kiểm soát giả.** Tác nhân có lúc bỏ qua nội dung đặc tả, như tạo lại một lớp đã có dù bước nghiên cứu đã ghi nó, hoặc áp dụng quá tay các nguyên tắc chung.
- **Mã có sẵn khó hơn.** Hai trong ba công cụ khó đưa vào dự án đã chạy, nên khó đánh giá.
- **Ranh giới chức năng và kỹ thuật không rõ** trong thực tế.
- **"Spec" đang bị dùng lỏng.** Từ này có nguy cơ thành đồng nghĩa với "lời nhắc chi tiết".
- **Bài học từ phát triển theo mô hình (MDD).** MDD từng không thành công cho ứng dụng kinh doanh. Fowler lo spec-as-source thừa hưởng cả sự cứng nhắc của MDD lẫn tính không xác định của mô hình ngôn ngữ.

Dù vậy, ông vẫn thấy **suy nghĩ theo kiểu spec-first có giá trị**: viết cẩn thận đặc tả trước khi nhờ tác nhân thường có ích. Cái ông nghi ngờ là các quy trình nặng nhiều tệp.

---

## 5. Khi nào đáng dùng, khi nào không

*Bảng này dựa trên lời của Fowler cộng với suy luận của mình.*

| Tình huống | Đặc tả | Vì sao |
|---|---|---|
| Sửa một lỗi nhỏ | **Không** | Công viết đặc tả vượt xa công làm |
| Thay đổi cỡ vừa trong mã có sẵn | **Nhẹ**, hoặc không | Duyệt nhiều tài liệu có thể tốn hơn viết thẳng với AI |
| Tính năng mới cỡ vừa đến lớn | **Có**, mức nhẹ | Nhiều chỗ trống cho AI đoán, nên chốt trước |
| Thay đổi có rủi ro cao (tiền, quyền, dữ liệu cá nhân) | **Có**, kèm tiêu chí chấp nhận rõ | Cần viết ra điều không được xảy ra |
| Vấn đề lớn, chưa rõ | **Chưa**, cần tìm hiểu người dùng trước | Đặc tả không thay được việc hiểu vấn đề |
| Cần kiểm soát từng bước nhỏ | **Ít**, làm từng bước | Đặc tả lớn có thể đi ngược cách làm lặp nhỏ |

---

## 6. Mẫu đặc tả nhẹ năm mục

*Gợi ý của mình, không phải chuẩn của công cụ nào.* Một tệp ngắn, một trang, đặt cạnh mã.

1. **Vì sao.** Một hai câu về vấn đề và người dùng. Không phải giải pháp.
2. **Hành vi mong muốn.** Mô tả điều người dùng thấy và làm, bằng câu thường.
3. **Không làm.** Những thứ cố ý để ngoài phạm vi. Mục này chặn AI "làm thêm".
4. **Ví dụ chấp nhận được.** Ba đến sáu ví dụ cụ thể: đầu vào, kết quả mong đợi, kể cả ca lạ (rỗng, rất dài, sai kiểu).
5. **Câu hỏi còn mở.** Điều bạn chưa biết. Bắt AI hỏi lại thay vì đoán.

**Ví dụ minh họa (dựng lại): tính năng hoàn tiền.**

- **Vì sao:** Khách hủy đơn muốn nhận lại tiền mà không phải gọi hỗ trợ.
- **Hành vi:** Trong trang đơn hàng, đơn chưa giao có nút "Hủy và hoàn tiền". Bấm xong, khách thấy trạng thái "đang hoàn tiền" và nhận email.
- **Không làm:** Hoàn tiền một phần, đơn đã giao, đổi sang phương thức thanh toán khác.
- **Ví dụ chấp nhận:** đơn chưa giao, 200 nghìn, hoàn đủ. Đơn đã giao: nút không hiện. Bấm hai lần liên tiếp: chỉ hoàn một lần. Cổng thanh toán lỗi: hiện thông báo, không đổi trạng thái đơn.
- **Câu hỏi mở:** Hoàn về đâu nếu thẻ đã hết hạn? Ai duyệt nếu quá một triệu?

Ba ví dụ chấp nhận ở giữa chính là thứ **kiểm thử** có thể bám theo, và là thứ người duyệt dùng để đối chiếu. Chúng cũng nối với danh sách [duyệt code do AI viết](https://www.thinnd.site/ky-thuat/duyet-code-do-ai-viet/): điểm 1 (khớp yêu cầu) và điểm 9 (test kiểm gì).

---

## 7. Quy trình bốn bước dùng được ngay

1. **Viết đặc tả nhẹ** (khoảng 10 đến 20 phút). Nhờ AI hỏi lại những chỗ mơ hồ, nhưng **bạn** quyết định.
2. **Cho AI lập kế hoạch ngắn** dựa trên đặc tả, và đọc kế hoạch trước khi cho làm.
3. **Làm từng bước nhỏ.** Mỗi bước một thay đổi nhỏ, chạy thử, rồi đối chiếu ví dụ chấp nhận.
4. **Cập nhật hoặc bỏ đặc tả.** Nếu tính năng sống lâu, sửa đặc tả khi hành vi đổi. Nếu không, xóa đi để khỏi lỗi thời.

Điểm 3 và 4 khớp với lo ngại của Fowler: **giữ bước nhỏ và nhớ rằng đặc tả cũng có thể cũ**.

---

## 8. Nhìn cân bằng

- **Phần lớn bằng chứng là bài phân tích của một người.** Fowler dùng thử các công cụ trên một số việc, không phải khảo sát lớn. Mình chưa thấy nghiên cứu độc lập đo hiệu quả của SDD.
- **Các công cụ đổi nhanh.** Mô tả Kiro, Spec Kit, Tessl có thể đã khác khi bạn đọc. Các nguồn thứ cấp còn ghi khác nhau về ngày ra mắt và số liệu mức dùng, nên mình không trích.
- **"Spec" có nhiều nghĩa.** Đừng nhầm đặc tả với lời nhắc dài hay với tài liệu thiết kế.
- **Đặc tả không thay được việc hiểu người dùng.** Nó giúp chốt điều cần làm, không giúp tìm ra điều đáng làm.
- **Mẫu năm mục là gợi ý của mình**, chưa kiểm chứng trên nhiều nhóm.

---

## 9. Kết luận

Viết đặc tả trước không phải thủ tục mới cho vui. Nó là cách **chốt những chỗ trống mà AI sẽ tự điền**. Nhưng như Fowler nhắc, đừng dùng búa tạ cho việc nhỏ: một đặc tả nhẹ, vài ví dụ chấp nhận, và từng bước nhỏ thường đủ.

Việc nhỏ làm ngay: chọn một tính năng bạn định nhờ AI làm trong tuần này, viết năm mục trên trong mười phút, rồi so sánh kết quả với cách bạn thường làm.

---

## Nguồn tham khảo

- [Martin Fowler: Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl](https://www.martinfowler.com/articles/exploring-gen-ai/sdd-3-tools.html)
- [GitHub Spec Kit](https://github.github.com/spec-kit/)
- Bài liên quan trong blog: [Sổ tay cho AI (AGENTS.md)](https://www.thinnd.site/ky-thuat/so-tay-cho-ai-agents-md/), [Duyệt code do AI viết](https://www.thinnd.site/ky-thuat/duyet-code-do-ai-viet/), [Ba tiếng làm việc với một AI agent trên dự án thật](https://www.thinnd.site/ky-su/nhat-ky-ai-agent-du-an-that/)
