Thời lượng: 20 phút
Level: Beginner
Yêu cầu: Hoàn thành Lesson 1.2
Mục tiêu bài học
Sau bài học này, bạn sẽ:
- Biết 5 thành phần của một standard hoàn chỉnh
- Có checklist Definition of Done cho các loại changes
- Hiểu tại sao "no examples = fail"
Nội dung chính
1. Tại sao cần Definition of Done?
Vấn đề: Ai đó viết một "standard" nhưng:
- Chỉ có text, không có examples
- Không có automation
- Không ai biết khi nào là "đủ"
Kết quả: Standard được interpret khác nhau → Thất bại
"Tất cả APIs nên return consistent errors"
→ "Nên" nghĩa là gì? "Consistent" như thế nào?
"Tất cả APIs PHẢI return error theo schema này:
{code: string, message: string}
Enforced by: lint rule #E001
Examples: Xem error-examples.md"2. Năm thành phần của Standard hoàn chỉnh
| # | Component | Mô tả | Ví dụ |
|---|---|---|---|
| 1 | Specification | Rules rõ ràng, unambiguous | "Errors MUST have code field" |
| 2 | Examples | Real code showing correct usage | 3-5 examples per standard |
| 3 | Lint Rules | Automated checks | ESLint rule, OpenAPI validator |
| 4 | Tests | Prove standard works | Unit tests, contract tests |
| 5 | Migration Guide | How to transition | Step-by-step migration doc |
3. Chi tiết từng thành phần
3.1. Specification - Viết rules rõ ràng
Vague:
Errors should be descriptive and helpful.Specific:
## Error Response Specification
### MUST (Required)
- Error responses MUST include `code` field (string, SCREAMING_SNAKE_CASE)
- Error responses MUST include `message` field (string, user-readable)
- Error codes MUST be registered in error-catalog.md
### SHOULD (Recommended)
- Errors SHOULD include `details` object for field-level errors
- Errors SHOULD include `traceId` for debugging
### MAY (Optional)
- Errors MAY include `documentation` URLDùng RFC 2119 keywords:
| Keyword | Meaning |
|---|---|
| MUST | Bắt buộc, không exception |
| SHOULD | Recommended, exception với justification |
| MAY | Optional, purely a choice |
3.2. Examples - Code thực tế
"Không có examples = Developers interpret khác nhau = Standard fail"
Mỗi standard cần ít nhất 3 examples:
// Example 1: Validation Error (400)
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": {
"email": "Must be a valid email address",
"password": "Must be at least 8 characters"
}
}
}
// Example 2: Not Found Error (404)
{
"success": false,
"error": {
"code": "USER_NOT_FOUND",
"message": "The requested user does not exist"
}
}
// Example 3: Internal Error (500)
{
"success": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred",
"traceId": "abc-123-def-456"
}
}3.3. Lint Rules - Automated enforcement
// eslint-plugin-backend-ds/rules/error-format.js
module.exports = {
meta: {
type: "problem",
docs: {
description: "Enforce standard error format"
}
},
create(context) {
return {
// Check all throw statements
ThrowStatement(node) {
// Validate error has required fields
if (!hasRequiredFields(node)) {
context.report({
node,
message: "Error must have 'code' and 'message' fields"
});
}
}
};
}
};Ví dụ OpenAPI Spectral rule:
# .spectral.yaml
rules:
error-response-schema:
description: All 4xx/5xx responses must use standard error schema
given: "$.paths.*.*.responses[?(@property >= 400)]"
then:
field: content.application/json.schema.$ref
function: pattern
functionOptions:
match: "#/components/schemas/ErrorResponse"3.4. Tests - Prove it works
// tests/error-format.test.ts
describe('Error Response Format', () => {
it('should return correct format for validation error', async () => {
const response = await request(app)
.post('/users')
.send({ email: 'invalid' });
expect(response.status).toBe(400);
expect(response.body).toMatchObject({
success: false,
error: {
code: expect.stringMatching(/^[A-Z_]+$/),
message: expect.any(String)
}
});
});
it('should include traceId for 5xx errors', async () => {
// Force internal error
const response = await request(app)
.get('/trigger-error');
expect(response.status).toBe(500);
expect(response.body.error).toHaveProperty('traceId');
});
});3.5. Migration Guide - Smooth transition
# Migration Guide: Error Format v1 → v2
## Overview
- **Breaking change:** Yes
- **Estimated effort:** 2-4 hours per service
- **Deadline:** 2026-02-15
## Step-by-step
### Step 1: Update error-handler middleware (15 min)
Replace your current error handler with the new one:
```typescript
// OLD
catch(err) {
res.status(500).json({ message: err.message });
}
// NEW
import { formatError } from '@company/error-handler';
catch(err) {
res.status(getStatusCode(err)).json(formatError(err));
}Step 2: Update error codes (30 min - 1 hour)
Map your current error strings to standard codes:
| Old | New |
|---|---|
| "not found" | RESOURCE_NOT_FOUND |
| "invalid" | VALIDATION_ERROR |
| "unauthorized" | UNAUTHORIZED |
Step 3: Update tests (1-2 hours)
[...]
Rollback plan
If issues occur, revert to old middleware by [...]
---
## Nguyên tắc then chốt
> *"No examples = Developers interpret differently = Standard fails"*
Áp dụng:
1. **Mỗi rule cần ≥3 examples**
2. **Examples phải là real code**, không phải pseudo-code
3. **Include edge cases**, không chỉ happy path
```markdown
"Xem API spec để biết format"
Actual JSON response right in the docThực hành
Bài tập 1: Viết Definition of Done Checklist
Mục tiêu: Tạo checklist cho các loại changes
Yêu cầu: Tạo 3 checklists cho:
- API Changes
- Database Changes
- Event/Message Changes
Template:
# Definition of Done Checklists
## API Changes
- [ ] OpenAPI spec updated
- [ ] At least 3 request/response examples
- [ ] Breaking change analysis documented
- [ ] Migration guide (if breaking)
- [ ] Contract tests added
- [ ] Lint rules pass
- [ ] Reviewed by 2 team members
## Database Changes
- [ ] Migration script (up + down)
- [ ] Rollback plan documented
- [ ] Index analysis for new queries
- [ ] Data backfill strategy (if needed)
- [ ] Tested with production-like data volume
- [ ] DBA review (if > 1M rows affected)
## Event/Message Changes
- [ ] Schema version bumped
- [ ] Backward compatibility verified
- [ ] Consumer impact analyzed
- [ ] Deprecation timeline (if breaking)
- [ ] Example messages documented
- [ ] Dead letter queue handling definedXem gợi ý mở rộng
Thêm cho API Changes:
- Performance test nếu endpoint critical
- Rate limiting documented
- Caching strategy defined
Thêm cho Database:
- Estimated migration time
- Maintenance window required?
- Read replica impact
Bài tập 2: Audit một standard hiện có
Chọn một standard trong codebase của bạn và check:
| Component | Có? | Quality (1-5) | Action needed |
|---|---|---|---|
| Specification | ☐ | ||
| Examples (≥3) | ☐ | ||
| Lint rules | ☐ | ||
| Tests | ☐ | ||
| Migration Guide | ☐ |
Tình huống thực tế
Scenario 1: Standard không được follow
Bối cảnh: Bạn đã viết error format standard 3 tháng trước. Hôm nay review code và thấy 40% services vẫn return errors theo format cũ.
Câu hỏi:
- Root cause có thể là gì?
- Bạn sẽ fix như thế nào?
- Làm sao prevent tương lai?
Xem phân tích
Câu 1 - Root causes:
- Không có lint rule → Không ai check
- Không có examples → Devs không biết đúng/sai
- Không có migration guide → Old code không update
- Không communicate → Team không biết có standard
Câu 2 - Fix:
- Add lint rule ngay → CI fail nếu wrong format
- Add examples → Clear documentation
- Office hours session → Train team
- Migration sprint → Dedicated time to update old code
Câu 3 - Prevent:
- Every standard MUST have lint rule trước khi publish
- Every standard MUST be announced trong team meeting
- Quarterly audit → Check compliance
Scenario 2: "Quá nhiều bureaucracy"
Bối cảnh: Developer phàn nàn: "Để add một field vào API response, tôi phải update OpenAPI spec, thêm examples, viết migration guide, add tests... Quá nhiều overhead!"
Câu hỏi:
- Concern này valid không?
- Bạn sẽ respond như thế nào?
- Có cách nào reduce overhead?
Xem phân tích
Câu 1 - Valid concern: Partially valid. Nếu MỌI change đều cần full checklist → Too slow.
Câu 2 - Response: "Tôi hiểu concern. Checklist designed cho BREAKING changes. Minor additions không cần full checklist."
Câu 3 - Reduce overhead:
| Change Type | Required Items |
|---|---|
| Breaking change | Full checklist |
| New optional field | OpenAPI + 1 example |
| Bug fix | Tests only |
| Documentation | None |
"Thêm một optional field? Chỉ cần OpenAPI update + 1 example. 10 phút."
Câu hỏi phỏng vấn
Junior Level
Q1: Standard hoàn chỉnh cần có những gì?
Xem đáp án
Đáp án: 5 thành phần:
- Specification (clear rules)
- Examples (≥3)
- Lint rules (automation)
- Tests (proof it works)
- Migration guide (path forward)
Q2: Tại sao examples quan trọng?
Xem đáp án
Đáp án:
- Không có examples → Mỗi người interpret khác
- Examples = Single source of truth
- Real code > Pseudo-code
Mid Level
Q1: Bạn phát hiện 50% team không follow error standard. Next steps?
Xem đáp án
Good answer:
- Root cause analysis: Tại sao không follow?
- Không biết? → Communication issue
- Không enforce? → Add lint rule
- Quá khó? → Simplify standard
- Short-term fix: Add CI check, block non-compliant code
- Migration plan: Sprint để fix old code
- Long-term: Review process cho new standards
Senior Level
Q1: Design một governance system đảm bảo standards được follow trong org 100+ engineers.
Xem đáp án
Framework:
-
Publishing process:
- RFC cho new standards
- 2-week review period
- Automation REQUIRED trước publish
-
Enforcement layers:
- Layer 1: IDE plugins (instant feedback)
- Layer 2: Pre-commit hooks (local)
- Layer 3: CI checks (PR block)
- Layer 4: Production monitoring (alerts)
-
Compliance metrics:
- Dashboard: % compliance per team
- Weekly reports to Tech Lead
- Quarterly review với Engineering Manager
-
Exception process:
- Documented in ADR
- Time-boxed (6 months max)
- Owner assigned
-
Feedback loop:
- Monthly survey: "Is standard helpful?"
- Office hours: Q&A
- Retrospective: What's not working?
Tóm tắt
Những điều cần nhớ
| Concept | Giải thích |
|---|---|
| 5 Components | Spec, Examples, Lint, Tests, Migration |
| RFC 2119 | MUST, SHOULD, MAY - clear expectations |
| Examples rule | No examples = Standard fails |
| Proportional overhead | Breaking change → Full checklist; Minor → Light |
Key Takeaways
- Specification alone is not enough: Cần examples, automation, tests
- Automation > Documentation: Lint rules enforce, docs just suggest
- Migration guides are essential: Old code needs path forward
Checklist hoàn thành
- Hiểu 5 components của standard hoàn chỉnh
- Tạo được Definition of Done checklist
- Biết dùng RFC 2119 keywords
- Có thể audit existing standards
Tài liệu tham khảo
Module tiếp theo
🎉 Chúc mừng! Bạn đã hoàn thành Module 1: Initialization & Scope.
Bạn đã học:
- Backend Design System là gì
- Cách scope MVP trong 2 tuần
- Definition of Done cho standards
Module tiếp theo: Module 2: API Contracts - Học cách thiết kế API contracts nhất quán, bao gồm response envelopes, error handling, và HTTP semantics.