Kinh nghiệm
9 phút đọc2 tháng 6, 2026

Clean Code JavaScript: Repo mà dev JS nào cũng nên đọc ít nhất một lần

Review repo clean-code-javascript tổng hợp nguyên tắc viết code JS sạch từ đặt tên biến đến SOLID, giúp codebase dễ maintain và scale hơn hẳn.

N

Nguyễn Nhật Long

@nguyennhatlong1303

Clean Code JavaScript: Repo mà dev JS nào cũng nên đọc ít nhất một lần

Mình nhớ hồi mới đi làm, có lần submit một PR mà senior review xong comment đúng một câu: "Code chạy đúng rồi, nhưng đọc không hiểu gì cả." Lúc đó mình hơi tự ái, nhưng ngồi lại đọc code của chính mình sau 2 tuần thì... đúng thật, chính mình cũng không hiểu mình viết cái gì. Đó là lúc mình bắt đầu tìm hiểu về clean code, và một trong những tài liệu đầu tiên mình đọc chính là repo clean-code-javascript trên GitHub.

Hôm nay mình muốn review kỹ repo này không phải kiểu liệt kê lại nội dung, mà là chia sẻ góc nhìn sau mấy năm áp dụng thực tế, cái gì hay, cái gì cần lưu ý, và ai nên đọc nó.

Repo này thực chất là gì?

Repo clean-code-javascript là bản dịch tiếng Việt (và cũng có bản gốc tiếng Anh của Ryan McDermott) lấy cảm hứng từ cuốn sách kinh điển Clean Code của Robert C. Martin (Uncle Bob), nhưng được adapt lại hoàn toàn cho JavaScript. Nó không phải là một library hay tool để bạn npm install. Nó là một tập hợp các nguyên tắc, quy ước, và ví dụ cụ thể về cách viết code JS sao cho dễ đọc, dễ maintain, dễ test.

Cấu trúc repo khá đơn giản chỉ là một file README dài, chia thành các section theo chủ đề: đặt tên biến, hàm, object và class, SOLID principles, testing, concurrency, error handling, formatting... Mỗi section đều có cặp ví dụ Bad vs Good rất trực quan.

Theo kinh nghiệm của mình, cái hay nhất của repo này không phải là nó dạy bạn điều gì quá mới mẻ. Phần lớn các nguyên tắc bạn đã "biết" rồi nhưng nó giúp bạn hệ thống hóa lại và có ví dụ cụ thể để tham chiếu khi cần.

Đặt tên biến tưởng dễ mà khó vãi

Phần đầu tiên repo cover là Variables. Nghe thì basic, nhưng mình dám cá là phần lớn bug trong codebase production không phải do logic sai, mà do dev đọc code hiểu nhầm ý nghĩa của biến.

Ví dụ repo đưa ra rất sát thực tế:

JavaScript
1// Bad
2const yyyymmdstr = moment().format('YYYY/MM/DD');
3
4// Good
5const currentDate = moment().format('YYYY/MM/DD');

Tưởng ai cũng biết, nhưng bạn mở bất kỳ project nào đã sống được 2-3 năm, mình đảm bảo sẽ thấy những biến kiểu d, tmp, data2, result1 nhan nhản. Repo này nhấn mạnh một nguyên tắc mình rất tâm đắc: dùng tên có thể tìm kiếm được (searchable names). Khi codebase lớn, bạn sẽ grep rất nhiều. Một biến tên d thì grep ra cả ngàn kết quả, còn daysSinceCreation thì chỉ ra đúng chỗ cần tìm.

Một điểm nữa mình thấy hay là nguyên tắc đừng thêm context thừa:

JavaScript
1// Bad
2const Car = {
3 carMake: 'Honda',
4 carModel: 'Accord',
5 carColor: 'Blue'
6};
7
8// Good
9const Car = {
10 make: 'Honda',
11 model: 'Accord',
12 color: 'Blue'
13};

Đã biết object là Car rồi thì property không cần lặp lại prefix car nữa. Cái này mình thấy rất nhiều anh em mắc phải, đặc biệt khi code backend với Mongoose/Sequelize model.

Functions ít argument, ít side effect, làm một việc duy nhất

