Bản đồ công trìnhTờ này lắp: API, Thanh toán VietQR
Bài nàyĐã họcChưa tớiĐã thay thế
Bạn sẽ học được gì
Tiêu chí nghiệm thu
Vì sao người không viết code vẫn cần đọc code
Bạn có thể hỏi: “AI viết code rồi, tôi đọc làm gì?” Hãy nghĩ tới việc chị Lan duyệt công thức bánh mới do thợ đề xuất. Chị không cần tự nướng, nhưng chị phải đọc được “200g đường cho một chiếc bánh 16cm” và biết ngay là quá ngọt.
Code cũng vậy. Phần lớn code trong một ứng dụng quản lý đơn hàng là logic nghiệp vụ được viết bằng ngôn ngữ máy: tính tiền, kiểm tra điều kiện, chuyển trạng thái. Nếu đọc được, bạn sẽ:
- Phát hiện AI cài sai quy tắc của bạn (miễn phí ship từ 500.000đ hay trên 500.000đ?).
- Hiểu thông báo lỗi thay vì chỉ chép dán cho AI và cầu may.
- Review thay đổi của agent nhanh hơn, tập trung đúng chỗ quan trọng.
Toàn bộ ví dụ trong bài viết bằng TypeScript, ngôn ngữ chính của dự án Bánh Mộc. TypeScript là JavaScript có thêm “nhãn kiểu”, sẽ được giải thích ở cuối bài.
Biến và hằng: những chiếc hộp có nhãn
Biến (variable) là một chiếc hộp có dán nhãn để đựng một giá trị. Trong tiệm bánh, hãy hình dung các hộp nguyên liệu trên kệ, mỗi hộp có nhãn: “đường”, “bột mì”, “bơ”.
const tenKhach = "Chị Hương"; // hằng: hộp dán chết, không đổi nội dung
let soLuong = 1; // biến: hộp có thể thay nội dung
soLuong = 2; // đổi nội dung hộp soLuong từ 1 thành 2
const PHI_SHIP = 30_000; // 30_000 chính là 30000; dấu _ chỉ để dễ đọc
const(constant, hằng): gán một lần, không được gán lại. Code hiện đại dùngconstlà chủ yếu.let: có thể gán lại giá trị mới.- Dấu
=trong code nghĩa là “cất vào hộp”, không phải “bằng nhau” như trong toán. - Dòng bắt đầu bằng
//là chú thích (comment): ghi chú cho người đọc, máy bỏ qua.
Tên biến viết liền, không dấu, thường theo kiểu camelCase (chữ đầu viết thường, các từ sau viết hoa chữ cái đầu) như tenKhach, soLuong. Hằng số cấu hình hay viết HOA như PHI_SHIP. Trong code thật, tên thường bằng tiếng Anh (customerName, quantity); trong bài này dùng cả hai để bạn quen.
Kiểu dữ liệu: mỗi hộp đựng một loại thứ
Hộp đựng đường không nên chứa trứng. Trong code, mỗi giá trị thuộc một kiểu dữ liệu (data type). Năm kiểu bạn sẽ gặp liên tục:
| Kiểu | Ý nghĩa | Ví dụ Bánh Mộc | Cách nhận ra |
|---|---|---|---|
string |
Chuỗi chữ | "BM-261012-007", "Mừng sinh nhật Bin" |
Nằm trong dấu nháy "..." hoặc '...' |
number |
Con số | 450000, 2 |
Số không có nháy |
boolean |
Đúng/sai | true, false (ví dụ isActive) |
Chỉ có hai giá trị |
array (mảng) |
Danh sách có thứ tự | ["dâu", "socola", "matcha"] |
Nằm trong ngoặc vuông [...] |
object (đối tượng) |
Một “phiếu” gồm nhiều ô có tên | { productName: "Bánh quy hộp quà", unitPrice: 120000 } |
Nằm trong ngoặc nhọn {...}, dạng tên: giá trị |
Ngoài ra có hai giá trị đặc biệt nghĩa là “không có gì”: undefined (chưa từng được gán) và null (cố ý để trống). Ví dụ đơn bánh mì ngọt không có chữ trên bánh, nên cakeMessage không có giá trị.
Một dòng đơn hàng (giống một dòng trong bảng order_items) là một object:
const dongBanhKem = {
productName: "Bánh kem dâu 20cm",
unitPrice: 450_000, // đơn giá, VNĐ
quantity: 1,
cakeMessage: "Mừng sinh nhật Bin",
};
console.log(dongBanhKem.unitPrice); // in ra 450000; dấu chấm để "mở ô" có tên unitPrice
Và cả đơn là một mảng các object: danh sách nhiều dòng.
Điều kiện: “nếu… thì…, nếu không thì…”
Logic nghiệp vụ đầy những chữ “nếu”. Code diễn đạt chúng bằng if / else:
// Quy tắc (giả định cho ví dụ): khách tự đến lấy thì không tính ship;
// giao tận nơi thì đơn từ 500.000đ được miễn phí ship, dưới mức đó tính 30.000đ.
if (deliveryType === "pickup") {
phiShip = 0;
} else if (tamTinh >= 500_000) {
phiShip = 0;
} else {
phiShip = 30_000;
}
Đọc như tiếng Việt: nếu khách tự lấy thì phí ship 0; nếu không, mà tạm tính từ 500.000 trở lên thì 0; còn lại thì 30.000. Máy kiểm tra từ trên xuống, gặp điều kiện đúng đầu tiên thì làm phần đó và bỏ qua phần còn lại.
Các ký hiệu so sánh và kết hợp hay gặp:
| Ký hiệu | Nghĩa | Ví dụ | ||||
|---|---|---|---|---|---|---|
=== |
bằng (nghiêm ngặt, cùng kiểu) | status === "moi" |
||||
!== |
khác | status !== "da_huy" |
||||
> >= < <= |
lớn hơn, lớn hơn hoặc bằng… | tamTinh >= 500_000 |
||||
&& |
VÀ (cả hai cùng đúng) | isCustomCake && cakeMessage === "" |
||||
| `\ | \ | ` | HOẶC (ít nhất một đúng) | `role === “owner” \ | \ | role === “manager”` |
! |
KHÔNG (đảo ngược) | !isActive nghĩa là “không còn bán” |
Bạn có thể thấy == (hai dấu bằng) trong code cũ. Nó so sánh “lỏng”, tự đổi kiểu trước khi so (ví dụ coi chuỗi "1" bằng số 1), dễ gây bất ngờ. Code hiện đại dùng ===.
Vòng lặp: làm lại cho từng món
Một đơn có nhiều món. Muốn tính tạm tính, người thợ phải đi qua từng món, nhân đơn giá với số lượng rồi cộng dồn. Đó là vòng lặp (loop):
let tamTinh = 0; // bắt đầu với hộp rỗng
for (const item of items) { // với MỖI món trong danh sách items...
tamTinh = tamTinh + item.unitPrice * item.quantity; // ...cộng thêm thành tiền của món đó
}
// sau vòng lặp, tamTinh chứa tổng tiền hàng
Đọc là: “Với mỗi item trong items, lấy tamTinh hiện tại cộng thêm đơn giá × số lượng, rồi cất lại vào tamTinh.”
AI thường viết cùng ý đó gọn hơn bằng các “hàm xử lý danh sách”. Bạn không cần tự viết, chỉ cần nhận ra:
// reduce: "gom" cả danh sách thành một giá trị, bắt đầu từ 0
const tamTinh = items.reduce((tong, item) => tong + item.unitPrice * item.quantity, 0);
// filter: lọc ra những món có chữ trên bánh
const monCoChu = items.filter((item) => item.cakeMessage !== undefined);
// map: biến mỗi món thành một thứ khác, ở đây là lấy tên
const tenCacMon = items.map((item) => item.productName);
Ký hiệu => (mũi tên) là cách viết ngắn của một hàm nhỏ: (item) => item.productName nghĩa là “nhận vào một item, trả ra tên của nó”.
Hàm: một công thức có tên
Hàm (function) là một đoạn công thức được đặt tên, nhận đầu vào (tham số), làm việc gì đó, và trả ra đầu ra (giá trị trả về). Giống công thức “Làm kem bơ”: đầu vào là bơ và đường, đầu ra là kem bơ. Đặt tên rồi thì lần sau chỉ cần nói “làm kem bơ” thay vì đọc lại từng bước.
// tên hàm đầu vào: tên và kiểu kiểu đầu ra
function tinhTamTinh(items: OrderItem[]): number {
let tong = 0;
for (const item of items) {
tong = tong + item.unitPrice * item.quantity;
}
return tong; // "return" = trả kết quả ra ngoài và kết thúc hàm
}
const ketQua = tinhTamTinh(donHang); // "gọi" hàm: đưa nguyên liệu vào, nhận kết quả
Hàm thuần và hàm có tác dụng phụ
Đây là phân biệt rất đáng giá khi review code:
- Hàm thuần (pure function): chỉ tính toán từ đầu vào ra đầu ra, không đụng gì bên ngoài. Cùng đầu vào luôn cho cùng kết quả.
tinhTamTinhlà hàm thuần. Dễ hiểu, dễ kiểm thử, an toàn. - Hàm có tác dụng phụ (side effect): làm thay đổi thế giới bên ngoài: ghi database, gửi tin nhắn Zalo, trừ tiền, gửi email. Gọi hai lần có thể gây hậu quả hai lần.
// Hàm có tác dụng phụ: mỗi lần gọi là một lần ghi database và một tin nhắn gửi đi
async function xacNhanDon(code: string): Promise<void> {
await capNhatTrangThai(code, "da_xac_nhan"); // ghi vào database
await guiTinZalo(code, "Tiệm đã nhận đơn của bạn. Cảm ơn!"); // gửi tin cho khách
}
Hai chữ mới: async đánh dấu hàm có những việc tốn thời gian chờ (đợi database, đợi mạng), và await nghĩa là “chờ việc này xong rồi mới làm tiếp”. Code backend đầy async/await vì hầu như việc gì cũng phải chờ database hay dịch vụ bên ngoài.
Ghép lại: hàm tính tổng tiền một đơn bánh
Đây là đoạn code hoàn chỉnh mà bạn sẽ dùng cho bài tập. Hãy đọc chậm, từng khối một, đối chiếu với chú thích.
// Kiểu giao hàng: chỉ được là một trong hai giá trị này
type DeliveryType = "pickup" | "delivery";
// "Khuôn" của một dòng đơn hàng
type OrderItem = {
productName: string;
unitPrice: number; // đơn giá, VNĐ, số nguyên
quantity: number;
cakeMessage?: string; // dấu ? nghĩa là không bắt buộc
};
const PHI_SHIP = 30_000;
const NGUONG_FREESHIP = 500_000;
// Hàm 1: cộng thành tiền của từng món
function tinhTamTinh(items: OrderItem[]): number {
let tong = 0;
for (const item of items) {
tong = tong + item.unitPrice * item.quantity;
}
return tong;
}
// Hàm 2: tính phí ship theo quy tắc của tiệm
function tinhPhiShip(subtotal: number, deliveryType: DeliveryType): number {
if (deliveryType === "pickup") {
return 0;
}
if (subtotal >= NGUONG_FREESHIP) {
return 0;
}
return PHI_SHIP;
}
// Hàm 3: ghép lại, trả về cả bốn con số
function tinhTongDon(items: OrderItem[], deliveryType: DeliveryType, deposit: number) {
const subtotal = tinhTamTinh(items);
const shippingFee = tinhPhiShip(subtotal, deliveryType);
const total = subtotal + shippingFee;
const conLai = total - deposit; // số tiền khách còn phải trả sau khi đã cọc
return { subtotal, shippingFee, total, conLai };
}
// Đơn của chị Hương: 1 bánh kem dâu 20cm + 2 hộp bánh quy, giao tận nơi, đã cọc 345.000đ (50% tiền bánh)
const donChiMai: OrderItem[] = [
{ productName: "Bánh kem dâu 20cm", unitPrice: 450_000, quantity: 1, cakeMessage: "Mừng sinh nhật Bin" },
{ productName: "Bánh quy hộp quà", unitPrice: 120_000, quantity: 2 },
];
console.log(tinhTongDon(donChiMai, "delivery", 345_000));
// Kết quả: { subtotal: 690000, shippingFee: 0, total: 690000, conLai: 345000 }
Luồng xử lý của tinhTongDon có thể vẽ thành sơ đồ, giúp bạn đối chiếu với quy tắc nghiệp vụ mà không cần đọc code:
- Nhận: danh sách món, kiểu giao, tiền cọc
- Khách tự đến lấy?
- Tạm tính ≥ 500.000đ?
- Phí ship = 30.000đ
- Tổng = tạm tính + phí ship
- Còn lại = tổng − tiền cọc
Xem sơ đồ gốc (Hình 1)
Vuốt ngang để xem hết sơ đồ
Đọc sơ đồ dạng chữ
- Nhận: danh sách món, kiểu giao, tiền cọc → Tạm tính = cộng (đơn giá × số lượng) từng món
- Tạm tính = cộng (đơn giá × số lượng) từng món → Khách tự đến lấy?
- Khách tự đến lấy? → Phí ship = 0 (Có)
- Khách tự đến lấy? → Tạm tính ≥ 500.000đ? (Không)
- Tạm tính ≥ 500.000đ? → Phí ship = 0 (Có)
- Tạm tính ≥ 500.000đ? → Phí ship = 30.000đ (Không)
- Phí ship = 30.000đ → Tổng = tạm tính + phí ship
- Phí ship = 0 → Tổng = tạm tính + phí ship
- Tổng = tạm tính + phí ship → Còn lại = tổng − tiền cọc
Hãy “chạy” bằng tay với đơn của chị Hương: tạm tính = 450.000 × 1 + 120.000 × 2 = 690.000. Giao tận nơi, nhưng 690.000 ≥ 500.000 nên phí ship 0. Tổng 690.000. Đã cọc 345.000, còn lại 345.000. Khớp với kết quả máy in ra.
Sửa món, kiểu giao, tiền cọc và bật/tắt ‘>=’ ↔ ‘>’ → chạy tinhTongDon từng dòng, xem biến đổi giá trị; có sẵn 4 bài tập (bánh mì ngọt, đúng ngưỡng 500.000, vòng lặp ghi đè, đơn rỗng)
Bàn thử cần bật JavaScript.
Kết quả chỉ để tham khảo, không thay cho việc bạn tự duyệt.
Kiểu trong TypeScript: nhãn ghi rõ hộp đựng gì
Bạn đã thấy những chữ như : number, : string, OrderItem[] trong code. Đó là chú thích kiểu (type annotation), phần TypeScript thêm vào JavaScript.
Ẩn dụ: trong bếp, hộp đường dán nhãn “ĐƯỜNG”. Nếu ai đó định đổ muối vào, người kiểm tra sẽ chặn lại trước khi món bánh bị hỏng. Bộ kiểm tra kiểu (type checker) của TypeScript làm đúng việc đó: đọc code và báo lỗi trước khi chương trình chạy, thay vì để khách hàng phát hiện.
Ví dụ kinh điển: dữ liệu đọc từ ô nhập trên form luôn là chuỗi chữ. Trong JavaScript thuần, cộng một số với một chuỗi sẽ nối chuỗi, không cộng số:
const tamTinh = 100_000;
const phiShipTuForm = "30000"; // giá trị lấy từ ô nhập: là chuỗi, không phải số
console.log(tamTinh + phiShipTuForm); // JavaScript in ra "10000030000", không phải 130000
Một đơn 130.000đ biến thành “10 tỷ” trên hóa đơn. Với TypeScript, nếu hàm khai báo rõ tham số là number, lỗi bị bắt ngay khi viết code. Đây là những thông báo lỗi kiểu bạn sẽ gặp, kèm cách “dịch”:
Điền ô trống rồi sao chép
error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
Dịch: bạn đưa vào hàm một chuỗi, trong khi hàm cần một con số. (Đúng tình huống “30000” ở trên.)
Điền ô trống rồi sao chép
error TS2345: Argument of type '"giao-hang"' is not assignable to parameter of type 'DeliveryType'.
Dịch: kiểu giao hàng chỉ được là "pickup" hoặc "delivery", không có giá trị "giao-hang".
Điền ô trống rồi sao chép
error TS2551: Property 'quantiy' does not exist on type 'OrderItem'. Did you mean 'quantity'?
Dịch: gõ sai tên ô; TypeScript còn gợi ý tên đúng.
Điền ô trống rồi sao chép
error TS2322: Type 'string' is not assignable to type 'number'.
Dịch: đang cất một chuỗi vào hộp chỉ dành cho số.
Và một lỗi khi chạy (không phải lỗi kiểu) rất phổ biến:
Điền ô trống rồi sao chép
TypeError: Cannot read properties of undefined (reading 'unitPrice')
Dịch: code định “mở ô” unitPrice của một thứ không tồn tại, ví dụ lấy món thứ 6 trong một đơn chỉ có 2 món, hoặc sản phẩm không tìm thấy trong database.
Vì sao kiểu đặc biệt quan trọng khi làm việc với AI? Vì nó cho agent một vòng phản hồi tự động: agent viết code, chạy type checker, thấy lỗi, tự sửa, trước khi bạn phải nhìn tới. Bài Kiểm tra tĩnh: linter, formatter và type checker08-06 sẽ đi sâu hơn.
Cách nhờ AI giải thích từng dòng code
Bạn không cần tự đọc hiểu mọi thứ. AI là một gia sư kiên nhẫn, nếu bạn hỏi đúng cách:
- Dán đoạn code ngắn (vài chục dòng), không dán cả file dài.
- Nói rõ trình độ của bạn: “tôi không biết lập trình, giải thích như cho chủ tiệm bánh”.
- Yêu cầu chạy thử với ví dụ cụ thể: “cho đơn có 2 món này, biến nào mang giá trị gì sau mỗi dòng”.
- Hỏi về quy tắc, không chỉ cú pháp: “đoạn này đang cài quy tắc nghiệp vụ gì? Viết lại thành câu tiếng Việt.”
- Đối chiếu: “so với quy tắc sau của tiệm tôi, code có chỗ nào khác không?”
Câu hỏi cuối cùng là quan trọng nhất. Bạn không cần đọc code giỏi hơn AI; bạn cần biết quy tắc của tiệm giỏi hơn AI.
Áp dụng vào dự án Bánh Mộc
Nhật ký công trình · Bánh Mộc
BM-261013-010
13.10.2026
- Chị LanChủ chuỗi

