01. Nhận Yêu Cầu & Chốt Kiến Trúc — Vibe Coding Series

Cách phân tích yêu cầu với AI để tránh build sai thứ, dùng Socratic questioning, tạo user story và chốt kiến trúc trước khi code.

Tuần thứ ba của dự án, tôi mới nhận ra mình đã hiểu sai yêu cầu từ đầu.

Khách hàng nói “user có thể assign task cho nhau”. Tôi nghe vậy, AI implement vậy — một user chọn task, chọn người nhận, bấm assign. Xong. Đơn giản.

Nhưng khi demo, khách hàng hỏi: “Ủa, sao team lead không approve được trước khi assign?” Tôi ngớ người. Không ai nói đến approval flow. Tôi không hỏi. AI không hỏi. Cả hai cùng assume.

Ba tuần code, một buổi demo, và tôi phải redesign lại toàn bộ permission model.


Bối cảnh

Ở bài 00, tôi đã giới thiệu Vibe Coding Framework — 8 phases từ ý tưởng đến production — và setup môi trường làm việc với AI agent. Bài này đi vào Phase 1: nhận yêu cầu, phân tích, và chốt kiến trúc trước khi viết dòng code đầu tiên.

Đây là phase mà hầu hết mọi người bỏ qua. Và đó là lý do tại sao họ mất hàng tuần để fix những thứ đáng ra không nên tồn tại.


Vấn đề: Requirements là nơi AI dễ hallucinate nhất

AI rất giỏi viết code. Nhưng AI cực kỳ tệ trong việc biết mình đang viết code cho cái gì.

Khi bạn đưa cho AI một brief mơ hồ — “build task management cho team” — nó sẽ không hỏi lại. Nó sẽ assume. Nó sẽ fill in the blanks bằng những gì nó đã thấy trong training data: Trello, Jira, Asana. Kết quả là một sản phẩm trông quen thuộc nhưng không phải thứ bạn cần.

Đây không phải lỗi của AI. Đây là lỗi của quy trình.

Requirements là nơi duy nhất trong toàn bộ development cycle mà sự mơ hồ có thể nhân lên theo cấp số nhân. Một assumption sai ở đây → sai architecture → sai implementation → sai test → sai product. Và bạn chỉ phát hiện ra ở cuối.

Từ brief mơ hồ đến kiến trúc được chốt — quy trình phân tích yêu cầu với AI


Kỹ thuật phân tích yêu cầu với AI

Socratic questioning: để AI hỏi ngược lại

Thay vì đưa brief cho AI và bảo nó implement, hãy đưa brief và bảo nó hỏi bạn.

Prompt:
"Đây là brief của tôi: [brief]. Trước khi implement bất cứ thứ gì,
hãy hỏi tôi tất cả những câu hỏi cần thiết để làm rõ yêu cầu.
Tập trung vào: edge case, permission model, business rule ẩn,
và những thứ tôi có thể đã assume mà không nói ra."

Khi tôi thử với TaskFlow, AI hỏi ngay:

  • “Khi một task bị xóa, các comment và attachment có bị xóa theo không?”
  • “User có thể assign task cho chính mình không?”
  • “Deadline là timezone của user hay timezone của server?”
  • “Nếu member bị remove khỏi team, task họ đang assigned sẽ ra sao?”

Bốn câu hỏi. Bốn edge case tôi chưa nghĩ đến. Và đây chỉ là phần nhỏ của một feature.

Tạo user story + acceptance criteria với AI

Sau khi làm rõ yêu cầu, dùng AI để format lại thành user story có acceptance criteria rõ ràng. Format tôi dùng:

User Story: Assign task
As a [team member]
I want to [assign a task to another member]
So that [the assignee knows they're responsible for it]

Acceptance Criteria:
- [ ] Only task creator or team lead can assign
- [ ] Assignee receives email notification within 5 minutes
- [ ] Task shows assignee's avatar in list view
- [ ] Cannot assign to user outside the team
- [ ] Assigning to self is allowed
- [ ] Previous assignee is notified when reassigned

Cái hay của format này: nó buộc bạn phải nghĩ đến ai làm gì và tại sao — không chỉ là “cần có feature assign task”. Và khi AI implement, nó có checklist cụ thể để validate.

Phát hiện edge case và conflict sớm

Sau khi có user story, dùng AI để tìm conflict:

Prompt:
"Đây là danh sách user story của tôi: [list]. Hãy tìm:
1. Conflict giữa các story (story A và B mâu thuẫn nhau)
2. Missing story (có story A nhưng thiếu story B là prerequisite)
3. Ambiguous acceptance criteria (tiêu chí nào có thể hiểu nhiều cách)"

Với TaskFlow, AI phát hiện ngay: story “team lead có thể xem tất cả task” conflict với story “task chỉ visible với assignee và creator” — hai requirement từ hai stakeholder khác nhau, không ai nhận ra cho đến khi đặt cạnh nhau.


Chốt kiến trúc: AI như sparring partner

Đặt câu hỏi đúng để AI đề xuất kiến trúc

Đừng hỏi AI “kiến trúc nào tốt nhất cho app của tôi”. Câu hỏi đó quá rộng, AI sẽ cho bạn một câu trả lời generic.

Hỏi cụ thể hơn:

Prompt:
"Với requirements này: [requirements], team size 2 người, timeline 3 tháng,
budget hạn chế, cần scale đến 10k user trong năm đầu — hãy đề xuất
3 kiến trúc khác nhau với trade-off của từng cái. Tôi sẽ chọn."

Bạn là người chọn. AI là người trình bày options.

Trade-off analysis: ví dụ thực tế

Với TaskFlow, tôi hỏi AI về database choice. Đây là phần tóm tắt trade-off nó đưa ra:

PostgreSQL (Supabase)MongoDBPlanetScale (MySQL)
Phù hợp vớiRelational data, RLS, realtimeFlexible schema, document-heavyServerless, branching
Điểm mạnhACID, Row Level Security built-inSchema flexibilityHorizontal scale
Điểm yếuSchema migration cần cẩn thậnConsistency phức tạp hơnKhông có RLS native
Với TaskFlow✅ Tốt nhất — RLS cho multi-tenant⚠️ Overkill, data vẫn relational⚠️ Thiếu RLS

Tôi chọn PostgreSQL/Supabase. Không phải vì AI bảo vậy — mà vì tôi hiểu tại sao sau khi đọc trade-off.

Ownership map: ai chịu trách nhiệm phần nào

Sau khi chốt kiến trúc, tạo ownership map — tài liệu xác định phần nào AI implement, phần nào human implement, phần nào cần human review bắt buộc.

# TaskFlow — Ownership Map

| Module | Owner | Review Required |
|--------|-------|-----------------|
| Auth (Supabase) | AI | Human final check |
| Row Level Security policies | Human | — |
| CRUD API routes | AI | Human spot-check |
| Email templates | AI | Human review |
| Payment integration | Human | — |
| Database migrations | Human | — |
| UI components | AI | Human review |
| Deployment config | Human | — |

Rule of thumb: bất cứ thứ gì liên quan đến security, money, hoặc data integrity — human owns it. AI có thể draft, nhưng human phải review và approve.


Ví dụ thực chiến: TaskFlow từ brief mơ hồ đến kiến trúc được chốt

Brief ban đầu (những gì tôi có):

“Build một task management app cho team indie. Có auth, CRUD task, dashboard, invite member, email notification.”

Sau Socratic questioning — những gì AI hỏi và tôi trả lời:

  • Multi-tenant? → Có, mỗi team là một workspace riêng
  • Role-based access? → Có: Owner, Admin, Member
  • Real-time update? → Không cần thiết cho MVP
  • File attachment? → Không trong MVP
  • Mobile app? → Không, web only

User stories được tạo ra: 23 stories, nhóm thành 5 epic (Auth, Team, Task, Dashboard, Notification)

Conflicts phát hiện: 2 conflicts về visibility rule, 1 missing story về “deactivate member”

Kiến trúc được chốt:

  • Next.js 15 App Router (full-stack, một repo)
  • Supabase (PostgreSQL + Auth + RLS)
  • Resend (email)
  • Vercel (deploy)
  • Monolith — không microservice (team nhỏ, MVP, scale sau)

Từ brief 50 chữ đến kiến trúc rõ ràng: mất khoảng 2 tiếng. Không phải 3 tuần.


Những điều cần tránh

Approve kiến trúc AI đề xuất mà không hiểu. AI có thể đề xuất microservice vì nó “best practice” — nhưng với team 2 người và MVP 3 tháng, microservice là overkill. Nếu bạn không hiểu trade-off, bạn không thể phản bác. Và bạn sẽ sống với quyết định đó trong nhiều tháng.

Bỏ qua non-functional requirements. “App phải nhanh” không phải requirement. “API response < 200ms cho 95th percentile với 1000 concurrent users” mới là requirement. AI sẽ không hỏi về performance, security, hoặc scalability nếu bạn không đặt câu hỏi. Bạn phải chủ động.


Tóm tắt

  • Đưa brief cho AI và bảo nó hỏi ngược lại — đây là cách nhanh nhất để phát hiện assumption ẩn
  • User story + acceptance criteria là “contract” giữa bạn và AI — không có nó, AI sẽ assume
  • Dùng AI để tìm conflict và missing story trước khi code, không phải sau
  • Trade-off analysis: AI trình bày options, bạn là người chọn — không bao giờ ngược lại
  • Ownership map xác định rõ ai chịu trách nhiệm phần nào — đặc biệt quan trọng với security và data

Tiếp theo

Phase 2 giải quyết vấn đề tiếp theo: khi frontend và backend build song song mà không có contract chung, integrate là địa ngục. Bài tiếp theo sẽ đi vào cách viết API spec trước khi code — và tại sao đây là thứ tiết kiệm nhiều thời gian nhất trong toàn bộ framework.

→ Bài 02: Specs & API Contract First

← Bài 00: Nền Tảng & Setup