Phần Functions là phần dài nhất và cũng là phần mình nghĩ giá trị nhất trong repo. Có vài nguyên tắc mà mình áp dụng hàng ngày:

Tối đa 2 arguments cho một function. Nếu cần nhiều hơn, dùng object destructuring. Cái này thay đổi cách mình viết code hoàn toàn:

JavaScript
1// Bad
2function createMenu(title, body, buttonText, cancellable) { ... }
3
4// Good
5function createMenu({ title, body, buttonText, cancellable }) { ... }

Lợi ích rõ nhất là khi gọi hàm, bạn không cần nhớ thứ tự argument. Ai từng debug một hàm có 5-6 params mà truyền sai thứ tự sẽ hiểu cái đau này.

Function nên làm đúng một việc. Nghe như câu cửa miệng, nhưng repo đưa ví dụ rất thuyết phục. Khi một function vừa validate, vừa transform, vừa save bạn không thể test từng phần riêng lẻ, không thể reuse, và khi có bug thì phải đọc cả function để tìm.

Mình thấy cái này hay ở chỗ repo không chỉ nói lý thuyết mà show code before/after rất rõ ràng, nên anh em junior đọc xong có thể áp dụng ngay được.

SOLID trong JavaScript không chỉ dành cho Java

Đây là phần mình muốn nói kỹ nhất, vì rất nhiều dev JS nghĩ SOLID là chuyện của Java/C#. Sai. Repo này chứng minh rằng SOLID hoàn toàn applicable cho JS, đặc biệt khi bạn làm việc với class hoặc module pattern.

Để dễ hình dung, mình tóm tắt 5 nguyên tắc và cách repo áp dụng vào JS:

Theo kinh nghiệm của mình, hai nguyên tắc SD là impactful nhất trong JS day-to-day. Single Responsibility giúp bạn tránh được những file 500+ dòng mà ai cũng sợ đụng vào. Dependency Inversion giúp code testable hơn rất nhiều thay vì import trực tiếp một module, bạn inject nó vào, và khi test thì mock dễ dàng.

Nguyên tắcÝ nghĩaÁp dụng JS thế nào
**S** Single ResponsibilityMỗi class/module chỉ có một lý do để thay đổiTách logic ra nhiều module nhỏ, mỗi module handle một concern
**O** Open/ClosedMở cho mở rộng, đóng cho sửa đổiDùng composition, higher-order functions thay vì sửa code cũ
**L** Liskov SubstitutionSubclass phải thay thế được parent classKhi extend class, đảm bảo contract không bị phá vỡ
**I** Interface SegregationClient không nên bị ép phụ thuộc vào interface không dùngTách interface lớn thành nhiều interface nhỏ (dùng composition)
**D** Dependency InversionDepend on abstractions, not concretionsInject dependencies thay vì hardcode

Repo đưa ví dụ về Dependency Inversion khá hay thay vì một class InventoryTracker tự tạo HTTP request bên trong, nó nhận một requester object từ bên ngoài. Khi cần đổi từ HTTP sang WebSocket hay GraphQL, bạn chỉ cần truyền một requester khác mà không sửa InventoryTracker.

Error Handling đừng nuốt lỗi

Một phần mà mình thấy nhiều dev Việt Nam hay bỏ qua là Error Handling. Repo nhấn mạnh: đừng bao giờ ignore caught errors.

JavaScript
1// Bad
2try {
3 functionThatMightThrow();
4} catch (error) {
5 console.log(error);
6}
7
8// Good
9try {
10 functionThatMightThrow();
11} catch (error) {
12 notifyUserOfError(error);
13 reportErrorToService(error);
14}

console.log(error) trong production thì coi như mất luôn error đó. Không ai ngồi đọc console log trên server cả. Repo khuyến khích dùng error reporting service (Sentry, Bugsnag,...) và handle error một cách có ý thức.

Mình bổ sung thêm: với Promise, repo cũng nhấn mạnh đừng để unhandled rejection. Cái này từ Node.js 15 trở đi sẽ crash process luôn nếu không handle, nên không phải chuyện nhỏ.

Testing repo nhắc nhẹ nhưng quan trọng nặng

