ai-developer-skill-os 8.1.7 → 8.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.agents/README.md +3 -3
  2. package/.agents/skills/qk-code-review/SKILL.md +189 -0
  3. package/.agents/skills/qk-code-review/references/ai/ai-anti-patterns.md +28 -0
  4. package/.agents/skills/qk-code-review/references/ai/v8-schema-validation.md +65 -0
  5. package/.agents/skills/qk-code-review/references/cross-cutting/architecture-review-guide.md +212 -0
  6. package/.agents/skills/qk-code-review/references/cross-cutting/async-concurrency-patterns.md +515 -0
  7. package/.agents/skills/qk-code-review/references/cross-cutting/code-quality-universal.md +358 -0
  8. package/.agents/skills/qk-code-review/references/cross-cutting/code-review-best-practices.md +136 -0
  9. package/.agents/skills/qk-code-review/references/cross-cutting/common-bugs-checklist.md +124 -0
  10. package/.agents/skills/qk-code-review/references/cross-cutting/error-handling-principles.md +492 -0
  11. package/.agents/skills/qk-code-review/references/cross-cutting/n-plus-one-queries.md +309 -0
  12. package/.agents/skills/qk-code-review/references/cross-cutting/performance-review-guide.md +387 -0
  13. package/.agents/skills/qk-code-review/references/cross-cutting/security-review-guide.md +318 -0
  14. package/.agents/skills/qk-code-review/references/cross-cutting/sql-injection-prevention.md +308 -0
  15. package/.agents/skills/qk-code-review/references/cross-cutting/xss-prevention.md +264 -0
  16. package/.agents/skills/qk-code-review/references/languages/angular.md +768 -0
  17. package/.agents/skills/qk-code-review/references/languages/c.md +890 -0
  18. package/.agents/skills/qk-code-review/references/languages/cpp.md +893 -0
  19. package/.agents/skills/qk-code-review/references/languages/csharp.md +519 -0
  20. package/.agents/skills/qk-code-review/references/languages/css-less-sass.md +661 -0
  21. package/.agents/skills/qk-code-review/references/languages/django.md +985 -0
  22. package/.agents/skills/qk-code-review/references/languages/fastapi.md +580 -0
  23. package/.agents/skills/qk-code-review/references/languages/go.md +993 -0
  24. package/.agents/skills/qk-code-review/references/languages/java.md +409 -0
  25. package/.agents/skills/qk-code-review/references/languages/java8.md +586 -0
  26. package/.agents/skills/qk-code-review/references/languages/kotlin.md +1018 -0
  27. package/.agents/skills/qk-code-review/references/languages/nestjs.md +593 -0
  28. package/.agents/skills/qk-code-review/references/languages/php.md +684 -0
  29. package/.agents/skills/qk-code-review/references/languages/python.md +1073 -0
  30. package/.agents/skills/qk-code-review/references/languages/qt.md +757 -0
  31. package/.agents/skills/qk-code-review/references/languages/react.md +871 -0
  32. package/.agents/skills/qk-code-review/references/languages/ruby.md +964 -0
  33. package/.agents/skills/qk-code-review/references/languages/rust.md +846 -0
  34. package/.agents/skills/qk-code-review/references/languages/svelte.md +1064 -0
  35. package/.agents/skills/qk-code-review/references/languages/swift.md +936 -0
  36. package/.agents/skills/qk-code-review/references/languages/typescript.md +1016 -0
  37. package/.agents/skills/qk-code-review/references/languages/vue.md +924 -0
  38. package/.agents/skills/qk-code-review/references/languages/zig.md +440 -0
  39. package/README.md +3 -3
  40. package/bin/install.js +5 -2
  41. package/package.json +1 -1
