Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Bạn đã bao giờ mở một hàm dài 300 dòng và không biết bắt đầu đọc từ đâu? Hàm dài thường khó hiểu, khó test và là nơi bug thích ẩn nấp. Nguyên tắc "hàm nhỏ, làm một việc" là cách đơn giản nhất để tránh tình trạng đó.
Một hàm "làm một việc" khi bạn có thể mô tả nó bằng một câu ngắn mà không cần dùng chữ "và". Ví dụ "tính tổng tiền đơn hàng" là một việc. Còn "kiểm tra dữ liệu, lưu vào database, gửi email và ghi log" là bốn việc đang bị nhồi chung.
Đây là hệ quả của nguyên tắc Single Responsibility: mỗi đơn vị code chỉ nên có một lý do để thay đổi. Khi quy tắc gửi email thay đổi, bạn không muốn đụng vào đoạn code tính giá.
Trước khi tách:
function processOrder(order) {if (!order.items || order.items.length === 0) {throw new Error('Đơn hàng trống');}let total = 0;for (const item of order.items) {total += item.price * item.quantity;}if (order.coupon === 'GIAM10') {total = total * 0.9;}saveToDatabase({ ...order, total });sendEmail(order.email, 'Cảm ơn bạn, tổng tiền: ' + total);}Sau khi tách:
function validateOrder(order) {if (!order.items || order.items.length === 0) {throw new Error('Đơn hàng trống');}}function calculateSubtotal(items) {return items.reduce((sum, item) => sum + item.price * item.quantity, 0);}function applyCoupon(total, coupon) {return coupon === 'GIAM10' ? total * 0.9 : total;}function processOrder(order) {validateOrder(order);const total = applyCoupon(calculateSubtotal(order.items), order.coupon);saveToDatabase({ ...order, total });sendEmail(order.email, 'Cảm ơn bạn, tổng tiền: ' + total);}Hàm processOrder giờ đọc gần như một đoạn văn: kiểm tra, tính tổng, lưu, gửi mail. Muốn biết chi tiết từng bước, bạn mới nhảy vào hàm con.
applyCoupon là hàm thuần, bạn chỉ cần vài dòng test là phủ hết các trường hợp.calculateSubtotal có thể dùng ở trang giỏ hàng lẫn trang hóa đơn.save(data, true).Một mẹo hay: trong cùng một hàm, các dòng nên nằm ở cùng mức độ chi tiết. Đừng để một dòng là "gửi email xác nhận" (mức cao) nằm ngay cạnh dòng "nối chuỗi ký tự để tạo header" (mức thấp). Dòng chi tiết nên được đẩy xuống hàm con. Nhờ vậy khi đọc hàm cha, bạn nắm được luồng tổng thể, không bị chìm vào chi tiết.
Tách hàm cũng có giới hạn. Nếu bạn tạo ra hàm chỉ gọi hàm khác mà không thêm ý nghĩa, hoặc phải nhảy qua 10 file để hiểu một luồng đơn giản, bạn đã đi quá xa. Một hàm 15-20 dòng có tên rõ ràng, làm trọn vẹn một việc, là vẫn rất tốt. Không có con số thần kỳ nào, hãy lấy "dễ đọc và dễ test" làm thước đo.
Hàm nhỏ và tập trung giúp code dễ đọc, dễ test và dễ sửa. Hãy bắt đầu bằng việc tìm hàm dài nhất trong dự án của bạn và thử tách nó thành 3-4 hàm nhỏ có tên rõ ràng. Sau vài lần, đây sẽ trở thành phản xạ tự nhiên.
Nếu bạn muốn thực hành viết code sạch cùng các bài tập có hướng dẫn, hãy khám phá thêm các khóa học trên codebem.com.
Nguyễn Đình Cường
0 comment