Phần testing trong repo khá ngắn gọn nhưng đúng trọng tâm. Nguyên tắc chính: mỗi test chỉ test một concept duy nhất. Mình thấy rất nhiều test case kiểu "test everything in one it block" khi fail thì không biết fail ở đâu, debug mệt muốn chết.

Repo không đi sâu vào tool (Jest, Mocha, Vitest...) mà focus vào mindset. Cái này mình thấy đúng hướng tool thay đổi liên tục, nhưng nguyên tắc viết test tốt thì không đổi.

Điểm mạnh và điểm cần lưu ý

Sau mấy năm dùng repo này như reference, mình đúc kết lại:

Anh em lưu ý: repo này là guidelines, không phải rules. Đừng biến nó thành dogma. Có những lúc bạn cần viết code "không clean" vì deadline, vì performance, vì context cụ thể của project. Clean code là đích đến, không phải điều kiện tiên quyết để ship feature.

Điểm mạnhĐiểm cần lưu ý
Ví dụ Bad/Good cực kỳ trực quanMột số ví dụ hơi lý tưởng hóa, thực tế messy hơn nhiều
Cover đủ từ basic đến advanced (SOLID)Không cover các pattern mới như hooks, composables
Bản tiếng Việt giúp anh em đọc nhanhBản dịch đôi chỗ hơi cứng, nên đọc song song bản gốc
Không gắn với framework cụ thể nàoThiếu ví dụ thực tế từ real-world project
Free, open-source, cộng đồng đóng gópKhông cập nhật thường xuyên (ES2022+ features chưa có)

Ai nên đọc, ai có thể skip?

Nếu bạn là junior dev (0-2 năm kinh nghiệm) đọc ngay, đọc kỹ, bookmark lại. Những nguyên tắc trong này sẽ giúp bạn level up nhanh hơn bất kỳ tutorial nào về framework.

Nếu bạn là mid-level (2-4 năm) đọc lại để hệ thống hóa. Có thể bạn đã biết 70-80% nội dung, nhưng 20% còn lại sẽ fill những gap mà bạn không biết mình có.

Nếu bạn là senior dùng nó như reference khi review code cho team. Thay vì comment "code này không clean", bạn có thể link đến section cụ thể trong repo. Nó giúp feedback khách quan hơn và người nhận feedback cũng dễ chấp nhận hơn.

Mình cũng recommend dùng repo này trong onboarding process cho team. Cho member mới đọc qua trong tuần đầu, rồi thảo luận cùng team xem những nguyên tắc nào team muốn adopt. Không cần áp dụng hết chọn ra 5-10 nguyên tắc quan trọng nhất với context project của bạn là đủ.

So sánh nhanh với các tài liệu tương tự

Nếu chỉ chọn một thứ để đọc, mình sẽ chọn repo clean-code-javascript vì nó cân bằng tốt giữa lý thuyết và thực hành, và không quá dài để đọc hết trong một buổi chiều.

Tài liệuNgôn ngữ targetĐộ sâuVí dụ codePhù hợp với
clean-code-javascriptJavaScriptTrung bình - CaoRất nhiều, Bad/GoodJS/TS dev mọi level
Airbnb Style GuideJavaScriptCaoNhiều, chi tiết config ESLintTeam cần coding standard
Clean Code (sách)Java (chủ yếu)Rất caoJava-centricDev muốn hiểu sâu lý thuyết
Google JS Style GuideJavaScriptCaoVừa phảiTeam theo Google ecosystem

Cuối cùng, mình muốn chia sẻ một điều mà mình học được sau nhiều năm: code sạch không phải viết cho compiler, mà viết cho người đọc tiếp theo và người đó rất có thể là chính bạn sau 6 tháng. Repo này là một trong những tài liệu tốt nhất để bắt đầu xây dựng thói quen đó. Star nó trên GitHub đi, rồi mở ra đọc mỗi khi cảm thấy code mình bắt đầu "có mùi".

NN

Nguyễn Nhật Long

@nguyennhatlong1303

Nguyễn Nhật Long is a Senior Frontend Engineer and Frontend Team Leader with 7 years of experience building real-time fintech platforms. Specializing in React, Next.js, TypeScript, and React Native, shipping 10+ products across Web, Mobile, Telegram Mini-Apps, and Web3.

Thấy hay? Chia sẻ cho bạn bè!