Việc để mã Front-end trở nên lộn xộn là điều rất dễ xảy ra.
Trong bài viết này, mình sẽ chỉ ra 17 điều bạn nên tránh nếu muốn giữ cho mã Front-end của mình rõ ràng và dễ bảo trì.
Cùng bắt đầu nhé 👇
Sai lầm #1: Sử dụng quá nhiều biến toàn cục
Biến toàn cục có thể được truy cập từ bất kỳ đâu trong ứng dụng, điều này khiến chúng trở nên nguy hiểm.
Nếu bạn thay đổi một biến toàn cục ở đâu đó, nó có thể gây lỗi ở nơi khác mà bạn không hề biết, và việc gỡ lỗi sẽ trở thành ác mộng.
Chúng cũng khiến việc viết unit test khó hơn vì hành vi của hàm có thể thay đổi tùy theo trạng thái toàn cục.
Do đó, hãy sử dụng tham số hàm hoặc biến cục bộ thay vì biến toàn cục.
VD tệ:
let userRole = 'guest'; function canEditPost() { return userRole === 'admin';
} userRole = 'admin'; // Changes app behavior unexpectedly
VD tốt hơn:
function canEditPost(userRole) { return userRole === 'admin';
} const role = 'admin';
canEditPost(role);
Sai lầm #2: Đặt tên biến và hàm mơ hồ
Sử dụng các tên như x
, data
, hoặc handleStuff
làm chậm quá trình phát triển.
Người đọc (bao gồm cả bạn trong tương lai) sẽ phải đoán từng thứ làm gì — hoặc tệ hơn là phải cuộn lên xuống để tìm hiểu.
Một quy tắc đơn giản: phạm vi càng rộng, tên càng nên mô tả rõ ràng.
Vòng lặp ngắn? i
là ổn.
Phạm vi lớn hơn? Hãy dùng tên cho thấy rõ mục đích.
VD tệ:
function d(a, b) { return a - b;
} const x = d(100, 50);
VD tốt hơn:
function calculateDiscount(originalPrice, discountAmount) { return originalPrice - discountAmount;
} const finalPrice = calculateDiscount(100, 50);
Sai lầm #3: Hàm “God”
Hàm "God" là những hàm làm mọi thứ — kiểm tra đầu vào, cập nhật giao diện, gọi API, xử lý lỗi — tất cả trong một.
Kết quả là: hàm dài dòng, khó đọc, khó test, và khó sửa lỗi.
Hãy chia logic thành các hàm nhỏ hơn, có mục đích rõ ràng.
VD tệ:
function handleFormSubmit(event) { event.preventDefault(); const name = event.target.name.value; const email = event.target.email.value; if (!name || !email.includes("@")) { alert("Invalid form"); return; } setLoading(true); fetch("/api/submit", { method: "POST", body: JSON.stringify({ name, email }), }) .then(res => res.json()) .then(data => { setUser(data.user); navigate("/dashboard"); }) .catch(() => { alert("Something went wrong"); }) .finally(() => setLoading(false));
}
VD tốt hơn:
function handleFormSubmit(event) { event.preventDefault(); const formData = getFormData(event); if (!isValidForm(formData)) { alert("Invalid form"); return; } submitForm(formData);
} function getFormData(event) { return { name: event.target.name.value, email: event.target.email.value, };
} function isValidForm({ name, email }) { return name && email.includes("@");
} async function submitForm(data) { try { setLoading(true); const response = await fetch("/api/submit", { method: "POST", body: JSON.stringify(data), }); const result = await response.json(); setUser(result.user); navigate("/dashboard"); } catch (e) { alert("Something went wrong"); } finally { setLoading(false); }
}
Sai lầm #4: Hàm có nhiều tham số cùng kiểu
Nếu một hàm có nhiều tham số cùng kiểu — ví dụ như boolean hoặc chuỗi — rất dễ bị nhầm lẫn thứ tự.
Hãy truyền vào một object có key rõ ràng.
VD tệ:
createUser("Alice", true, false, true);
VD tốt hơn:
createUser({ name: "Alice", isAdmin: true, isVerified: false, isActive: true });
Sai lầm #5: Không giải phóng tài nguyên
Khi bạn thêm event listener, tạo interval, setTimeout, hoặc dùng useEffect
trong React — hãy nhớ dọn dẹp sau khi không còn cần nữa.
Nếu không, bạn có thể gặp tình trạng rò rỉ bộ nhớ, lặp event listener, hoặc các request ma vẫn đang chạy.
Những lỗi này đặc biệt nghiêm trọng với app frontend chạy lâu (như dashboard, trang quản trị).
VD tệ:
useEffect(() => { window.addEventListener('resize', handleResize); }, []);
VD tốt hơn:
useEffect(() => { window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize);
}, []);
Sai lầm #6: Biến không có đơn vị
Nếu một giá trị có đơn vị — như milliseconds, pixels hay megabytes — hãy bao gồm cả đơn vị đó trong tên biến.
Nếu không, các dev khác (hoặc chính bạn trong tương lai) sẽ phải đoán ý nghĩa của con số đó.
VD tệ:
const timeout = 3000;
VD tốt hơn:
const timeoutMs = 3000;
Sai lầm #7: Lồng điều kiện quá 3 cấp
Khi logic của bạn lồng quá 2 hoặc 3 cấp, nó trở nên khó đọc và khó hiểu, nhất là với nhiều khối if/else
.
Thay vào đó, hãy “làm phẳng” code bằng cách:
- Trả về sớm (
return early
) - Đảo ngược điều kiện
- Tách logic thành các hàm nhỏ hơn
VD tệ:
if (user) { if (user.isAdmin) { if (user.hasAccess) { // do stuff } }
}
VD tốt hơn:
if (!user || !user.isAdmin || !user.hasAccess) return; // do stuff
Sai lầm #8: Hardcode URL hoặc cấu hình
Hardcode các URL, API key hay config theo môi trường là một cái bẫy.
Khi giá trị đó thay đổi, bạn sẽ phải lùng sục toàn bộ codebase để sửa.
Hãy lưu các giá trị config vào biến môi trường hoặc constants, rồi import khi cần.
VD tệ:
fetch('https://api.example.com/posts');
VD tốt hơn:
const API_BASE_URL = process.env.API_BASE_URL;
fetch(`${API_BASE_URL}/posts`);
Sai lầm #9: Giữ lại code chết “để phòng”
Ai cũng từng làm — comment code lại “phòng khi cần.”
Nhưng thực tế: 99% là sẽ không bao giờ dùng lại 😅. Và không ai muốn phải lướt qua đống đó cả.
Hãy xóa đi và dùng Git để khôi phục nếu cần.
VD tệ:
// old validation logic (maybe needed later)
// function validateInput(input) { ... }
Tốt nhất bạn nên xóa chúng đi là xong!
Sai lầm #10: File utils khổng lồ
File utils.js ban đầu vô hại, nhưng dần trở thành “nồi lẩu thập cẩm” các hàm linh tinh.
Trước khi nhận ra, nó đã dài hàng trăm dòng và khó tìm kiếm.
Hãy đặt các hàm tiện ích gần nơi sử dụng, hoặc chia nhỏ thành các file riêng biệt như arrayUtils.js
, dateUtils.js
, v.v.
VD tệ:
// utils.js
export function doStuff() {}
VD tốt hơn:
// listUtils.js (next to List component)
export function getVisibleItems(items, filter) { return items.filter(item => item.visible && item.category === filter);
}
Sai lầm #11: Nuốt lỗi
Nếu code có thể throw lỗi, đừng phớt lờ nó.
Lỗi bị nuốt là ác mộng khi debug, nhất là ở production.
Một dòng console.error
đơn giản có thể tiết kiệm hàng giờ đồng hồ.
Và nếu ảnh hưởng đến người dùng, hãy hiển thị thông báo trong UI.
VD tệ:
try { riskyFunction();
} catch (e) { // nothing
}
VD tốt hơn:
try { riskyFunction();
} catch (e) { console.error("Error in riskyFunction:", e); showToast("TODO: Useful error message + actions");
}
Sai lầm #12: Một file quá khổ
Khi bạn để mọi thứ trong một file duy nhất — component, logic, styling, state — file đó sẽ nhanh chóng phình to.
Kết quả là 800+ dòng cuộn mỏi tay.
Hãy chia nhỏ:
- Nhóm code liên quan thành thư mục
- Mỗi file có một vai trò rõ ràng
Việc này giúp giảm tải nhận thức và dễ dàng onboarding dev mới.
VD tệ:
// App.js — 1000+ lines of code
VD tốt hơn:
/components
/context
/pages
Sai lầm #13: Không dùng linter
Các công cụ linter như ESLint bắt lỗi trước khi code vào production: từ bug đơn giản đến thiếu dependency trong useEffect
.
Chúng cũng giúp thống nhất style code trong team.
Đừng bỏ qua warning hay dùng // eslint-disable
bừa bãi
VD tệ:
useEffect(() => { fetchData();
}, []); // missing fetchData in deps
VD tốt hơn:
- Dùng ESLint + plugin React hooks. Nó sẽ cảnh báo:
React Hook useEffect has a missing dependency: 'fetchData'.
Sai lầm #14: Cấu trúc thư mục lộn xộn
Dự án của bạn không nên giống như một ngăn kéo lộn xộn.
Nếu file nằm rải rác không theo trật tự, sẽ rất khó tìm kiếm và mở rộng.
Hãy cấu trúc theo chức năng hoặc domain.
VD tệ:
/src App.js helpers.js styles.css randomStuff.js
VD tốt hơn:
/src /components /services App.js
Sai lầm #15: Comment những dòng code hiển nhiên
Bạn không cần giải thích let count = 0
nghĩa là gì.
Hãy tin vào người đọc!
Nếu đoạn code gây nhầm lẫn, hãy viết lại cho dễ hiểu hơn.
VD tệ:
// Set count to 0
let count = 0;
VD tốt hơn:
let itemCount = 0;
Sai lầm #16: Không comment cho logic “dị”
Đôi khi bạn phải viết workaround hoặc hỗ trợ case cũ.
Không sao cả — nhưng hãy giải thích tại sao.
Nếu không, teammate của bạn sẽ phải đau đầu với magicFix42(data)
là cái gì.
VD tệ:
const result = magicFix42(data);
VD tốt hơn:
// Applies patch for backend bug #321. Read ticket for more context const result = magicFix42(data);
Sai lầm #17: Tự viết lại thứ đã có sẵn
Đừng phát minh lại bánh xe.
Có rất nhiều thư viện nhỏ, ổn định được xây dựng bởi những người giỏi hơn chúng ta.
Nếu có thể dùng package uy tín để giải quyết vấn đề, hãy dùng.
Chỉ cần kiểm soát số lượng dependency để tránh làm to bundle.
VD có vẻ ổn:
function debounce(fn, delay) { let timer; return function (...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); };
}
Nhưng bạn vẫn có thể làm nó tốt hơn:
import { debounce} from 'lodash-es'; const debouncedFn = debounce(myFn, 300);
Kết luận
Code frontend có thể nhanh chóng trở nên lộn xộn.
Tránh 17 sai lầm này sẽ giúp bạn viết code dễ đọc, dễ debug và dễ bảo trì hơn.
Chính bạn trong tương lai — và các đồng nghiệp của bạn — sẽ cảm ơn bạn rất nhiều.