Minimal Code Không Có Nghĩa Là Stable Code
Viết ít code hơn chưa chắc đã tốt hơn. Đôi khi sự "tối giản" lại là con dao hai lưỡi khiến production cháy lúc 2 giờ sáng.
Nguyễn Nhật Long
@nguyennhatlong1303
Bạn có bao giờ review một PR mà đồng nghiệp tự hào khoe "Em refactor xong, giảm được 200 dòng code" rồi tuần sau feature đó crash trên production không? Mình thì có. Nhiều hơn một lần.
Chuyện này không mới, nhưng gần đây cộng đồng dev quốc tế lại sôi nổi bàn luận khi Adam một developer trên Dev.to viết bài thẳng thắn với tiêu đề "Minimal Code Doesn't Mean Stable Code". Và thành thật mà nói, mình đồng ý gần như 100%.
Chuyện gì đang xảy ra?
Trong văn hóa dev hiện đại, có một niềm tin gần như mặc định: ít code hơn = tốt hơn. Nguyên tắc DRY (Don't Repeat Yourself), KISS (Keep It Simple, Stupid), hay những câu quote kiểu "The best code is no code at all" được truyền tai nhau như chân lý.
Không sai. Nhưng vấn đề là nhiều người hiểu sai tinh thần của những nguyên tắc này. Họ đánh đồng minimal code với good code, rồi bắt đầu:
- Xóa error handling vì "thừa"
- Gộp nhiều logic vào một function "cho gọn"
- Bỏ qua edge cases vì "hiếm khi xảy ra"
- Dùng one-liner phức tạp thay vì code dễ đọc
Kết quả? Code trông "sạch" trên GitHub nhưng mong manh như thủy tinh trên production.
Tại sao chúng ta bị cuốn vào "cult of minimal code"?
Theo kinh nghiệm của mình, có vài lý do chính:
Thứ nhất, ego. Viết một đoạn code ngắn gọn, clever, dùng reduce chain với ternary operator lồng nhau nó cho cảm giác mình giỏi. Code review mà ai đó comment "elegant" thì sướng cả ngày. Nhưng "elegant" với "maintainable" là hai thứ rất khác nhau.
Thứ hai, metrics sai. Một số team đo chất lượng code bằng số dòng. Ít dòng hơn = PR tốt hơn. Đây là một trong những metrics nguy hiểm nhất mà mình từng thấy.
Thứ ba, thiếu kinh nghiệm production. Khi bạn chưa bị đánh thức lúc 2 giờ sáng vì một unhandled edge case, bạn sẽ không hiểu tại sao cái if check "thừa" kia lại quan trọng đến vậy.
Minimal code vs. Stable code Khác nhau ở đâu?
Để dễ hình dung, mình so sánh hai mindset này:
Điều mình thấy hay là khi bạn nhìn vào bảng này, bạn sẽ nhận ra: stable code không nhất thiết phải dài hơn minimal code. Nó chỉ cần đúng chỗ hơn.
| Tiêu chí | Minimal Code Mindset | Stable Code Mindset |
|---|---|---|
| Mục tiêu chính | Ít dòng code nhất có thể | Code hoạt động đúng trong mọi điều kiện |
| Error handling | Bỏ qua hoặc tối giản | Xử lý đầy đủ, có fallback |
| Edge cases | "Chắc không ai làm vậy" | "Nếu có ai làm vậy thì sao?" |
| Readability | Có thể hy sinh để ngắn gọn | Ưu tiên cao, code là documentation |
| Testing | Chỉ test happy path | Test cả unhappy path, boundary cases |
| Logging | Ít hoặc không có | Đủ để debug khi production có vấn đề |
| Maintenance | Khó hiểu sau 3 tháng | Đồng nghiệp mới vào cũng đọc được |
Những "tội lỗi" phổ biến nhất
Xóa error handling "cho sạch"
Mình từng thấy một đồng nghiệp refactor một API handler từ 50 dòng xuống còn 15 dòng. Đẹp. Gọn. Nhưng anh ấy bỏ hết try-catch, bỏ input validation, bỏ cả logging. Hai tuần sau, một request với payload bất thường từ client cũ khiến service crash liên tục. Không có log, không ai biết tại sao. Mất 4 tiếng để debug một thứ mà đáng lẽ chỉ cần đọc log là xong.
One-liner "thông minh"
So sánh hai đoạn code này:
1// "Minimal" 1 dòng2const result = data?.items?.filter(x => x.active && x.type === 'premium')?.reduce((acc, x) => ({...acc, [x.id]: {...x, discount: x.tier > 2 ? 0.3 : x.tier > 1 ? 0.2 : 0.1}}), {}) || {};
1// "Stable" 12 dòng2const activeItems = data?.items?.filter(item => item.active && item.type === 'premium') || [];34const discountByTier = (tier) => {5 if (tier > 2) return 0.3;6 if (tier > 1) return 0.2;7 return 0.1;8};910const result = {};11for (const item of activeItems) {12 result[item.id] = { ...item, discount: discountByTier(item.tier) };13}
Đoạn thứ hai dài hơn gấp 12 lần. Nhưng khi có bug, bạn sẽ cảm ơn người viết nó. Bạn có thể đặt breakpoint, đọc hiểu logic trong 10 giây, và biết chính xác chỗ nào sai.
Abstract quá sớm
Một pattern mình gặp rất nhiều ở các bạn junior: thấy hai đoạn code hơi giống nhau là lập tức tạo một shared utility function. Rồi khi hai nơi đó cần diverge logic, cái shared function bắt đầu nhận thêm 5 cái flag parameter, có 3 cái if bên trong, và cuối cùng phức tạp hơn cả việc duplicate code ban đầu.
Rule of three vẫn là rule tốt: đợi đến khi bạn thấy pattern lặp lại ít nhất 3 lần rồi hãy abstract.
Ai bị ảnh hưởng?
Thành thật mà nói tất cả chúng ta. Nhưng đặc biệt là:
- Junior developers đang cố chứng minh mình bằng "clever code"
- Team leads đang set metrics không phù hợp
- Solo developers không có ai review code, dễ rơi vào echo chamber của bản thân
Và nếu bạn đang làm ở startup Việt Nam, nơi mà "ship fast" là ưu tiên số một, thì áp lực viết ít code để merge nhanh càng lớn hơn.
Vậy nên làm gì?
Theo kinh nghiệm của mình sau nhiều năm "trả giá", đây là vài nguyên tắc mình luôn giữ:
- Viết code cho người đọc, không phải cho compiler. Người đọc có thể là đồng nghiệp, hoặc chính bạn sau 6 tháng.
- Error handling không phải noise, nó là feature. Mỗi dòng try-catch, mỗi cái validation check đều là một lớp bảo vệ cho production.
- Đo chất lượng bằng stability, không bằng line count. Hỏi "code này có survive được edge cases không?" thay vì "code này có ngắn gọn không?"
- Log đủ, không log thừa. Khi production cháy lúc 3 giờ sáng, log là thứ duy nhất cứu bạn.
- Review code với mindset "nếu mọi thứ đều sai thì sao?" Input sai? Network timeout? Database chậm? Null ở chỗ không ngờ?
Chốt lại một câu
Minimal code là một mục tiêu tốt nhưng nó phải đứng sau stability, readability, và maintainability. Đừng để việc theo đuổi sự "tối giản" biến code của bạn thành một quả bom hẹn giờ.
Lần tới khi bạn review PR và thấy ai đó tự hào "giảm được 200 dòng code", hãy hỏi: "200 dòng đó làm gì, và giờ ai đang làm việc đó?" Nếu câu trả lời là "không ai cả" thì đó không phải refactor. Đó là xóa feature.
Nguyễn Nhật Long
@nguyennhatlong1303Nguyễ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è!