SDD Bootcamp Playbook — Chương 2 / 78 trang
Mô Hình Tư Duy MớiDeveloper Như Kiến Trúc Sư + Nhạc Trưởng
Khi AI viết code thay bạn, kỹ năng có giá trị không còn là gõ code nhanh — mà là thiết kế giải pháp, chỉ huy AI, và kiểm chứng kết quả.
Tổng Quan
Chương 2 Dạy Gì?
Vấn đề cốt lõi
AI có thể viết code, nhưng code AI tạo ra có thể trông đúng mà logic sai, thiếu security, không nhất quán giữa modules. Bạn cần tư duy mới để làm chủ AI — không phải để AI làm chủ bạn.
Bạn sẽ học được
- Chuyển từ Code Writer → Outcome Engineer
- T-Shape model cho AI era
- Context Engineering — quản lý AI như infrastructure
- Debug & verify code AI tạo
- Trách nhiệm đạo đức & bảo mật
"AI không thay thế developer — nó thay thế developer không biết dùng AI. Và developer biết dùng AI mà không có nền tảng kỹ thuật thì như nhạc trưởng không biết đọc nhạc."
Mục Lục
Nội Dung Chương 2
2.1
Từ Code Writer sang Outcome Engineer
2.2
T-Shape Model cho AI-Augmented Developer
2.3
Cognitive Load & Context Engineering
2.4
Debugging & Verification — Kỹ Năng Sống Còn
2.5
Ethical Considerations: Trách Nhiệm & Bảo Mật
Case Study
Code Writer vs. Outcome Engineer — Login Feature
Section 2.1
Từ Code Writer
sang Outcome Engineer
Khi AI viết code, giá trị của bạn không còn nằm ở khả năng gõ code nhanh. Giá trị của bạn nằm ở khả năng định nghĩa vấn đề, chỉ huy AI, và kiểm chứng kết quả. Đây là sự chuyển dịch từ how sang why & what.
2.1.1 — Bối Cảnh
Vì Sao Tư Duy Phải Thay Đổi?
Thị trường đang thay đổi
- GitHub Copilot: 1.8 triệu developers dùng hàng ngày
- Stack Overflow: lần đầu tiên traffic giảm khi AI coding tools tăng
- Khảo sát McKinsey: 30-40% coding tasks có thể được AI thực hiện
- Emerging: "AI-native" engineering teams không có junior coder
Những gì không thể tự động hoá
- Hiểu business context — tại sao feature này quan trọng
- Quyết định trade-offs — performance vs maintainability
- Domain knowledge — quy tắc kế toán, y tế, pháp lý
- Chịu trách nhiệm — khi hệ thống lỗi, AI không bị sa thải
Câu hỏi không còn là "AI có thể thay thế developer không?" mà là "Developer nào sẽ bị thay thế và developer nào sẽ trở nên không thể thiếu?"
2.1.2 — 3 Kỹ Năng Mới
Intent → Specification → Verification
① Intent Definition
Định nghĩa tại sao (Why) và cái gì (What) trước khi lo như thế nào (How).
Framework: Why-What-How. Không thể viết spec tốt nếu không hiểu intent.
② Specification Writing
Viết spec đủ để AI implement đúng không cần hỏi thêm. Acceptance criteria testable, constraints rõ ràng, edge cases được nghĩ đến.
Spec tốt = AI output tốt. Spec mơ hồ = AI hallucinate.
③ Outcome Verification
Kiểm chứng 3 tầng: Tests pass → Logic đúng → Architecture phù hợp. Không chỉ chạy được mà phải đúng.
Automation bias: đừng tin code AI chỉ vì nó chạy.
2.1.2 — Intent Definition
Framework: Why — What — How
WHY — Mục đích
- Business problem cần giải quyết
- Ai sẽ dùng feature này?
- Nếu không làm thì sao?
- Measure of success là gì?
Ví dụ: "User quên mật khẩu → mất access → revenue loss"
WHAT — Yêu cầu
- Acceptance Criteria (AC) cụ thể, testable
- Non-functional requirements
- Constraints và giới hạn
- Edge cases và error states
Ví dụ: "AC-1: Email reset link hết hạn sau 15 phút"
HOW — Hướng dẫn kỹ thuật
- Tech stack và patterns bắt buộc
- Files sẽ tạo/sửa
- API contracts
- Performance targets cụ thể
Ví dụ: "Dùng nodemailer, bcrypt token, Redis TTL"
💡 Quy tắc ngón tay cái: Nếu bạn không thể điền đầy đủ Why và What, bạn chưa sẵn sàng để code — dù tự code hay dùng AI.
2.1.2 — Outcome Verification
Kiểm Chứng 3 Tầng
Tầng 1 — Tests Pass
Unit tests, integration tests, E2E tests đều pass. Nhưng đây chỉ là điều kiện cần, không phải đủ. Tests có thể pass mà logic vẫn sai nếu tests kém chất lượng.
Tầng 2 — Logic Đúng
Walk through code với realistic data. Hỏi: "Code này xử lý gì khi input là null? Khi có concurrent access? Khi timezone khác nhau?" Đây là tầng cần domain knowledge của bạn.
Tầng 3 — Architecture Đúng
Code có theo đúng patterns không? Service layer tách biệt? Error handling nhất quán? Không có N+1 queries? Không hardcode secrets? Đây là tầng cần technical depth.
Bảng 2.2
Code Writer vs. Outcome Engineer
| Khía cạnh | Code Writer (Cũ) | Outcome Engineer (Mới) |
| Trọng tâm | Cú pháp & ngôn ngữ | Logic & kiến trúc hệ thống |
| Câu hỏi đầu tiên | "Viết code thế nào?" | "Tại sao cần feature này?" |
| Công cụ chính | IDE & Compiler | AI Agents & Context Management |
| Giá trị cốt lõi | Viết code nhanh, ít lỗi | Thiết kế giải pháp & Kiểm chứng |
| Xử lý lỗi | Debug thủ công từng dòng | Verify logic & Chỉ dẫn AI fix |
| Kỹ năng cao nhất | Thuộc API, nắm patterns | Viết spec, đánh giá trade-offs |
| Trách nhiệm | Code mình viết | Mọi code (kể cả AI tạo) |
| Đo lường | Lines of code / ngày | Features shipped & quality |
2.1.3 — Bài Tập
🛠 Thực Hành Why-What-How
Đề bài
Chọn 1 trong 3 tình huống:
- Feature đặt lịch khám bệnh cho phòng khám 50 bác sĩ
- Feature tìm kiếm sách cho thư viện 20.000 đầu sách tiếng Việt
- Feature mượn/trả sách với phí phạt trễ hạn
Yêu cầu
Trong 15 phút, viết ra:
- Why: Business context (3-5 câu)
- What: 5 Acceptance Criteria testable
- How: Tech stack + pattern + 2 constraints
- 2 edge cases không rõ ràng
Tiêu chí đánh giá Spec tốt
✓AC có thể viết test tự động không?
✓Constraints có cụ thể (số, đơn vị) không?
✓Edge cases có realistic không?
✓Có "Out of Scope" để giới hạn không?
Section 2.2
T-Shape Model
cho AI-Augmented Dev
T-Shape không mới — nhưng hình dạng chữ T đã thay đổi. Chiều ngang mở rộng: bạn cần sử dụng AI xuyên suốt toàn bộ SDLC. Chiều dọc sâu hơn: fundamentals quan trọng hơn bao giờ hết vì AI khuếch đại cả kiến thức lẫn sự thiếu hiểu biết của bạn.
2.2.1 — Chiều Ngang
AI Across SDLC — Từ Planning đến Deploy
| SDLC Phase | AI Role | Bạn Làm Gì | Kết quả |
| Planning | Business Analyst | Cung cấp context, validate output | Requirements rõ, risks xác định |
| Design | Architecture Consultant | Đánh giá trade-offs, chọn approach | Architecture document |
| Coding | Implementation Agent | Review code, enforce patterns | Code đúng spec |
| Testing | QA Engineer | Viết test cases, review coverage | Test suite đầy đủ |
| Documentation | Technical Writer | Review accuracy, update spec | Docs đồng bộ code |
| Deploy | DevOps Assistant | Review configs, approve pipeline | CI/CD chạy đúng |
💡 Critical Thinking không thể tắt: Ở mỗi phase, bạn phải đặt câu hỏi "AI có hiểu đúng context không?", "Output có hợp lý không?", "Có điều gì bị bỏ qua không?"
2.2.2 — Chiều Dọc
Fundamentals — Sâu Hơn Bao Giờ
DSA — Data Structures & Algorithms
AI không tự thêm index. AI tạo N+1 queries. AI dùng array khi nên dùng Set. Bạn cần biết để nhận ra — không phải để implement từ đầu.
Design Patterns
AI thường pha trộn patterns hoặc không dùng pattern nào. Nếu bạn không chỉ định rõ trong spec, mỗi phiên agent cho một kiến trúc khác nhau. Bạn phải ra lệnh, không phải hy vọng.
System Design
Scalability, caching, message queues, database indexing, load balancing — AI không tự thêm vào trừ khi bạn yêu cầu. Vòng luẩn quẩn: không biết → không yêu cầu → AI không làm.
Domain Knowledge — Vũ Khí Bí Mật
AI biết viết code xử lý thanh toán, nhưng không biết quy định kế toán kép. AI biết đọc file FASTQ, nhưng không biết Phred score nghĩa là gì. Domain knowledge là lợi thế bền vững nhất.
2.2.2 — Patterns Bạn Cần Biết
6 Design Patterns Quan Trọng Nhất
| Pattern | Khi nào dùng | Ví dụ trong spec |
| Repository | Tách data access khỏi business logic | "Mọi database query phải qua Repository layer" |
| Service Layer | Business logic tập trung | "Mọi business logic nằm trong /services" |
| Factory | Tạo objects phức tạp | "Dùng factory cho tạo Order với nhiều loại" |
| Observer | Event-driven communication | "Dùng event emitter cho cross-module comm" |
| Strategy | Algorithm có thể thay đổi | "Pricing calculator dùng Strategy pattern" |
| Middleware | Cross-cutting concerns | "Auth, logging, error handling dùng middleware" |
Nếu không chỉ định pattern trong spec, AI sẽ tạo code không theo pattern nào cụ thể, hoặc pha trộn nhiều patterns mâu thuẫn. Module A dùng Repository, Module B truy vấn DB trực tiếp trong controller.
Bảng 2.4 — 2.2.3
Ma Trận Tự Đánh Giá Kỹ Năng
Thang điểm: 1=Chưa biết | 2=Nhận biết | 3=Cơ bản | 4=Thành thạo | 5=Chuyên gia
| Kỹ năng | A | B | C | D | E |
| CHIỀU NGANG: AI TOOLING |
| Prompt Engineering | /5 | /5 | /5 | /5 | /5 |
| Sử dụng AI coding agent (Claude Code / Cursor) | /5 | /5 | /5 | /5 | /5 |
| Viết Spec / User Story / Intent | /5 | /5 | /5 | /5 | /5 |
| Review và đánh giá code AI tạo | /5 | /5 | /5 | /5 | /5 |
| AGENTS.md / CLAUDE.md / .cursorrules | /5 | /5 | /5 | /5 | /5 |
| Git + CI/CD cơ bản | /5 | /5 | /5 | /5 | /5 |
| CHIỀU DỌC: FUNDAMENTALS |
| Cấu trúc dữ liệu & Thuật toán | /5 | /5 | /5 | /5 | /5 |
| Design Patterns | /5 | /5 | /5 | /5 | /5 |
| Database Design & SQL | /5 | /5 | /5 | /5 | /5 |
| Security fundamentals | /5 | /5 | /5 | /5 | /5 |
| Domain Knowledge (dự án) | /5 | /5 | /5 | /5 | /5 |
2.2.4 — Thực Hành SDLC
Phase 1: Planning — AI Như Business Analyst
Prompt 1 — Brainstorm Requirements
"Tôi đang xây dựng hệ thống quản lý thư viện
trực tuyến cho trường đại học 5000 sinh viên.
Hãy liệt kê:
1. 15 functional requirements chính
(chia theo actor: SV, thủ thư, admin)
2. 10 non-functional requirements
3. 5 rủi ro kỹ thuật lớn nhất với mitigation
4. Đề xuất 3 milestones cho 20 tuần"
Prompt 2 — Phê Bình Spec
"Tôi đã viết spec cho tính năng Mượn Sách.
Hãy đóng vai Senior Developer phê bình:
- Tìm 10 chỗ mơ hồ hoặc thiếu chi tiết
- Tìm 5 edge cases chưa được đề cập
- Đánh giá AC: có testable không?
- Gợi ý cải thiện cụ thể.
[Dán spec vào đây]"
Hiệu quả nhất: AI đóng vai reviewer thay vì creator → phát hiện author blindness
2.2.4 — Thực Hành SDLC
Phase 2: Design — Phase 3: Coding
Prompt 3 — So sánh kiến trúc
"Dự án thư viện: React + Node.js + PostgreSQL.
So sánh 3 phương án tìm kiếm:
A) PostgreSQL FTS (tsvector + GIN index)
B) PostgreSQL LIKE + unaccent extension
C) Elasticsearch riêng biệt
Bối cảnh: 20K sách, 5K users, tiếng Việt,
đồ án sinh viên 20 tuần (không có ops team).
→ Phân tích performance, tiếng Việt, độ phức
tạp, chi phí, và recommendation."
Prompt 4 — Implement từ Spec
"Implement tính năng Mượn Sách theo spec.
Constraints:
- Pattern: Controller → Service → Repository
- Error handling: throw custom AppError
- Validation: dùng zod schema
- Naming: camelCase, files kebab-case
- Mỗi function < 30 dòng
Trước khi code, liệt kê các files sẽ tạo/sửa
và chờ tôi duyệt."
Plan-first approach → nhất quán hơn nhiều
2.2.4 — Thực Hành SDLC
Phase 4: Testing — Phase 5: Docs
Prompt 5 — Generate Test Cases
"Viết test suite cho BorrowService.borrowBook():
1. Happy path (mượn thành công)
2. Validation errors (sách không tồn tại)
3. Business rule violations (quá 5 cuốn)
4. Edge cases (concurrent borrow)
5. Error handling (database timeout)
Dùng Jest + supertest. Mock database."
Cách đánh giá: Mutation test — thay đổi logic xem tests có FAIL không?
Prompt 6 — Generate API Docs
"Từ code BorrowController, tạo API docs
theo format OpenAPI 3.0 bao gồm:
- Endpoints với HTTP method và path
- Request body schema + validation rules
- Response schema (success & error)
- Authentication requirements
- Rate limiting info
- Ví dụ request/response"
💡 Coverage ≠ Quality: 80% coverage với tests có nghĩa tốt hơn 100% coverage với tests vô nghĩa.
2.2.5 — DSA & Performance
Tại Sao DSA Quan Trọng Hơn Khi Có AI?
"Nhiều sinh viên hỏi: 'Nếu AI viết code được, tại sao phải học DSA?' Câu trả lời: DSA không để viết code — mà để đánh giá code AI tạo có hiệu quả không."
N+1
Queries — lỗi phổ biến nhất AI tạo
O(n²)
→ O(n) khi dùng Hash Map đúng cách
5000x
chênh lệch tốc độ với 10K records
Bạn không cần thuộc cách implement Red-Black Tree hay Dijkstra.
Bạn CẦN biết: khi nào dùng hash map thay vì nested loop, khi nào cần index, khi nào query N+1 xảy ra, khi nào cần pagination.
2.2.5 — Ví Dụ 1 & 2
Nested Loop vs Hash Map — N+1 Queries
Ví dụ 1: O(n²) → O(n)
// AI tạo — O(n²)
for (const book1 of list1) {
for (const book2 of list2) {
if (book1.isbn === book2.isbn)
duplicates.push(book1);
}
}
// Tối ưu — O(n+m) — dùng Set
const isbnSet = new Set(
list2.map(b => b.isbn)
);
return list1.filter(
b => isbnSet.has(b.isbn)
);
// 10K sách: 5000x nhanh hơn
Ví dụ 2: N+1 Queries
// AI tạo — 101 queries!
const books = await db.query(
'SELECT * FROM books' // 1
);
for (const book of books) {
book.author = await db.query(
'SELECT * FROM authors ...'
); // N queries
}
// Tối ưu — 1 query với JOIN
SELECT b.*, a.name
FROM books b
JOIN authors a ON b.author_id = a.id
Trông đúng, chạy đúng, nhưng cực kỳ chậm với dữ liệu thực
2.2.5 — Ví Dụ 3, 4 & 5
Index — Pagination — Data Structure
Ví dụ 3: Missing Index
-- Không có index
SELECT * FROM borrow_records
WHERE user_id = 123
ORDER BY borrowed_at DESC;
-- Full scan: 100-500ms
-- Thêm index
CREATE INDEX idx_borrow
ON borrow_records
(user_id, borrowed_at DESC);
-- B-tree: 1-5ms
Ví dụ 4: No Pagination
// AI: load toàn bộ
const books = await db.query(
'SELECT * FROM books'
);
// 20K records = ~10MB JSON!
// Tối ưu: cursor pagination
const { cursor, limit=20 } = req;
const books = await db.query(
`SELECT * FROM books
WHERE id > $1 LIMIT $2`,
[cursor || 0, limit]
);
Ví dụ 5: Array vs Set
// AI dùng array
const cats = [];
for (const b of books) {
if (!cats.includes(b.cat)) {
cats.push(b.cat); // O(n)!
}
}
// Tổng: O(n²)
// Đúng: dùng Set
return [...new Set(
books.map(b => b.category)
)]; // O(n)
2.2.6 — Repository & Service Patterns
Pattern 1-2: Repository + Service Layer
Pattern 1: Repository
// FAT CONTROLLER (sai)
app.get('/api/users/:id', async (req, res) => {
const user = await db.query( // ✗ DB trong ctrl
'SELECT * FROM users WHERE id = $1',
[req.params.id]
);
...
});
// Đúng pattern
app.get('/api/users/:id', async (req, res) => {
const user = await userService // ✓
.getUserWithStats(req.params.id);
res.json(user);
});
Pattern 2: Service Layer
// Quy tắc phân biệt:
// if/else về business rule → Service
// DB query → Repository
// Parse request/format res → Controller
async function borrowBook(userId, bookId) {
const user = await userRepo.findById(userId);
if (!user || user.status !== 'active')
throw new AppError(403, 'Not eligible');
const borrows = await borrowRepo
.countActive(userId);
if (borrows >= 5)
throw new AppError(400, 'Max limit');
...
}
Controller
Request/Response
→
Service
Business Logic
→
Repository
DB Queries
Section 2.3
Cognitive Load &
Context Engineering
Khi làm việc với AI, có hai bộ nhớ cần quản lý: context window của AI và cognitive load của bạn. Cả hai đều hữu hạn, cả hai đều dễ bị quá tải. Quản lý chúng như infrastructure — không phải để mặc kệ và hy vọng.
2.3.1 — Context Window
Context Window — RAM Của AI (2026)
| Model | Context Window | Ước tính trang sách | Ghi chú |
| Claude Opus 4.6 | 200K tokens | ~300 trang | Dùng trong Claude Code |
| Claude Sonnet 4.6 | 200K tokens | ~300 trang | Nhanh hơn, rẻ hơn Opus |
| GPT-4o | 128K tokens | ~190 trang | Dùng trong Copilot |
| Gemini 2.5 Pro | 1M tokens | ~1500 trang | Dùng trong Kiro |
| Codex CLI (OpenAI) | 128K tokens | ~190 trang | Open-source |
Phép tính thực tế — Claude Code session:
System prompt + tools: ~10K
AGENTS.md + CLAUDE.md: ~3K
Code files agent đọc (10 files): ~30K
Lịch sử chat (20 messages): ~40K
Agent's reasoning (thinking): ~30K
Code agent tạo: ~20K
Tổng: ~133K / 200K = 66% đã dùng → Chỉ còn 67K tokens cho việc tiếp theo
2.3.1 — Triệu Chứng
Khi Context Gần Đầy — AI Xuống Cấp
① "Quên" hướng dẫn
Instructions ở đầu phiên bị "đẩy ra" khỏi vùng chú ý của AI khi context dài.
② Nhầm lẫn giữa files
Đặc biệt khi có nhiều files có tên hoặc cấu trúc tương tự nhau.
③ Code không nhất quán
Code tạo sau không khớp với code tạo trước trong cùng phiên.
④ Hallucinate
Bịa ra API, function, hoặc library không tồn tại. Xảy ra nhiều hơn khi context bị nhiễu.
⑤ Vòng lặp vô tận
Agent sửa code rồi lại hỏng, sửa lại rồi lại hỏng — không thoát ra được. Dấu hiệu rõ nhất: nên bắt đầu phiên mới ngay.
2.3.2 — Context Engineering
4 Nguyên Tắc Cốt Lõi
① Selection — Chọn Lọc
Không dump toàn bộ codebase. Chỉ cung cấp files liên quan trực tiếp.
✓ CẦN: Service file, interface, caller, test, error log
✗ KHÔNG: Files không liên quan, lịch sử chat cũ
② Structure — Cấu Trúc
Thông tin có cấu trúc hiệu quả hơn thông tin rời rạc. Thay vì paste 10 đoạn chat, tổng hợp thành 1 file ngắn gọn. AGENTS.md và CLAUDE.md là công cụ cấu trúc context.
③ Clean — Làm Sạch
Loại bỏ thông tin lỗi thời, dead code, comments cũ.
- Bắt đầu conversation mới cho mỗi task
- Nếu phiên > 30 messages → bắt đầu phiên mới
④ Layer — Phân Tầng
→Tầng 1: Foundation — AGENTS.md, CLAUDE.md — LUÔN có mặt
→Tầng 2: Feature — Spec của feature đang làm
→Tầng 3: Task — Code, errors, tests cụ thể
Bảng 2.6
Context Engineering vs. Quản Lý RAM
| Khía cạnh | Quản lý RAM (máy tính) | Context Engineering (AI) |
| Tài nguyên | RAM (GB) | Context window (tokens) |
| Giới hạn | Hết RAM → swap/crash | Hết context → hallucinate/quên |
| Chiến lược | Load on demand, cache, GC | Chọn lọc, cấu trúc, làm sạch, phân tầng |
| Tối ưu | Memory profiling, heap analysis | Token counting, fresh sessions |
| Anti-pattern | Memory leak, dangling pointers | Context pollution (dump mọi thứ) |
| Tool hỗ trợ | Task Manager, htop, Valgrind | AGENTS.md, CLAUDE.md, memory.md |
| Mục tiêu | Chương trình chạy ổn định | AI output chính xác và nhất quán |
2.3.3 — Cognitive Load
5 Kỹ Thuật Giảm Tải Nhận Thức
① Modularization
Chia thành modules nhỏ, mỗi module = 1 phiên agent riêng. Mỗi phiên nên tạo không quá 300-500 dòng code mới.
② Fresh Conversations
Phiên mới cho mỗi task. Phiên > 30 messages → bắt đầu phiên mới với summary. Phiên sạch = AI và bạn đều tập trung hơn.
③ Plan-First Approach
"Trước khi code, lên kế hoạch:
- Files cần tạo/sửa
- Thứ tự làm
- Dependencies
Chờ tôi approve plan trước."
④ Checklists
Não bộ chỉ giữ được 4±2 items trong working memory (Miller, 1956). Checklist ngoại hóa trí nhớ, đảm bảo không bỏ sót.
⑤ Time-Boxing (Pomodoro)
25 phút review → nghỉ 5 phút. Não bộ review hiệu quả nhất trong 25 phút đầu. Đừng review 2000 dòng code trong 1 phiên liên tục.
2.3.4 — Thực Hành
3 Tình Huống Context Engineering
Tình huống 1: Đầu ngày
Mỗi sáng, AI không nhớ gì từ hôm qua. "Load context" như load save game:
"Hôm nay tôi làm feature Auth.
Spec: .spec/auth-spec.md.
Hôm qua xong: login + rate limit.
Hôm nay: refresh token + lockout."
Phiên mới + summary ngắn = context sạch
Tình huống 2: Agent "lạc"
Triệu chứng: agent lặp lại code cũ, dùng sai naming, "quên" constraints → Context Reset Protocol:
- Dừng lại ngay
- Save progress
- Mở phiên MỚI với summary
- Tiếp tục từ điểm dừng
Tình huống 3: Nhóm 5 người
Mỗi người dùng AI riêng → code không nhất quán → Shared Context Layer:
project-root/
├─ .spec/
│ ├─ constitution.md ← bất biến
│ ├─ architecture.md
│ └─ api-contracts.md
├─ AGENTS.md ← mọi agent đọc
└─ CLAUDE.md
2.3.6 — Template
AGENTS.md — Template Cho Đồ Án
# AGENTS.md
## Project Overview
Hệ thống quản lý thư viện XYZ.
5000 sinh viên, 20000 đầu sách.
## Tech Stack
- Frontend: React 18 + TypeScript
- Backend: Node.js 20 + Express
- Database: PostgreSQL 16 + Prisma
- Testing: Jest + Supertest
## Architecture Pattern
Controller → Service → Repository
KHÔNG đặt DB queries ngoài *.repository.ts
## Coding Conventions
- camelCase cho functions/variables
- PascalCase cho types/classes
- kebab-case cho file names
- AppError cho mọi errors
- Mọi function < 30 dòng
## Security Rules
- NEVER hardcode secrets
- NEVER paste .env vào prompt
- Parameterized queries BẮT BUỘC
- zod cho mọi user input
## Git Workflow
- Branch: feature/XX-description
- PR phải có 1 reviewer approve
File này là "nguồn sự thật" cho cả team. Khi thay đổi convention → cập nhật AGENTS.md trước, commit, thông báo nhóm.
2.3.8 — Làm Việc Nhóm
3 Team Ceremonies — Đồng Bộ Nhóm Với AI
Monday Spec Review
30 phút
Review tất cả specs cho tasks tuần này. Mọi người hiểu ai làm gì và API giữa các modules. Giảm xung đột khi merge cuối tuần.
Wednesday Pair Programming
60 phút
2 người cùng ngồi với 1 phiên AI. Người 1 viết prompt, Người 2 kiểm tra logic. Rotation hàng tuần để mọi người hiểu code của nhau.
Friday Demo + Retro
45 phút
Demo những gì đã làm tuần này. Retro: cái gì tốt, cái gì cần cải thiện. Cập nhật AGENTS.md và constitution nếu cần.
Với AI, mỗi người có thể tạo code RẤT NHANH và RẤT NHIỀU. Nhưng nếu 5 người tạo code theo hướng khác nhau, kết quả là hỗn loạn. Ceremonies là mutex trong teamwork — ngăn race conditions.
Section 2.4
Debugging &
Verification
Khi phần lớn code được AI tạo, bạn sẽ dành nhiều thời gian đọc và kiểm tra code của "người khác" hơn là viết code của mình. Đây là kỹ năng mới — ít khi được dạy trong trường đại học.
2.4.1 — Đọc Code AI
4 Đặc Trưng Code AI Cần Nhận Biết
① Trông chuyên nghiệp nhưng sai logic
AI viết code sạch, đặt tên biến tốt, cấu trúc rõ ràng. Điều này tạo automation bias — tin tưởng chỉ vì trông chuyên nghiệp. Cảnh giác!
② Nhất quán trong file, không nhất quán giữa files
Không có memory giữa phiên: Module A dùng camelCase, Module B dùng snake_case. Error handling khác nhau giữa services. Lý do cần Constitution + AGENTS.md.
③ Edge cases bị bỏ qua
AI xử lý happy path rất tốt nhưng thường miss:
- Input null/undefined/empty string
- Concurrent access
- Timezone issues (UTC vs local)
- Unicode (tiếng Việt, emoji)
- Network failures, timeout
④ Dependencies thừa
AI có xu hướng import nhiều libraries hơn cần. Mỗi dependency = 1 rủi ro bảo mật + 1 điểm hỏng tiềm tàng. Check: package nào thực sự được dùng?
2.4.3 — TDD + AI
TDD + AI = Combo Mạnh Nhất
Red
BẠN viết tests
→
Green
AI viết code
→
Refactor
BẠN review
→
Lặp lại
Thêm edge cases
Ví dụ: Tests encode business rules
test('apply highest discount only', () => {
// Business rule: chỉ áp mã cao nhất
expect(calculateFinalPrice(100000, [
{ type: 'pct', value: 50 },
{ type: 'pct', value: 30 }
])).toBe(50000);
});
test('price cannot go negative', () => {
expect(calculateFinalPrice(
10000, [{type:'fixed',value:20000}]
)).toBe(0);
});
Tại sao hiệu quả
- Bạn kiểm soát "cái gì đúng" (tests)
- AI lo "làm thế nào" (implementation)
- Tests = hàng rào: code sai → tests fail ngay
- Bạn không cần đọc 100 dòng impl — chỉ cần tests pass và tests đầy đủ
Bảng — 2.4.4
10 Lỗi Phổ Biến Nhất Trong Code AI
| # | Lỗi | Tần suất | Mức nguy | Cách phát hiện |
| 1 | N+1 queries | Rất cao | Performance | Review mọi loop chứa DB query |
| 2 | Missing input validation | Rất cao | Security | Kiểm tra mọi endpoint nhận data user |
| 3 | Hardcoded secrets | Cao | Security | Grep: password, secret, key, token |
| 4 | Inconsistent error handling | Cao | Maintainability | So sánh error handling giữa modules |
| 5 | No pagination | Cao | Performance | Kiểm tra mọi endpoint trả list |
| 6 | Race conditions | TB | Data integrity | Tìm read-then-write không có lock |
| 7 | Missing index | TB | Performance | EXPLAIN mọi query với data lớn |
| 8 | Zombie imports | Thấp | Code quality | Lint rule: no-unused-imports |
| 9 | Over-abstraction | Thấp | Maintainability | Hỏi: "Có >1 implementation không?" |
| 10 | Stale comments | Thấp | Maintainability | Review comments vs code logic |
2.4.5 — Debug Protocol
Quy Trình Debug Code AI — 6 Bước
① Xác định triệu chứng rõ ràng
Không phải "nó không chạy" mà là: "POST /api/login trả về 500 với body {...}, error: TypeError: Cannot read property 'id' of null"
② Kiểm tra spec trước
Lỗi có phải do spec thiếu không? Nhiều khi lỗi nằm ở spec mơ hồ, không phải implementation. Ví dụ: spec không nói xử lý khi user null.
③ Giới hạn phạm vi
Bug ở layer nào? Controller? Service? Repository? DB? Test từng layer độc lập bằng cách gọi function trực tiếp với test data.
④ Dùng AI để debug AI
Mở phiên MỚI (context sạch!), cung cấp: endpoint, input, expected, actual, error, code. Hỏi AI phân tích nguyên nhân.
⑤ Verify fix
Hiểu tại sao fix đó đúng → viết test cho case gây bug → chạy toàn bộ test suite (không regression).
⑥ Update spec và tests
Thêm edge case vào spec. Thêm test case. Đảm bảo bug không lặp lại. Bug là thông tin — hãy document nó.
2.4.6 — Walkthrough
Debug Bug Thực Tế: Overdue Fee
Bug: calculateOverdueFee trả số âm
// Code AI tạo — BUG ở đây!
function calculateOverdueFee(
dueDate: string, returnDate: string
) {
const due = new Date(dueDate);
const ret = new Date(returnDate);
const diffMs = due.getTime()
- ret.getTime(); // ← ĐẢO NGƯỢC!
const diffDays = Math.ceil(
diffMs / (1000 * 60 * 60 * 24)
);
const fee = Math.max(0, diffDays * 5000);
return Math.min(fee, 500000);
}
Mental Simulation & Fix
// Input: due=Feb28, ret=Mar01
// due - ret = số ÂM (due < ret)
// max(0, âm*5000) = 0 (BUG!)
// Fix: đổi thứ tự trừ
const diffMs =
ret.getTime() - due.getTime();
// Verify:
// Đúng hạn: ret=due → 0 ✓
// Trễ 1 ngày: → 5000 ✓
// Trễ 100 ngày: → 500000 (cap) ✓
// Trả sớm: → 0 ✓
Bug nhỏ (đảo 2 biến) nhưng kết quả sai hoàn toàn. Bài học: test CẢ HAI chiều (sớm và trễ) cho mọi hàm tính toán.
Section 2.5
Ethical Considerations
Bất kể AI tạo ra bao nhiêu code, bạn luôn là người chịu trách nhiệm cuối cùng. Đây không chỉ là nguyên tắc đạo đức — mà là thực tế pháp lý: nếu ứng dụng gây thiệt hại, bạn và team chịu trách nhiệm — không phải Anthropic hay OpenAI.
2.5.1 — Human-in-the-Loop
⚠ 3 Quy Tắc Vàng
1
Không commit code mà bạn không hiểu.
Khi giáo viên hỏi "Tại sao đoạn code này hoạt động thế này?", câu trả lời "Vì AI viết thế" là KHÔNG chấp nhận được.
2
Không deploy tính năng mà bạn không thể giải thích.
Giải thích được = hiểu được logic + edge cases + failure modes.
3
Không chấp nhận AI output mà bạn không thể verify.
Nếu bạn không biết cách kiểm tra output → học cách kiểm tra trước khi dùng AI cho lĩnh vực đó.
2.5.2 — Bảo Mật
5 Lỗ Hổng Phổ Biến Trong Code AI
① SQL Injection
// XẤU:
`SELECT * FROM users WHERE email
= '${email}'` // ← NGUY HIỂM
// TỐT — parameterized:
db.query(
'SELECT * FROM users WHERE email=$1',
[email]
)
② Hardcoded Credentials
// XẤU:
const JWT_SECRET = 'super-secret-123';
// TỐT:
const JWT_SECRET = process.env.JWT_SECRET;
if (!JWT_SECRET)
throw new Error('Not configured');
③ Missing Input Validation
// XẤU — không validate:
const { email, name } = req.body;
db.createUser({ email, name });
// TỐT:
if (!isValidEmail(email))
return res.status(400)...;
const clean = sanitize(name);
④ Insecure Deps + ⑤ Permissive CORS
// Sau mỗi lần AI thêm package:
npm audit
// Kiểm tra: package có maintained không?
// XẤU — CORS open:
app.use(cors({ origin: '*' }));
// TỐT — chỉ định domain:
app.use(cors({
origin: ['https://myapp.com']
}));
Tỷ lệ code AI có lỗ hổng bảo mật: 9.8% – 42.1% (các nghiên cứu khác nhau)
2.5.4 — Security Checklist
Security Checklist 15 Items — Cho Mỗi PR
| # | Kiểm tra | Mức độ |
| 1 | Không có hardcoded secrets (grep: password, secret, key, token) | Bắt buộc |
| 2 | Tất cả DB queries dùng parameterized (không string concat) | Bắt buộc |
| 3 | Tất cả user input được validate và sanitize | Bắt buộc |
| 4 | CORS chỉ cho phép domains cụ thể (không '*') | Bắt buộc |
| 5 | JWT secret từ env, không hardcode | Bắt buộc |
| 6 | Password hash bằng bcrypt/argon2 (không MD5/SHA1) | Bắt buộc |
| 7 | .gitignore có: .env, *.key, *.pem, node_modules | Bắt buộc |
| 8 | npm audit / pip audit không có critical vulnerabilities | Cao |
| 9 | Rate limiting cho endpoints nhạy cảm (login, register) | Cao |
| 10 | Error messages không lộ internal info (stack trace, DB schema) | Cao |
| 11 | HTTPS enforce (redirect HTTP → HTTPS) | Cao |
| 12 | Không có console.log chứa sensitive data | Trung bình |
| 13 | File upload: validate type, size | Trung bình |
| 14 | Session/token có expiry hợp lý | Trung bình |
| 15 | Helmet.js hoặc tương đương (HTTP security headers) | Trung bình |
2.5.3 & 2.5.5 — Tech Debt
Tech Debt Từ AI — 4 Dạng + Chiến Lược
| Dạng debt | Mô tả | Cách phát hiện | Cách ngăn |
| Inconsistent patterns | Module A dùng Repository, Module B dùng Active Record | Cross-module code review | Constitution định nghĩa patterns |
| Over-engineering | Abstraction cho mọi thứ kể cả 1 use case | "Có thực sự cần interface này?" | YAGNI rule trong constitution |
| Zombie code | Imports, functions tạo nhưng không dùng | Lint: no-unused-vars | Lint + auto-fix trong CI |
| Doc drift | Docs không khớp code hiện tại | Spot check hàng sprint | Generate docs từ code |
Chiến Lược 10% Rule
Dành 10% thời gian mỗi sprint cho debt cleanup. Sprint 2 tuần = 1 ngày cleanup. Thứ 6 hàng tuần: 2 giờ fix lint + naming + stale docs + remove zombie code.
2.5.6 — Thảo Luận
3 Kịch Bản Đạo Đức Thực Tế
Kịch bản 1: Skip Review
Deadline demo ngày mai. AI tạo code, tests pass. Muốn merge không review kỹ.
Thảo luận: Rủi ro là gì? Giải pháp thay thế? Giảm scope? Xin thêm thời gian?
Kịch bản 2: Không hiểu code
AI tạo algorithm phức tạp cho recommendation. Chạy đúng nhưng bạn không hiểu logic.
Quy tắc vàng: Nếu bạn không thể giải thích code cho nhóm, đừng commit nó.
Kịch bản 3: Lỡ paste .env
Thành viên A paste cả file .env (có DB password, API keys) vào Claude. Rồi mới nhận ra.
Hành động NGAY:
- Rotate TẤT CẢ credentials đã lộ
- Kiểm tra truy cập trái phép
- Thêm rule vào AGENTS.md
- Dùng .env.example với giá trị giả
Case Study
Code Writer vs.
Outcome Engineer
Tính năng Login cho ứng dụng web (React + Node.js + PostgreSQL). Hai developer, cùng một yêu cầu, hai cách tiếp cận khác nhau hoàn toàn. Kết quả? Một người mất 3 ngày fix bugs. Người kia hoàn thành trong 40 phút.
Case Study — Cách 1
Code Writer: 5 Phút, 8 Lỗ Hổng
Prompt dùng
"Tạo cho tôi tính năng login
với React frontend và Node.js backend,
dùng PostgreSQL."
Code AI tạo (5 phút)
router.post('/login', async (req, res) => {
const { email, password } = req.body;
const user = await User.findByEmail(email);
if (!user) return res.status(401)...;
const match = await bcrypt.compare(...);
if (!match) return res.status(401)...;
const token = jwt.sign({ id: user.id },
'secret-key', { expiresIn: '7d' });
res.json({ token });
});
8 Lỗ Hổng Phát Hiện Sau
✗Không có rate limiting → Brute force attack
✗JWT secret hardcoded → Lộ trong source code
✗Token expiry 7 ngày → Token bị đánh cắp dùng 1 tuần
✗Không log failed attempts → Không phát hiện tấn công
✗Không validate input → SQL injection tiềm ẩn
✗Không có refresh token → User bị logout giữa chừng
✗Không có password policy → Chấp nhận password "1"
✗Không có account lockout → Unlimited attempts
Tổng: 5 phút implement + 3+ ngày fix + rủi ro bảo mật không giới hạn
Case Study — Cách 2
Outcome Engineer: Spec 30 Phút
# Feature Spec: Authentication System
## Business Context
User cần đăng nhập để truy cập dữ liệu cá nhân.
Hệ thống phải bảo vệ tài khoản khỏi unauthorized access.
Target: 1000 users, 100 concurrent logins.
## Acceptance Criteria
AC-1: Đăng nhập bằng email/password
AC-2: Rate limiting: max 5 attempts/phút/IP
AC-3: Account lock sau 10 lần sai (unlock sau 30 phút)
AC-4: JWT access token: 15 phút expiry
AC-5: Refresh token: 7 ngày, rotate on use, revoke on logout
AC-6: Password: min 8 chars, 1 uppercase, 1 number, 1 special
AC-7: bcrypt cost factor: 12
AC-8: Log mọi login attempt (success/fail) với IP, timestamp
## Technical Constraints
- Parameterized queries only (no string concatenation)
- Secrets từ environment variables, NEVER hardcode
- Validate & sanitize ALL input
- CORS: chỉ frontend domain | HTTPS only
## Edge Cases
- Login từ timezone khác nhau
- Concurrent login từ nhiều devices
- Token refresh khi access token hết giữa request
- Email case sensitivity (User@mail.com vs user@mail.com)
## Out of Scope (v2)
- OAuth/SSO | 2FA | Password reset via email
Case Study — Cách 2 (tiếp)
Outcome Engineer: Code Đầy Đủ, 10 Phút
export async function login(input: unknown, ip: string) {
// Validate input (AC: validate ALL input)
const { email, password } = loginSchema.parse(input);
// Rate limiting (AC-2: max 5 attempts/min/IP)
await rateLimiter.checkLimit(`login:${ip}`, 5, 60);
// Find user — email case-insensitive (Edge Case)
const user = await authRepository.findByEmail(
email.toLowerCase().trim()
);
if (!user) {
logger.warn('Login failed: user not found', { email, ip });
throw new AppError(401, 'Invalid email or password');
}
// Check account lock (AC-3)
if (user.lockedUntil && user.lockedUntil > new Date()) {
logger.warn('Login on locked account', { userId: user.id });
throw new AppError(423, 'Account locked. Try again later.');
}
// Verify password (AC-7: bcrypt cost 12)
const isValid = await comparePassword(password, user.passwordHash);
if (!isValid) {
await authRepository.incrementFailedAttempts(user.id);
if (user.failedAttempts + 1 >= 10) {
const lockUntil = new Date(Date.now() + 30 * 60 * 1000);
await authRepository.lockAccount(user.id, lockUntil);
}
throw new AppError(401, 'Invalid email or password');
}
// Generate token pair (AC-4: 15min, AC-5: 7d)
const tokens = generateTokenPair({ userId: user.id, role: user.role });
logger.info('Login successful', { userId: user.id, ip });
return { accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken, expiresIn: 900 };
}
Agent trích dẫn AC-2, AC-3, AC-4, AC-5, AC-7, AC-8 trong code. Edge case email case-insensitive được xử lý. Logging đầy đủ. Error message không lộ "email không tồn tại".
Bảng 2.8 — Case Study
So Sánh Hai Cách Tiếp Cận
| Tiêu chí | Code Writer | Outcome Engineer |
| Thời gian ban đầu | 5 phút | 40 phút |
| Thời gian fix issues | 3+ ngày | < 1 giờ |
| Tổng thời gian thực | 3+ ngày | < 2 giờ |
| Bảo mật | 8 lỗ hổng | 0 lỗ hổng đã biết |
| Test coverage | Basic (happy path) | Full (mọi AC + edge cases) |
| Tái sử dụng | Không có spec | Spec là tài liệu sống |
| Team hiểu code | Chỉ người tạo | Ai đọc spec đều hiểu |
| Giáo viên đánh giá | Khó trace đóng góp | Spec = deliverable rõ ràng |
| Mở rộng cho v2 | Rewrite lại | Update spec, re-run agent |
Bài Học Cốt Lõi
Outcome Engineer
KHÔNG chậm hơn —
họ nhanh hơn khi tính
tổng thời gian cả vòng đời feature.
30 phút
viết spec tiết kiệm
3 ngày
fix bugs
Spec
là cách duy nhất để
5 người
cùng hiểu 1 tính năng
Bài Tập Tổng Hợp
🛠 Outcome Engineer Challenge — 80 Phút
| Phase | Hoạt động | Người | Thời gian |
| Phase 1: Spec | 1 người viết Why, 2 người viết AC+constraints, 1 người viết edge cases, 1 người dùng AI brainstorm | Nhóm | 20 phút |
| Phase 2: TDD | Viết tests cho mọi AC, dùng AI tìm 5 edge cases bổ sung | Nhóm | 15 phút |
| Phase 3: Implement | Đưa spec + tests cho agent, duyệt plan, implement | Agent + Nhóm | 15 phút |
| Phase 4: Verify | Tests pass? Logic đúng? Architecture đúng? Security checklist? | Nhóm | 20 phút |
| Phase 5: Retro | Spec thiếu gì? Nếu Vibe Coding thì khác thế nào? Update Skill Matrix | Nhóm | 10 phút |
Đầu ra: 1 feature hoàn chỉnh với spec + tests + code + verification + retro notes. Lưu lại toàn bộ artifacts làm tài liệu học tập.
Tổng Kết
Tóm Tắt Chương 2
2.1 — Outcome Engineer
Developer chuyển từ How sang Why & What. 3 kỹ năng mới: Intent Definition, Spec Writing, Outcome Verification.
2.2 — T-Shape mở rộng
Ngang = AI across SDLC + Critical Thinking. Dọc = DSA + Patterns + Domain Knowledge quan trọng hơn bao giờ.
2.3 — Context = Infrastructure
4 nguyên tắc: Chọn lọc, Cấu trúc, Làm sạch, Phân tầng. 5 kỹ thuật giảm Cognitive Load. AGENTS.md = shared context.
2.4 — TDD + AI Combo
Đọc code AI với skepticism. TDD = hàng rào kiểm soát. Dùng AI tìm edge cases. Debug 6 bước có hệ thống.
2.5 — Human-in-the-Loop luôn
Không paste secrets. Kiểm tra 5 loại lỗ hổng phổ biến. 15-item security checklist mỗi PR. Quản lý tech debt từ đầu với 10% Rule.
💡 Case Study: 40 phút Outcome Engineer > 3 ngày Code Writer khi tính full lifecycle. Spec = đầu tư, không phải chi phí.
Checklist Hoàn Thành + Preview
Bạn Đã Nắm Được Chương 2 Khi...
✅ Checklist
□Hiểu chuyển dịch Code Writer → Outcome Engineer
□Biết viết Why-What-How cho một feature
□Tự đánh giá Skill Matrix, biết điểm yếu
□Hiểu và áp dụng 4 nguyên tắc Context Engineering
□Biết phân biệt 4 đặc trưng code AI
□Đã làm bài tập TDD + AI ít nhất 1 lần
□Biết 15-item security checklist
□Hiểu AGENTS.md dùng để làm gì
➡ Tiếp Theo: Chương 3
Hệ Sinh Thái Công Cụ AI Coding
- So sánh chi tiết: Claude Code vs Cursor vs GitHub Copilot vs Codex CLI vs Kiro
- Ưu nhược điểm đa chiều: giá, tính năng, workflow
- Hướng dẫn chọn tool cho đồ án nhóm
- Setup và cấu hình thực tế