@@ -0,0 +1,358 @@
1
+ # Các Anti-Pattern Chất lượng Code Phổ quát (Universal Code Quality)
2
+
3
+ > Hướng dẫn nhận diện các anti-pattern về chất lượng code độc lập với ngôn ngữ, bao quát các chủ đề: Tái sử dụng code, Rò rỉ trừu tượng (Leaky abstraction), Phình to tham số (Parameter bloat), Câu lệnh điều kiện lồng nhau, Magic strings, TOCTOU, Cập nhật vô nghĩa (No-op update), v.v. Áp dụng cho mọi PR.
4
+
5
+ ## Mục lục
6
+
7
+ - [Kiểm tra Tái sử dụng Code (Code Reuse)](#kiểm-tra-tái-sử-dụng-code)
8
+ - [Phình to Tham số (Parameter Bloat)](#phình-to-tham-số)
9
+ - [Rò rỉ Trừu tượng (Leaky Abstraction)](#rò-rỉ-trừu-tượng)
10
+ - [Lạm dụng Chuỗi (String Typing)](#lạm-dụng-chuỗi)
11
+ - [Điều kiện Lồng nhau (Nested Conditions)](#điều-kiện-lồng-nhau)
12
+ - [Biến thể Copy-Paste (Copy-Paste Variations)](#biến-thể-copy-paste)
13
+ - [Cập nhật Vô nghĩa (No-Op Updates)](#cập-nhật-vô-nghĩa)
14
+ - [Lỗi tương tranh TOCTOU (Race Conditions)](#lỗi-tương-tranh-toctou)
15
+ - [Thao tác quá rộng (Broad Operations)](#thao-tác-quá-rộng)
16
+ - [Trạng thái Dư thừa (Redundant State)](#trạng-thái-dư-thừa)
17
+ - [Checklist Chất lượng Chung](#checklist-chất-lượng-chung)
18
+
19
+ ---
20
+
21
+ ## Kiểm tra Tái sử dụng Code (Code Reuse)
22
+
23
+ Trước khi chấp nhận code mới, hãy tìm kiếm trong source code xem đã có các hàm tiện ích (utilities) dùng chung nào chưa.
24
+
25
+ ### Tận dụng Utility có sẵn
26
+
27
+ ```python
28
+ # ❌ Viết lại logic nối đường dẫn —— Trong project đã có sẵn PathBuilder
29
+ def get_config_path(name):
30
+ base = os.environ.get("APP_ROOT", ".")
31
+ return os.path.join(base, "config", name + ".json")
32
+
33
+ # ✅ Dùng PathBuilder đã có
34
+ def get_config_path(name):
35
+ return PathBuilder.config(f"{name}.json")
36
+ ```
37
+
38
+ ```javascript
39
+ // ❌ Tự viết tay hàm debounce —— Project đã có lodash hoặc utils/debounce.ts
40
+ function debounce(fn, ms) {
41
+ let timer;
42
+ return (...args) => {
43
+ clearTimeout(timer);
44
+ timer = setTimeout(() => fn(...args), ms);
45
+ };
46
+ }
47
+
48
+ // ✅ Import hàm utility có sẵn
49
+ import { debounce } from "@/utils/debounce";
50
+ ```
51
+
52
+ **Checklist:**
53
+ - [ ] Hàm mới viết có bị trùng tên hoặc trùng chức năng với utility có sẵn không?
54
+ - [ ] Đoạn logic viết inline có thể thay thế bằng hàm dùng chung không?
55
+ - [ ] Đã ngó qua thư mục `shared/utils` chưa?
56
+
57
+ ---
58
+
59
+ ## Phình to Tham số (Parameter Bloat)
60
+
61
+ ### Hàm có quá nhiều tham số
62
+
63
+ ```python
64
+ # ❌ Cứ có yêu cầu mới là nhét thêm 1 tham số
65
+ def create_user(name, email, role, team, active, avatar_url, timezone):
66
+ ...
67
+
68
+ # ✅ Nhóm thành DataClass / Config Object
69
+ @dataclass
70
+ class CreateUserParams:
71
+ name: str
72
+ email: str
73
+ role: Role = Role.MEMBER
74
+ team: str | None = None
75
+ active: bool = True
76
+ avatar_url: str | None = None
77
+ timezone: str = "UTC"
78
+
79
+ def create_user(params: CreateUserParams) -> User:
80
+ ...
81
+ ```
82
+
83
+ ```typescript
84
+ // ❌ Hàm nhận 6 tham số cứng (positional arguments)
85
+ function renderWidget(title: string, width: number, height: number, theme: string, collapsible: boolean, icon: string) { ... }
86
+
87
+ // ✅ Pattern Options Object
88
+ interface WidgetOptions {
89
+ title: string;
90
+ width?: number;
91
+ height?: number;
92
+ theme?: "light" | "dark";
93
+ collapsible?: boolean;
94
+ icon?: string;
95
+ }
96
+ function renderWidget(options: WidgetOptions) { ... }
97
+ ```
98
+
99
+ **Checklist:**
100
+ - [ ] Hàm có từ 4 tham số trở lên không? Hãy đổi sang Options Object.
101
+ - [ ] Tham số mới thêm vào chỉ là một cái Cờ (Boolean flag)? Cân nhắc dùng Enum hoặc Strategy Pattern.
102
+ - [ ] Có tham số nào triệt tiêu nhau không? (Vd: `enable_x` và `disable_y`).
103
+
104
+ ---
105
+
106
+ ## Rò rỉ Trừu tượng (Leaky Abstraction)
107
+
108
+ ### Để lọt chi tiết Implementation ra ngoài
109
+
110
+ ```python
111
+ # ❌ Trả về Object của ORM —— Ép caller phải biết về thư viện SQLAlchemy
112
+ def get_users():
113
+ return session.query(User).filter(User.active == True).all()
114
+
115
+ # ✅ Trả về Domain Object (DTO), giấu tịt lớp Database đi
116
+ def get_active_users() -> list[UserDTO]:
117
+ rows = user_repo.find_active()
118
+ return [UserDTO.from_row(r) for r in rows]
119
+ ```
120
+
121
+ ```typescript
122
+ // ❌ Component nhận trực tiếp cấu trúc của API Response
123
+ <UserCard user={apiResponse.data.results[0]} />
124
+
125
+ // ✅ Component chỉ nhận Domain Type, dùng Adapter để chuyển đổi
126
+ interface UserSummary {
127
+ displayName: string;
128
+ avatarUrl: string;
129
+ }
130
+ <UserCard user={adaptUser(apiResponse)} />
131
+ ```
132
+
133
+ **Checklist:**
134
+ - [ ] Kiểu trả về (Return type) của hàm có làm lộ thư viện bên dưới không (ORM, HTTP Client, JSON format)?
135
+ - [ ] Component UI có bị dính chặt vào cấu trúc của hệ thống bên ngoài không?
136
+
137
+ ---
138
+
139
+ ## Lạm dụng Chuỗi (String Typing / Magic Strings)
140
+
141
+ ### Dùng String trần trụi thay vì Enum/Constant
142
+
143
+ ```python
144
+ # ❌ Magic strings rải rác khắp nơi, gõ sai chính tả là ăn lỗi
145
+ if status == "active": ...
146
+ if role == "admin": ...
147
+
148
+ # ✅ Gom thành Enum
149
+ class Status(StrEnum):
150
+ ACTIVE = "active"
151
+ SUSPENDED = "suspended"
152
+
153
+ if user.status == Status.ACTIVE: ...
154
+ ```
155
+
156
+ ```typescript
157
+ // ❌ Tên event bằng string —— Code editor không gợi ý, gõ sai không báo lỗi
158
+ emitter.emit("userCreated", data);
159
+ emitter.on("usercreated", handler); // BUG do gõ sai chữ C thành c
160
+
161
+ // ✅ Dùng Object Constant / Enum
162
+ const Events = {
163
+ USER_CREATED: "userCreated",
164
+ } as const;
165
+ emitter.emit(Events.USER_CREATED, data);
166
+ ```
167
+
168
+ **Checklist:**
169
+ - [ ] Có string nào dùng để đại diện cho Trạng thái (Status) / Loại (Type) mà chưa gom vào Enum không?
170
+
171
+ ---
172
+
173
+ ## Điều kiện Lồng nhau (Nested Conditions)
174
+
175
+ ### Khối lệnh IF/ELSE lồng nhau sâu hoắm
176
+
177
+ ```python
178
+ # ❌ Chuỗi Ternary (Toán tử 3 ngôi) dài dòng
179
+ label = (
180
+ "Admin" if role == "admin" else
181
+ "Manager" if role == "manager" else
182
+ "Viewer" if role == "viewer" else
183
+ "Unknown"
184
+ )
185
+
186
+ # ✅ Dùng Lookup Table (Dictionary / Map)
187
+ ROLE_LABELS = {
188
+ "admin": "Admin",
189
+ "manager": "Manager",
190
+ "viewer": "Viewer",
191
+ }
192
+ label = ROLE_LABELS.get(role, "Unknown")
193
+ ```
194
+
195
+ ```python
196
+ # ❌ IF lồng 3 lớp (Arrow code / Hadouken code)
197
+ def process(order):
198
+ if order is not None:
199
+ if order.items:
200
+ for item in order.items:
201
+ if item.price > 0:
202
+ ...
203
+
204
+ # ✅ Early Return (Bảo vệ từ sớm)
205
+ def process(order):
206
+ if not order or not order.items:
207
+ return
208
+ for item in order.items:
209
+ if item.price <= 0:
210
+ continue
211
+ ...
212
+ ```
213
+
214
+ **Checklist:**
215
+ - [ ] Toán tử 3 ngôi lồng nhau $\ge$ 2 lớp?
216
+ - [ ] IF/ELSE lồng nhau $\ge$ 3 lớp?
217
+ - [ ] Có thể thay thế bằng Lookup Table, Match/Switch, hoặc Early Return không?
218
+
219
+ ---
220
+
221
+ ## Biến thể Copy-Paste (Copy-Paste Variations)
222
+
223
+ ### Các khối code giống hệt nhau, chỉ khác mỗi cái tên
224
+
225
+ ```typescript
226
+ // ❌ Copy-paste handler, chỉ thay đổi cái URL
227
+ async function deletePost(id: string) {
228
+ await fetch(`/api/posts/${id}`, { method: "DELETE" });
229
+ router.push("/posts");
230
+ }
231
+ async function deleteComment(id: string) {
232
+ await fetch(`/api/comments/${id}`, { method: "DELETE" });
233
+ router.push("/comments");
234
+ }
235
+
236
+ // ✅ Parameter hóa (Truyền biến vào)
237
+ async function deleteResource(resource: string, id: string) {
238
+ await fetch(`/api/${resource}/${id}`, { method: "DELETE" });
239
+ router.push(`/${resource}`);
240
+ }
241
+ ```
242
+
243
+ **Checklist:**
244
+ - [ ] Có $\ge$ 2 đoạn code y hệt nhau, chỉ khác mỗi biến/URL/chữ không? Đưa thành hàm chung có tham số đi.
245
+
246
+ ---
247
+
248
+ ## Cập nhật Vô nghĩa (No-Op Updates)
249
+
250
+ ### Chọc vào State/DB ngay cả khi dữ liệu không đổi
251
+
252
+ ```typescript
253
+ // ❌ Cứ mỗi 5 giây là setStatus một lần mặc kệ data có đổi hay không (khiến UI re-render)
254
+ useEffect(() => {
255
+ const interval = setInterval(() => {
256
+ fetch("/api/status").then(r => r.json()).then(setStatus);
257
+ }, 5000);
258
+ return () => clearInterval(interval);
259
+ }, []);
260
+
261
+ // ✅ Kiểm tra trước khi set
262
+ setStatus(prev => isEqual(prev, data) ? prev : data);
263
+ ```
264
+
265
+ ```python
266
+ # ❌ Vòng lặp liên tục update DB dù giá trị bằng y hệt cũ
267
+ for item in items:
268
+ item.status = compute_status(item)
269
+ session.commit()
270
+
271
+ # ✅ Chỉ update nếu có thay đổi (Dirty check)
272
+ for item in items:
273
+ new_status = compute_status(item)
274
+ if item.status != new_status:
275
+ item.status = new_status
276
+ session.commit()
277
+ ```
278
+
279
+ ---
280
+
281
+ ## Lỗi tương tranh TOCTOU (Time-of-Check-to-Time-of-Use)
282
+
283
+ ### "Kiểm tra trước - Làm sau" trong môi trường Đồng thời (Concurrency)
284
+
285
+ ```python
286
+ # ❌ Kiểm tra file tồn tại rồi mới mở -> Nhỡ lúc mở file nó bị xóa rồi thì sao?
287
+ if os.path.exists(path):
288
+ with open(path) as f:
289
+ data = f.read()
290
+
291
+ # ✅ Cứ mở file đi, lỗi thì Bắt (Try/Catch)
292
+ try:
293
+ with open(path) as f:
294
+ data = f.read()
295
+ except FileNotFoundError:
296
+ data = None
297
+ ```
298
+
299
+ ```python
300
+ # ❌ Lỗi kinh điển hệ thống ngân hàng: Kiểm tra số dư rồi mới trừ tiền (Không Atomic)
301
+ if account.balance >= amount:
302
+ account.balance -= amount
303
+
304
+ # ✅ Bỏ vào Giao dịch (Transaction) hoặc Khóa (Lock)
305
+ with account.lock:
306
+ if account.balance < amount:
307
+ raise InsufficientFundsError()
308
+ account.balance -= amount
309
+ ```
310
+
311
+ ---
312
+
313
+ ## Thao tác quá rộng (Broad Operations)
314
+
315
+ ### Lấy nguyên xe tải hàng trong khi chỉ cần 1 củ tỏi
316
+
317
+ ```typescript
318
+ // ❌ Lấy nguyên bảng Orders về RAM chỉ để lọc ra 2 đơn hàng Pending
319
+ const allItems = await db.query("SELECT * FROM orders");
320
+ const pending = allItems.filter(o => o.status === "pending");
321
+
322
+ // ✅ Đẩy việc lọc (Filter) xuống cho Database làm
323
+ const pending = await db.query(
324
+ "SELECT * FROM orders WHERE status = ?", ["pending"]
325
+ );
326
+ ```
327
+
328
+ ```python
329
+ # ❌ Đọc nguyên cái file log bự chà bá chỉ để lấy Dòng số 1
330
+ content = Path("log.txt").read_text()
331
+ first_line = content.split("\n")[0]
332
+
333
+ # ✅ Đọc đúng 1 dòng (Stream)
334
+ with open("log.txt") as f:
335
+ first_line = f.readline()
336
+ ```
337
+
338
+ ---
339
+
340
+ ## Trạng thái Dư thừa (Redundant State)
341
+
342
+ ### Trạng thái có thể Tự suy luận (Derived)
343
+
344
+ ```typescript
345
+ // ❌ Lưu trữ thừa mứa: Đã có firstName và lastName rồi còn lưu fullName làm gì?
346
+ interface User {
347
+ firstName: string;
348
+ lastName: string;
349
+ fullName: string; // Redundant! Nếu update firstName mà quên update fullName là Toang!
350
+ }
351
+
352
+ // ✅ Tính toán tự động dựa trên gốc
353
+ interface User {
354
+ firstName: string;
355
+ lastName: string;
356
+ }
357
+ const fullName = `${user.firstName} ${user.lastName}`;
358
+ ```
@@ -0,0 +1,136 @@
1
+ # Best Practice Review Code (Code Review Best Practices)
2
+
3
+ Bí kíp toàn diện để tiến hành Code Review một cách hiệu quả và chuyên nghiệp.
4
+
5
+ ## Triết lý Review (Review Philosophy)
6
+
7
+ ### Mục tiêu của Code Review
8
+
9
+ **Mục tiêu Chính:**
10
+ - Bắt lỗi (bugs) và các trường hợp biên (edge cases) trước khi đẩy lên Production.
11
+ - Đảm bảo code dễ bảo trì (maintainability) và dễ đọc (readability).
12
+ - Chia sẻ kiến thức (knowledge sharing) giữa các thành viên trong team.
13
+ - Ép buộc tuân thủ chuẩn code (coding standards) một cách nhất quán.
14
+ - Cải thiện các quyết định về Thiết kế và Kiến trúc.
15
+
16
+ **Mục tiêu Phụ:**
17
+ - Hướng dẫn (Mentor) cho các developer trẻ.
18
+ - Xây dựng văn hóa và sự tin tưởng trong team.
19
+ - Document lại các quyết định thiết kế thông qua quá trình thảo luận.
20
+
21
+ ### Code Review KHÔNG PHẢI là:
22
+
23
+ - Một công cụ gác cổng hạch sách để cản trở tiến độ.
24
+ - Một nơi để phô trương kiến thức cá nhân.
25
+ - Nơi để bắt bẻ từng dấu phẩy, dấu cách (Việc đó để linter tự động làm).
26
+ - Nơi để ép người khác viết lại code theo sở thích cá nhân của mình.
27
+
28
+ ## Thời điểm Review (Review Timing)
29
+
30
+ ### Khi nào thì Review?
31
+
32
+ | Kích hoạt (Trigger) | Hành động (Action) |
33
+ |---------|--------|
34
+ | PR vừa mở | Review trong vòng 24 giờ, lý tưởng nhất là trong ngày |
35
+ | PR đã sửa theo yêu cầu | Re-review lại trong vòng 4 giờ |
36
+ | Phát hiện lỗi chí mạng (Blocking) | Thông báo ngay lập tức |
37
+
38
+ ### Phân bổ thời gian
39
+
40
+ - **PR Nhỏ (<100 lines)**: 10-15 phút
41
+ - **PR Vừa (100-400 lines)**: 20-40 phút
42
+ - **PR Lớn (>400 lines)**: Yêu cầu chia nhỏ ra, hoặc dành >60 phút để review
43
+
44
+ ## Các cấp độ Review (Review Depth Levels)
45
+
46
+ ### Level 1: Skim Review (Lướt nhanh - 5 phút)
47
+ - Đọc mô tả PR và các Issues được đính kèm.
48
+ - Kiểm tra trạng thái của CI/CD (Test có pass không).
49
+ - Lướt qua danh sách các file thay đổi.
50
+ - Xác định xem có cần Review sâu hơn không.
51
+
52
+ ### Level 2: Standard Review (Chuẩn mực - 20-30 phút)
53
+ - Đọc lướt toàn bộ luồng code (Walkthrough).
54
+ - Kiểm tra logic có đúng không.
55
+ - Kiểm tra xem có viết Test Cover không.
56
+ - Quét nhanh các vấn đề bảo mật.
57
+
58
+ ### Level 3: Deep Review (Chuyên sâu - >60 phút)
59
+ - Đánh giá kiến trúc hệ thống.
60
+ - Phân tích hiệu năng (Performance).
61
+ - Kiểm toán Bảo mật (Security audit).
62
+ - Khám phá các rủi ro ở trường hợp biên (Edge cases).
63
+
64
+ ## Nguyên tắc Giao tiếp (Communication Guidelines)
65
+
66
+ ### Thái độ và Ngôn từ
67
+
68
+ **Sử dụng ngôn từ hợp tác:**
69
+ - "Bạn nghĩ sao về việc..." thay vì "Bạn phải làm thế này..."
70
+ - "Chúng ta có thể thử cân nhắc..." thay vì "Cái này sai rồi!"
71
+ - "Mình hơi thắc mắc chỗ này..." thay vì "Tại sao bạn không..."
72
+
73
+ **Cụ thể và có tính Action (Actionable):**
74
+ - Đưa ra ví dụ code (code examples) khi đề xuất thay đổi.
75
+ - Kèm link đến tài liệu (docs) hoặc các cuộc thảo luận cũ.
76
+ - Giải thích "TẠI SAO" (Why) lại đưa ra lời khuyên đó.
77
+
78
+ ### Xử lý Bất đồng (Handling Disagreements)
79
+
80
+ 1. **Cố gắng thấu hiểu**: Đặt câu hỏi làm rõ ý của người kia.
81
+ 2. **Ghi nhận điểm đúng**: Cho thấy bạn đã suy nghĩ ở góc độ của họ.
82
+ 3. **Đưa ra bằng chứng**: Dùng benchmark, docs, hoặc ví dụ cụ thể.
83
+ 4. **Escalate (Nâng cấp) nếu cần**: Mời Senior Dev hoặc Architect vào phân xử.
84
+ 5. **Biết khi nào nên dừng lại**: Không phải cuộc tranh cãi nào cũng đáng để sống chết bảo vệ.
85
+
86
+ ## Phân loại Mức độ Ưu tiên (Review Prioritization)
87
+
88
+ ### 🔴 Must Fix (Bắt buộc sửa / Blocking)
89
+ - Lỗ hổng Bảo mật (Security vulnerabilities).
90
+ - Nguy cơ làm hỏng / mất dữ liệu (Data corruption).
91
+ - Các thay đổi làm gãy (Breaking changes) mà không có kịch bản chuyển đổi (migration).
92
+ - Lỗi hiệu năng chí mạng.
93
+ - Quên không bắt lỗi (Error handling) ở các tính năng hiển thị cho End-user.
94
+
95
+ ### 🟡 Should Fix (Nên sửa / Important)
96
+ - Bỏ sót chưa viết Test (Test coverage gaps).
97
+ - Rủi ro hiệu năng ở mức vừa phải.
98
+ - Code bị lặp lại (Duplication).
99
+ - Đặt tên tối nghĩa hoặc Cấu trúc rối rắm.
100
+ - Logic quá phức tạp mà không có comment giải thích.
101
+
102
+ ### 🟢 Nice to Have (Có thì tốt / Non-blocking)
103
+ - Sở thích về Style code (nằm ngoài scope của Linter).
104
+ - Các tối ưu nhỏ lẻ (Minor optimizations).
105
+ - Thêm thắt vài Test case phụ.
106
+ - Cải thiện câu từ trong Document.
107
+
108
+ ## Anti-Patterns cần tránh
109
+
110
+ ### Anti-Patterns của người Review
111
+ - **Rubber stamping (Đóng dấu bừa)**: Bấm Approve (Duyệt) mà không thèm xem code.
112
+ - **Bike shedding (Tranh cãi chuyện ruồi muỗi)**: Cãi nhau nảy lửa về những tiểu tiết vớ vẩn.
113
+ - **Scope creep (Tiện tay dắt dê)**: "Nhân tiện bạn đang sửa file này, bạn làm thêm cái tính năng X này nhé..."
114
+ - **Ghosting (Bốc hơi)**: Thả 1 đống Request Changes rồi lặn mất tăm, không thèm quay lại xem người ta sửa chưa.
115
+ - **Perfectionism (Chủ nghĩa hoàn hảo)**: Chặn PR (Block) chỉ vì vài khác biệt nhỏ về phong cách cá nhân.
116
+
117
+ ### Anti-Patterns của người Viết Code (Author)
118
+ - **Mega PRs (PR Siêu to khổng lồ)**: Gửi 1 cục PR dài >1000 dòng bắt người ta ngồi đọc.
119
+ - **No context (Không có ngữ cảnh)**: Để trống mô tả PR, không link issue nào.
120
+ - **Defensive responses (Xù lông nhím)**: Cãi lại mọi lời góp ý, khăng khăng mình đúng.
121
+ - **Silent updates (Sửa trong im lặng)**: Lẳng lặng commit sửa code nhưng không thèm Reply lại các comment báo cho người Review biết.
122
+
123
+ ## Số liệu và Cải tiến (Metrics and Improvement)
124
+
125
+ ### Nên theo dõi các Số liệu sau
126
+ - Thời gian từ lúc mở PR đến lúc có Review đầu tiên (Time to first review).
127
+ - Tổng thời gian hoàn thành một vòng Review (Review cycle time).
128
+ - Số vòng Review phải đập đi xây lại (Number of review rounds).
129
+ - Tỷ lệ lỗi lọt qua lưới (Defect escape rate).
130
+ - Tỷ lệ Cover của quá trình Review.
131
+
132
+ ### Cải tiến liên tục
133
+ - Tổ chức các buổi Retrospective để bàn về quy trình Review.
134
+ - Chia sẻ bài học từ các con Bug lọt ra Production.
135
+ - Cập nhật các Checklist Review liên tục dựa trên các lỗi hay gặp.
136
+ - Tuyên dương những bài Review chất lượng, bắt được lỗi hiểm hóc.
@@ -0,0 +1,124 @@
1
+ # Checklist Lỗi Phổ biến (Common Bugs Checklist)
2
+
3
+ Bảng tra cứu nhanh các mẫu lỗi thường gặp, được phân loại theo từng nhóm. Để xem ví dụ chi tiết, giải thích sâu hơn và checklist đầy đủ, vui lòng tham khảo cẩm nang của từng ngôn ngữ cụ thể được liên kết bên dưới.
4
+
5
+ ## Các vấn đề Phổ quát (Universal Issues)
6
+
7
+ ### Lỗi Logic
8
+ - [ ] Lỗi lệch một đơn vị (Off-by-one errors) trong vòng lặp và truy xuất mảng.
9
+ - [ ] Lỗi logic Boolean (Vi phạm định luật De Morgan).
10
+ - [ ] Quên kiểm tra null/undefined.
11
+ - [ ] Lỗi tương tranh (Race conditions) trong môi trường đồng thời (concurrent).
12
+ - [ ] Dùng sai toán tử so sánh (Ví dụ: `==` thay vì `===`, hoặc `=` thay vì `==`).
13
+ - [ ] Tràn số nguyên (Integer overflow/underflow).
14
+ - [ ] Sai số khi so sánh số thực dấu phẩy động (Floating point comparison issues).
15
+
16
+ ### Quản lý Tài nguyên
17
+ - [ ] Rò rỉ bộ nhớ (Memory leaks) do quên đóng connection, listener.
18
+ - [ ] Quên đóng File handles.
19
+ - [ ] Quên trả lại Database connections vào Pool.
20
+ - [ ] Quên gỡ Event listeners khi không còn dùng.
21
+ - [ ] Quên xóa Timers/intervals (gọi `clearTimeout` / `clearInterval`).
22
+
23
+ ### Xử lý Lỗi (Error Handling)
24
+ - [ ] Nuốt lỗi (Swallowed exceptions) bằng các khối `catch` để trống.
25
+ - [ ] Catch lỗi quá rộng (Generic exception handling) làm che mất lỗi thực sự.
26
+ - [ ] Quên đẩy (propagate) lỗi lên cấp trên.
27
+ - [ ] Ném ra (Throw) sai loại Exception.
28
+ - [ ] Thiếu khối `finally` để dọn dẹp tài nguyên.
29
+
30
+ ## TypeScript/JavaScript
31
+
32
+ - [ ] Dùng `==` thay vì `===`.
33
+ - [ ] Lạm dụng `any` — Khuyến khích dùng type cụ thể hoặc `unknown` kết hợp type guards.
34
+ - [ ] Quên `await` khi gọi hàm bất đồng bộ.
35
+ - [ ] Không bắt lỗi promise rejections (Thiếu `try-catch` khi gọi `await`).
36
+ - [ ] Bị mất context `this` khi gọi callback.
37
+ - [ ] Quên truyền prop `key` khi render danh sách (list).
38
+ - [ ] Closure vô tình giữ lại biến cũ của vòng lặp (stale loop variable).
39
+ - [ ] Gọi `parseInt` mà không truyền tham số cơ số (radix).
40
+ - [ ] Sửa đổi trực tiếp (Modify) mảng/object trong khi đang lặp qua nó.
41
+
42
+ ## React / React 19
43
+
44
+ - [ ] Gọi Hooks bên trong lệnh if hoặc vòng lặp (Vi phạm Rules of Hooks).
45
+ - [ ] Mảng phụ thuộc (dependency array) của `useEffect` bị thiếu hoặc sai.
46
+ - [ ] `useEffect` thiếu hàm cleanup (đối với các subscriptions, timers, fetches).
47
+ - [ ] Lạm dụng `useEffect` để tính toán state suy diễn (Derived state) — thay vào đó hãy dùng `useMemo`.
48
+ - [ ] Lạm dụng `useMemo`/`useCallback`, hoặc dùng mà không đi kèm `React.memo`.
49
+ - [ ] Định nghĩa Component con ngay bên trong Component cha (Khiến component bị re-mount mỗi lần render).
50
+ - [ ] Truyền props không ổn định (inline object/function) cho các component đã được `memo`.
51
+ - [ ] Thay đổi trực tiếp (Mutate) vào props.
52
+ - [ ] Thiếu `key` trong mảng, hoặc lấy `index` làm key cho các mảng có khả năng sắp xếp lại (reorder).
53
+
54
+ ## Python
55
+
56
+ - [ ] Dùng mutable data làm giá trị mặc định (`def f(x=[])`).
57
+ - [ ] Dùng `except:` trần trụi (sẽ bắt nhầm luôn cả `KeyboardInterrupt` và `SystemExit`).
58
+ - [ ] Chia sẻ thuộc tính (Shared mutable attributes) sai cách ở cấp độ Class (`class C: items = []`).
59
+ - [ ] Dùng `is` thay vì `==` để so sánh giá trị (value comparison).
60
+ - [ ] Quên khai báo tham số `self` trong các phương thức của Class.
61
+ - [ ] Thay đổi danh sách (Modify list) trong khi đang duyệt (iterating).
62
+ - [ ] Cộng chuỗi trong vòng lặp (Khuyến khích dùng `"".join()`).
63
+ - [ ] Quên đóng file (Nên dùng câu lệnh `with`).
64
+ - [ ] Thiếu Type annotations (khai báo kiểu) ở các public functions.
65
+
66
+ ## Go
67
+
68
+ - [ ] Phớt lờ lỗi (`result, _ := SomeFunction()`).
69
+ - [ ] Chạy Goroutine mà không có cơ chế thoát (Gây rò rỉ bộ nhớ).
70
+ - [ ] Quên truyền, hoặc truyền sai `context.Context`.
71
+ - [ ] Lỗi Capture biến của vòng lặp (Ở các bản Go < 1.22).
72
+ - [ ] Gọi `defer` ở trong vòng lặp (Chỉ được thực thi khi kết thúc hàm, KHÔNG PHẢI kết thúc vòng lặp).
73
+ - [ ] Khai báo đè biến (Variable shadowing).
74
+ - [ ] Dùng Map trước khi khởi tạo (`make`).
75
+ - [ ] Bọc lỗi (Error wrapping) bằng `%v` thay vì `%w` (Làm hỏng `errors.Is`/`errors.As`).
76
+
77
+ ## Java / Spring Boot
78
+
79
+ - [ ] Viết dài dòng cho POJO/DTO thay vì dùng `record` *(Java 17+)*.
80
+ - [ ] Quên `break` trong switch truyền thống (Nên dùng switch expressions) *(Java 14+)*.
81
+ - [ ] Dùng Field injection (`@Autowired` thẳng vào biến) thay vì Constructor injection.
82
+ - [ ] Lỗi N+1 query trong JPA (Quên `fetch join` hoặc `@EntityGraph`).
83
+ - [ ] Gọi `Optional.get()` mà không chịu check `isPresent()` trước.
84
+ - [ ] Stream operations có chứa side effects.
85
+
86
+ ## PHP
87
+
88
+ - [ ] Thiếu `declare(strict_types=1);` ở đầu file mới.
89
+ - [ ] So sánh yếu (`==`, `!=`) ở những chỗ nhạy cảm như login, token, thanh toán.
90
+ - [ ] Dùng `in_array()` / `array_search()` mà không bật chế độ nghiêm ngặt (strict mode).
91
+ - [ ] Nối chuỗi để build câu lệnh SQL (Dễ dính SQL Injection) thay vì dùng Prepared statements.
92
+ - [ ] In dữ liệu user (echo) mà không escape (Dễ dính XSS).
93
+ - [ ] Lưu password bằng `md5()` / `sha1()` thay vì `password_hash()`.
94
+ - [ ] Che giấu lỗi bằng dấu `@` hoặc nuốt lỗi bằng `catch` để trống.
95
+
96
+ ## SQL
97
+
98
+ - [ ] Nối chuỗi để tạo query (Rủi ro SQL Injection) — luôn dùng Parameterized queries.
99
+ - [ ] Bỏ quên Index ở những cột hay bị filter/join.
100
+ - [ ] Dùng `SELECT *` thay vì chọn các cột cụ thể.
101
+ - [ ] Mẫu truy vấn N+1 (N+1 query patterns).
102
+ - [ ] Truy vấn bảng lớn mà không có `LIMIT`.
103
+ - [ ] So sánh `NULL` sai cách (`IS NULL` vs `= NULL`).
104
+ - [ ] Quên bao bọc các thao tác liên quan vào trong một Transaction.
105
+ - [ ] Chọn sai loại JOIN.
106
+
107
+ ## Thiết kế API (API Design)
108
+
109
+ - [ ] Đặt tên endpoint (resource) thiếu nhất quán.
110
+ - [ ] Chọn sai HTTP methods (Ví dụ: Dùng POST cho một thao tác Idempotent thay vì PUT/PATCH).
111
+ - [ ] API lấy danh sách mà không có phân trang (pagination).
112
+ - [ ] Trả về sai HTTP Status codes.
113
+ - [ ] Không giới hạn số lượng request (Thiếu Rate limiting).
114
+ - [ ] Thiếu kiểm duyệt (validation) và làm sạch dữ liệu đầu vào.
115
+ - [ ] Chỉ tin tưởng hoàn toàn vào sự kiểm duyệt từ phía Client.
116
+
117
+ ## Testing
118
+
119
+ - [ ] Chỉ chăm chăm test các chi tiết bên trong (Implementation details) thay vì test hành vi (Behavior) hiển thị ra bên ngoài.
120
+ - [ ] Bỏ sót các trường hợp Edge case (trường hợp biên).
121
+ - [ ] Test chạy lúc pass lúc fail (Flaky tests / Non-deterministic).
122
+ - [ ] Test chạy thẳng vào External dependencies (Thiếu mocks).
123
+ - [ ] Thiếu test cho các trường hợp báo lỗi (Negative tests).
124
+ - [ ] Setup bài test quá phức tạp.