Khám phá Learn Stream About Jokes
INSIDER Tony's Friends — Insider — ~2 playbook/tuần, Discord riêng, tài nguyên dựng sẵn Tham gia →
Bài viết

Vibe coding cần document tốt, nhưng thế nào là tốt?

Bạn đang ở level nào trong vibe coding? Request rồi fix theo cảm giác, hay đã có documentation chuẩn để AI hiểu đúng từ đầu?

Bạn đã bao giờ dùng Cursor hay Claude Code để hỏi về codebase, nhưng nó trả lời sai hoặc không tìm được thông tin? Bạn nghĩ AI kém, nhưng thực ra vấn đề nằm ở chỗ khác: documentation của bạn không được viết cho AI đọc.

Mình đã trải qua hành trình này. Từ việc code theo kiểu “prompt rồi fix theo observation”, đến viết doc nhưng không có chuẩn, và cuối cùng tìm ra cách viết documentation mà cả người và AI đều có thể tìm kiếm, hiểu, và làm việc hiệu quả.


Ba level viết doc cho context của vibe coder

Trước khi đi vào chi tiết, hãy nhìn lại ba level mà hầu hết vibe coder đều trải qua:

Level 1: prompt rồi fix theo observation

Đây là level phổ biến nhất. Bạn prompt AI, nó generate code, bạn chạy thử, thấy lỗi, fix lại. Không có documentation, không có context rõ ràng. Mỗi lần prompt là một cuộc conversation mới, AI không biết gì về kiến trúc (architecture) của bạn.

Vấn đề ở đây là AI phải đoán context mỗi lần. Kết quả phụ thuộc vào việc bạn mô tả vấn đề tốt đến đâu. Và khi project lớn lên, việc giải thích lại từ đầu trở nên rất mệt.

Level 2: viết doc nhưng không có chuẩn

Bạn bắt đầu viết README, thêm comments, có thể tạo vài file markdown giải thích hệ thống. Tốt hơn level 1, nhưng vẫn có vấn đề.

Documentation của bạn được viết cho người đọc: văn xuôi dài, kiểu kể chuyện (narrative style), thông tin rải rác. AI đọc nhưng không trích xuất (extract) được thông tin một cách đáng tin cậy. Bạn có docs, nhưng AI vẫn trả lời sai vì nó không tìm được hoặc không parse được thông tin cần thiết.

Level 3: structured docs cho cả người và AI

Đây là level mà bài viết này hướng đến. Documentation được thiết kế với hai mục tiêu: người có thể đọc và hiểu nhanh, AI có thể điều hướng (navigate) và trích xuất thông tin chính xác.

Sự khác biệt không nằm ở việc viết nhiều hay ít, mà ở cấu trúc. Khi docs có structure nhất quán, AI biết chỗ nào tìm gì, và bạn cũng vậy.


Tại sao cấu trúc quan trọng với AI

Hãy hiểu cách LLM đọc documentation. Nó không đọc như người, từ trên xuống, theo dòng. LLM xử lý tất cả tokens cùng lúc thông qua cơ chế attention.

Điều này có những hệ quả quan trọng:

Attention weights không đều

LLM gán trọng số attention khác nhau cho từng phần tử. Headings, tables, code blocks nhận được attention cao hơn văn xuôi thông thường. Nghĩa là nếu bạn chôn thông tin quan trọng trong một đoạn văn dài, khả năng AI bỏ sót nó cao hơn so với khi bạn đặt nó trong table hoặc heading.

ElementMức attention
# HeadingsRất cao
TablesCao
Code blocksCao
Bold textTrung bình-cao
Văn xuôi thườngThấp

Token efficiency rất quan trọng

Cùng một thông tin, cách trình bày khác nhau tốn số tokens khác nhau. Ví dụ:

Kiểu văn xuôi (47 tokens):

Queue có max batch size là 1, nghĩa là xử lý từng message một. Timeout là 5 giây, retry tối đa 2 lần trước khi vào dead letter queue vilab-ai-dlq.

Kiểu table (28 tokens):

ConfigValue
Max batch size1
Timeout5s
Max retries2
DLQvilab-ai-dlq

Kiểu table tiết kiệm 40% tokens và AI trích xuất chính xác hơn vì structure rõ ràng.

Vấn đề chunking

Khi docs quá dài, các hệ thống RAG phải chia nhỏ (chunk) chúng. Nếu bạn có một doc khổng lồ 10,000 tokens, nó sẽ bị cắt thành nhiều chunks, và context có thể bị mất ở chỗ cắt.

Với cách tiếp cận này, mỗi doc được giữ ở 800-1500 tokens, vừa đủ để một chunk chứa trọn vẹn một domain, không bị cắt ngang.


Công thức chia domain

Câu hỏi lớn nhất khi viết documentation là: nên chia thành bao nhiêu file? Nội dung nào thuộc file nào?

Sau khi phân tích nhiều hệ thống documentation tốt, mình rút ra công thức:

Domain = Responsibility × Change-frequency × Dependency-level