Agent vừa viết xong phần tính tiền cho Mộc OMS. Thay vì chỉ bấm thử giao diện, chị Lan làm ba việc:
- Nhờ agent dịch code thành quy tắc tiếng Việt. Agent liệt kê: “Phí ship 30.000đ cho đơn giao tận nơi có tạm tính dưới 500.000đ; miễn phí khi từ 500.000đ hoặc khách tự lấy.”
- Đối chiếu với danh sách quy tắc của tiệm (danh sách chị lập từ bài 01-01). Chị phát hiện agent thiếu một quy tắc: đơn có bánh kem tùy chỉnh phải cọc tối thiểu 50% tiền bánh (làm tròn lên nghìn đồng) mới được xác nhận. Đây là thứ AI không thể tự biết.
- Chạy code trong đầu với ba đơn ở ngưỡng: tạm tính đúng 500.000đ, 499.000đ, và đơn không có món nào. Đơn rỗng cho ra tổng 30.000đ, tức là chỉ có phí ship mà không có bánh. Chị yêu cầu agent thêm kiểm tra “đơn phải có ít nhất một món” ở backend và viết test cho cả ba trường hợp.
Chị Lan không viết dòng code nào. Nhưng chị đã tìm ra hai lỗi nghiệp vụ mà giao diện không bao giờ để lộ. Đó là vai trò “kiểm định viên” mà bài Vai trò mới của bạn00-04 đã nhắc tới.
Prompt mẫu
Điền ô trống rồi sao chép
Tôi là chủ tiệm bánh, không biết lập trình. Hãy giải thích đoạn TypeScript dưới đây
từng dòng một, bằng tiếng Việt đời thường. Sau đó:
1. Viết lại các quy tắc nghiệp vụ mà đoạn code đang cài, mỗi quy tắc một câu.
2. Chạy thử bằng tay với ví dụ: [mô tả một đơn cụ thể], ghi giá trị từng biến sau mỗi bước.
3. Chỉ ra các trường hợp ở ngưỡng (đúng bằng, rỗng, số âm) mà code có thể xử lý sai.
[dán code]
Điền ô trống rồi sao chép
Đây là quy tắc tính tiền của tiệm tôi:
- Tiền là số nguyên VNĐ.
- Giao tận nơi: phí ship 30.000đ; đơn có tạm tính từ 500.000đ trở lên được miễn phí ship.
- Khách tự lấy: không tính ship.
- Đơn phải có ít nhất 1 món, số lượng mỗi món từ 1 đến 50.
Hãy đọc hàm tính tiền trong [đường dẫn file] và liệt kê mọi điểm code KHÁC với quy tắc trên,
kể cả điểm code xử lý thiếu. Chưa sửa, chỉ báo cáo kèm số dòng.
Điền ô trống rồi sao chép
Tôi gặp lỗi sau khi chạy dự án (dán nguyên văn):
[dán lỗi]
Hãy giải thích bằng tiếng Việt dễ hiểu: lỗi này nghĩa là gì, xảy ra ở file và dòng nào,
nguyên nhân có thể là gì. Đề xuất cách sửa nguyên nhân gốc, không được tắt kiểm tra kiểu
hay dùng "any" để che lỗi.
Sai lầm thường gặp
-
Sự cố 01
Chỉ kiểm tra bằng giao diện, không đọc logic.
Triệu chứngBấm thử vài đơn bình thường, thấy đúng, coi là xong. Lỗi nằm ở các trường hợp ngưỡng không ai bấm thử.
Cách tránhNhờ AI dịch code thành quy tắc, đối chiếu từng quy tắc, chạy tay với ví dụ ở ngưỡng.
-
Sự cố 02
Chấp nhận tiền dạng số thập phân.
Triệu chứngSai số làm tròn nhỏ cộng dồn thành chênh lệch khi đối soát.
Cách tránhQuy định trong file hướng dẫn agent: tiền là số nguyên VNĐ; phần trăm phải làm tròn ngay.
-
Sự cố 03
Để AI “sửa” lỗi kiểu bằng cách tắt kiểm tra.
Triệu chứngAI đôi khi thêm
any,as any, hoặc// @ts-ignoređể lỗi biến mất. Lỗi không biến mất, chỉ bị giấu đi.Cách tránhGhi rõ trong prompt và file hướng dẫn: không dùng
anyhay@ts-ignoređể che lỗi; sửa nguyên nhân gốc. -
Sự cố 04
Không phân biệt hàm thuần và hàm có tác dụng phụ.
Triệu chứngReview hàm gửi tin nhắn cũng hời hợt như hàm cộng số.
Cách tránhĐánh dấu các hàm ghi database, gửi tin, xử lý tiền là “vùng cần review kỹ” và yêu cầu test cho chúng.
-
Sự cố 05
Dán cả file dài cho AI giải thích.
Triệu chứngCâu trả lời dài, chung chung, bạn không học được gì.
Cách tránhDán từng đoạn ngắn, kèm câu hỏi cụ thể và một ví dụ dữ liệu.
Checklist
Bài tập thực hành
Các bài 1 đến 4 dùng đoạn code “Ghép lại: hàm tính tổng tiền một đơn bánh” ở trên. Hãy tự tính ra giấy trước, rồi mới xem đáp án.
tinhTongDon([{ productName: "Bánh mì ngọt", unitPrice: 25_000, quantity: 4 }], "delivery", 0);
Đáp án: tạm tính 100.000; giao tận nơi và dưới 500.000 nên phí ship 30.000; tổng 130.000; còn lại 130.000.
tinhTongDon(
[
{ productName: "Bánh kem dâu 20cm", unitPrice: 450_000, quantity: 1 },
{ productName: "Bánh mì ngọt", unitPrice: 25_000, quantity: 2 },
],
"delivery",
0
);
Câu hỏi phụ: nếu agent viết subtotal > NGUONG_FREESHIP thay vì >=, kết quả đổi thế nào? Đáp án: tạm tính đúng 500.000; với >= phí ship 0, tổng 500.000. Với >, phí ship 30.000, tổng 530.000. Quy tắc “từ 500.000đ” nghĩa là phiên bản >= mới đúng.
function tinhTamTinh(items: OrderItem[]): number {
let tong = 0;
for (const item of items) {
tong = item.unitPrice * item.quantity;
}
return tong;
}
Đáp án: 240.000. Mỗi vòng lặp ghi đè tong thay vì cộng dồn, nên chỉ giữ thành tiền của món cuối cùng (2 hộp bánh quy). TypeScript không báo lỗi vì kiểu vẫn đúng; chỉ có test hoặc người đọc logic mới bắt được. Đây là ví dụ cho thấy kiểu không thay thế được việc kiểm tra nghiệp vụ.
tinhTongDon([], "delivery", 0);
Đáp án: tạm tính 0; giao tận nơi và 0 nhỏ hơn 500.000 nên phí ship 30.000; tổng 30.000. Code “đúng” theo từng dòng nhưng sai về nghiệp vụ: không ai đặt một đơn chỉ có phí ship. Bài học: cần một quy tắc “đơn phải có ít nhất 1 món”, kiểm tra ở backend trước khi tính tiền. Hãy viết quy tắc này thành một câu prompt yêu cầu agent bổ sung kèm test.
-
Bài 1
Cơ bản
Đơn bánh mì ngọt
-
Bài 2
Cơ bản
Đúng ngưỡng
-
Bài 3
Nâng cao
Tìm lỗi trong vòng lặp
Agent sửa hàm
tinhTamTinhthành như sau. Với đơn của chị Hương, hàm trả về bao nhiêu? -
Bài 4
Nâng cao
Đơn rỗng
Thuật ngữ trong bài
- Biến (variable)
- Hộp có tên để chứa một giá trị;
letđổi được,constkhông - Chú thích (comment)
- Ghi chú cho người đọc, bắt đầu bằng
//, máy bỏ qua - Kiểu dữ liệu (data type)
- Loại giá trị: string, number, boolean, array, object
undefined/null- Giá trị “không có gì”
- Điều kiện (
if/else) - Rẽ nhánh theo đúng/sai
- Vòng lặp (loop)
- Lặp lại một việc cho từng phần tử
reduce/filter/map- Gom danh sách thành một giá trị / lọc / biến đổi từng phần tử
- Hàm (function)
- Công thức có tên, nhận đầu vào, trả đầu ra
- Tham số (parameter)
- Đầu vào của hàm
- Giá trị trả về (return)
- Đầu ra của hàm
- Hàm thuần (pure function)
- Chỉ tính toán, không thay đổi gì bên ngoài
- Tác dụng phụ (side effect)
- Thay đổi bên ngoài: ghi database, gửi tin nhắn
async/await- Đánh dấu việc cần chờ / chờ việc đó xong
- TypeScript
- JavaScript có thêm hệ thống kiểu
- Type checker
- Công cụ kiểm tra kiểu và báo lỗi trước khi chạy
Đọc thêm
- MDN Web Docs: phần “JavaScript Guide” giải thích biến, kiểu, điều kiện, vòng lặp, hàm.
- Ngôn ngữ lập trình và framework01-05: vì sao chọn TypeScript.
- Đọc và review code do AI viết: checklist cho người không chuyên06-06
- Unit test và TDD cùng agent08-03: biến các trường hợp ngưỡng trong bài tập thành test tự động.
Nghiệm thu tờ 01-04
Đọc xong và tự kiểm theo phiếu nghiệm thu, rồi đánh dấu tờ này.