Responsibility (trách nhiệm): Mỗi document chỉ chịu trách nhiệm MỘT việc. Test đơn giản: bạn có thể mô tả doc đó trong một câu không có chữ “và” không?

✅ “Document này giải thích Telegram bot interface” ❌ “Document này giải thích API và bot và database schema”

Change-frequency (tần suất thay đổi): Những thứ thay đổi cùng nhau nên ở cùng document. Nếu mỗi lần sửa authentication bạn cũng phải sửa routing, chúng nên ở cùng doc hoặc ít nhất cùng section.

Dependency-level (mức phụ thuộc): Số thứ tự của doc thể hiện mức phụ thuộc. Số nhỏ là nền tảng, nếu nó hỏng, nhiều thứ khác hỏng theo. Số lớn là bề mặt, hỏng thì chỉ ảnh hưởng một phần nhỏ.


Cấu trúc một document

Mỗi document nên theo skeleton này:

# NN-domain-name

{2-3 câu overview: đây là gì, tại sao nó tồn tại}

## System Diagram

{Mermaid diagram visualize concept chính}

## 1. First Section

{Giải thích với tables cho data/config}

## 2. Second Section

{Tiếp tục với numbered sections}

## File Reference

| File | Purpose |
|------|---------|
| `src/module.ts` | Main implementation |

## Cross-References

| Doc | Relation |
|-----|----------|
| [00-architecture](00-architecture.md) | Parent context |
| [03-related](03-related.md) | Uses this module |

Tại sao thứ tự này? Vì nó trả lời các câu hỏi theo thứ tự tự nhiên:

  1. Overview → Đây là gì?
  2. Diagram → Nó trông như thế nào?
  3. Sections → Nó hoạt động ra sao?
  4. File Reference → Code ở đâu?
  5. Cross-References → Liên quan đến gì?

Người đọc có thể scan nhanh để tìm phần cần. AI có structure dự đoán được để điều hướng.


Ví dụ thực tế: cấu trúc docs cho một project

Để cụ thể hơn, đây là cấu trúc docs mình dùng cho một content platform:

docs/
├── 00-architecture-overview.md
├── 01-content-pipeline.md
├── 02-ingest-worker.md
├── 03-telegram-bot.md
├── 04-ai-providers.md
├── 05-content-collections.md
├── 06-media-storage.md
├── 07-astro-frontend.md
├── 08-deployment.md
└── SITE.md (index)

Mỗi doc có responsibility rõ ràng:

DocResponsibility
00-architectureHình dáng hệ thống, cách các component kết nối
01-content-pipelineLuồng từ input đến published content
02-ingest-workerCloudflare Worker xử lý incoming content
03-telegram-botBot interface và commands
04-ai-providersAI service abstraction (Gemini, MiniMax)
05-content-collectionsAstro content schemas
06-media-storageR2 storage và CDN
07-astro-frontendFrontend routing và components
08-deploymentCI/CD và environments

Số thứ tự thể hiện dependency. Architecture (00) là foundation, mọi thứ phụ thuộc vào nó. Deployment (08) là surface, nó phụ thuộc vào mọi thứ khác.


Ví dụ document hoàn chỉnh

Đây là một document mẫu:

# 02-ingest-worker

Cloudflare Worker xử lý content ingestion: nhận URLs/text,
fetch content, generate AI recap, upload media, push to GitHub.

## System Diagram

flowchart TB
    Input[Telegram/API] --> Router[HTTP Router]
    Router --> Stream[Stream Handler]
    Stream --> Fetch[Content Fetcher]
    Fetch --> AI[AI Recap]
    AI --> Media[R2 Upload]
    Media --> GitHub[Push MDX]
    GitHub --> Queue[Async Queue]

## 1. HTTP Routes

| Route | Method | Purpose |
|-------|--------|---------|
| `/ingest` | POST | Main ingestion endpoint |
| `/telegram` | POST | Telegram webhook |
| `/health` | GET | Health check |

## 2. Content Fetching

Worker fetches content từ nhiều nguồn:

| Source | Method | Module |
|--------|--------|--------|
| Websites | Defuddle API | `stream.ts` |
| GitHub repos | GitHub API | `stream.ts` |
| YouTube | Windmill | `stream.ts` |
| PDFs | unpdf | `pdf.ts` |

## 3. Queue Processing

| Config | Value |
|--------|-------|
| Max batch size | 1 |
| Timeout | 15 min |
| Max retries | 2 |
| DLQ | `vilab-ai-dlq` |

## File Reference

| File | Purpose |
|------|---------|
| `src/index.ts` | HTTP router, orchestration |
| `src/stream.ts` | URL fetching, recap flow |
| `src/ai.ts` | AI provider abstraction |
| `src/queue.ts` | Queue consumer |

## Cross-References

| Doc | Relation |
|-----|----------|
| [01-content-pipeline](01-content-pipeline.md) | Parent flow |
| [03-telegram-bot](03-telegram-bot.md) | Input source |
| [04-ai-providers](04-ai-providers.md) | AI services used |

Document này khoảng 1000 tokens, vừa đủ cho một chunk. Người đọc scan được nhanh. AI trích xuất được chính xác routes, configs, file locations.


Khi không biết nội dung thuộc doc nào

Đôi khi bạn có một đoạn thông tin và không chắc nó thuộc doc nào. Đây là bốn câu hỏi giúp quyết định:

Change Question: “Nếu mình đổi X, mình có phải đổi Y không?” Nếu có, X và Y nên ở cùng doc.

Break Question: “Nếu X hỏng, những gì khác sẽ hỏng?” Điều này xác định số thứ tự, càng nhiều thứ hỏng theo, số càng nhỏ.

Explain Question: “Mình có thể giải thích concept này trong 3 phút không?” Nếu không, có thể cần chia nhỏ.

Find Question: “Nếu ai đó cần tìm thông tin này, họ sẽ tìm ở đâu?” Document nên match mental model của người tìm.


Những anti-patterns cần tránh

Một số cách tổ chức documentation phổ biến nhưng không hiệu quả:

Tổ chức theo file type: models.md, controllers.md, services.md. Vấn đề là một feature thường span nhiều file types, nên đọc docs cũng phải nhảy qua lại.

Sắp xếp theo alphabet: A-Z không có learning path. Người mới không biết bắt đầu từ đâu.

Một mega-doc: Mọi thứ trong README.md. Không thể tìm, không thể chunk properly.

Quá nhiều văn xuôi: Paragraphs dài với config values chôn bên trong. Khó scan, AI khó trích xuất.

Không cross-reference: Mỗi doc là một hòn đảo. Không có đường điều hướng.


Triển khai: 5 bước

Nếu bạn muốn áp dụng cách tiếp cận này cho project của mình:

Bước 1: Inventory

Liệt kê tất cả concepts trong system. Không cần tổ chức, chỉ cần list:

  • HTTP routing
  • Authentication
  • Database models
  • External APIs
  • Background jobs
  • Deployment

Bước 2: Cluster

Nhóm theo responsibility. Những thứ thay đổi cùng nhau, phục vụ cùng mục đích → cùng cluster.

Bước 3: Order

Sắp xếp clusters theo dependency. Foundation trước, surface sau.

Bước 4: Write

Với mỗi cluster, viết một doc theo skeleton:

  1. Overview 2-3 câu
  2. Mermaid diagram
  3. Numbered sections với tables
  4. File Reference
  5. Cross-References

Bước 5: Validate

Checklist:

  • Mỗi doc có overview?
  • Mỗi doc có diagram?
  • Config/data trong tables, không trong văn xuôi?
  • Tất cả có File Reference?
  • Tất cả có Cross-References?
  • Index file updated?

Kết quả thực tế

Sau khi áp dụng cách viết này, mình thấy sự khác biệt rõ rệt khi làm việc với AI agents:

Trước: “Hãy thêm một route mới vào API” → AI hỏi lại: “API nào? Structure như thế nào? Authentication ra sao?”

Sau: “Hãy thêm một route mới vào API” → AI đọc 02-ingest-worker.md, thấy existing routes trong table, patterns trong File Reference, và generate code đúng conventions.

Không phải AI thông minh hơn. Mà là documentation cho nó context cần thiết để làm việc hiệu quả.


Kết luận

Vibe coding không chỉ là biết prompt. Đó là biết tạo ra môi trường mà AI có thể làm việc tốt nhất.

Documentation là phần quan trọng của môi trường đó. Viết cho AI đọc được không có nghĩa là viết khô khan hay robotic. Nó có nghĩa là viết có structure, nhất quán, và dự đoán được.

Công thức để nhớ:

Domain = Responsibility × Change-frequency × Dependency-level

Mỗi doc một responsibility. Những thứ thay đổi cùng nhau ở cùng chỗ. Số thứ tự thể hiện dependency level.

Và structure của mỗi doc: Overview → Diagram → Sections → File Reference → Cross-References.

Bắt đầu từ project tiếp theo của bạn. Hoặc refactor docs của project hiện tại. Bạn sẽ thấy sự khác biệt ngay lần đầu AI agent đọc đúng và generate đúng từ documentation của bạn.

#documentation #ai #developer-experience #best-practices

Bài viết liên quan

50 năm của Email: Từ hộp thư cho người đến giao diện cho Agent

idea

Cloudflare vừa cập nhật Email Service. Điều đáng nói không phải là mức giá rẻ hơn Resend, mà là cách họ cấu trúc lại một giao thức 50 năm tuổi thành môi trường làm việc gốc cho AI.

AI không thay thế bạn. Nhưng nó làm bạn... ít liên quan hơn

idea

AI đang làm cho một số người trở nên ít liên quan. Không phải mất việc, không phải bị đuổi. Chỉ đơn giản là, người ta không còn cần chờ bạn nữa.

0:00

Chia sẻ ảnh

Bắt đầu gõ để tìm kiếm...