Đệ Quy Khiến Bạn Trở Thành Kỹ Sư Tồi
Đệ quy là cạm bẫy cho người mới học.
Bạn còn nhớ lần đầu bạn viết một hàm đệ quy chạy được không? Tính giai thừa, tính Fibonacci. Bạn phấn khích như vừa mở được ... "luân xa". Bạn nghĩ mình đã chạm đến một "cảnh giới mới" của lập trình. Tôi cũng từng như bạn. Nhưng giờ thì tôi biết: đó chỉ là một ảo giác. Đệ quy nghe có vẻ tao nhã, nhưng trong thế giới thực, nó là một cách viết code dở tệ, kém hiệu quả và tiềm ẩn nguy cơ phá hủy cả hệ thống của bạn.
Hãy nói về stack. Mỗi lần bạn gọi đệ quy, CPU phải tạo ra một stack frame mới, lưu toàn bộ biến cục bộ, kể cả những biến không dùng đến. Trên máy tính bàn với vài GB RAM, bạn có thể chưa cảm thấy gì. Nhưng trên một con vi điều khiển với 20 KB RAM? Một vài trăm lần gọi đệ quy là đủ để đốt sạch bộ nhớ và giết chết chương trình. Đệ quy không chỉ nguy hiểm – nó là kẻ ăn RAM hàng loạt. Và điều may mắn của chúng ta là gì ? ... là chúng ta hoàn toàn không cần phải sử dụng đệ quy và tiết kiệm lượng bộ nhớ trên.
Hãy nói về tốc độ. Vòng lặp giữ nguyên stack frame từ đầu đến cuối, chạy gọn gàng, tối ưu. Đệ quy thì mỗi lần gọi là một lần push/pop stack frame, tiêu tốn thời gian không cần thiết. Và đừng tự lừa mình rằng “máy tính nhanh lắm, không sao đâu”. Đệ quy Fibonacci kiểu ngây thơ là một trong những ví dụ lãng phí CPU kinh điển: số lời gọi tăng theo cấp số nhân chỉ để tính ra một con số mà bạn có thể có được bằng một vòng lặp cộng dồn đơn giản.
OK, Dừng Nerd. Hãy nói về maintainability.
Đệ quy đẹp trong giáo trình, nhưng ác mộng khi debug. Một bug nhỏ trong base case và chương trình của bạn biến thành vòng xoáy vô tận, rút cạn bộ nhớ. Muốn trace stack? Chuẩn bị cuộn chuột đến mỏi tay và nhìn call stack sâu mười tầng. Nó ngu ngốc đến nỗi bạn có 1 cây stacktrace dài cả ngàn dòng... Trong khi đó, một vòng lặp for rõ ràng, minh bạch, ai đọc cũng hiểu.
Bạn nghĩ đệ quy giúp code ngắn gọn hơn? Code ngắn không đồng nghĩa code tốt. Code phải dễ đọc, dễ maintain, và không crash giữa đêm khi bạn đang ngủ. Đệ quy làm code mong manh hơn, khó kiểm soát hơn, và là nguyên nhân của những lần on-call ám ảnh.
Hãy nhìn vào đoạn code này, cái nào dễ hiểu hơn ?
Đệ quy
public class MyFibonanci {
public static int fibonacci(int n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
public static void main(String[] args) {
int n = 10;
System.out.println("\nFibonacci(" + n + ") = " + fibonacci(n));
}
}
Vòng lặp
public class SimpleFibonacci {
public static void main(String[] args) {
int n = 10;
int first = 0, second = 1;
for (int i = 2; i < n; i++) {
int next = first + second;
System.out.print(next + " ");
first = second;
second = next;
}
System.out.println("\nFibonacci(" + n + ") = " + second);
}
}
... Nếu bạn bảo phần đệ quy dễ hiểu hơn thì chúc mừng, bạn chắc chắn đã có Computer Science Degree trong CV, vài giải Competitive Programing treo trong phòng khách của bố mẹ, và Genshin Impact trong điện thoại.

Tôi sẽ nhấn mạnh thêm một lần nữa: nếu bạn vẫn đang dùng đệ quy cho mọi thứ – duyệt mảng, tính tổng, thậm chí in ra dãy số – bạn đang biến codebase của mình thành một quả bom hẹn giờ. Production code không phải nơi để khoe “thanh tao”. Nó là nơi cần chạy ổn định, tiết kiệm tài nguyên, và không khiến đồng đội bạn phải chửi thề.
Đệ quy chỉ nên tồn tại trong một số rất ít trường hợp thật sự cần thiết: duyệt cây, backtracking, chia để trị. Ngoài ra? Vứt nó đi. Dùng vòng lặp, dùng stack/queue thủ công, dùng cách nào cũng được miễn đừng biến chương trình thành con tin của call stack.
Nếu bạn thấy khó chịu khi đọc những dòng này, tốt. Nghĩa là bạn đang tự hỏi lại mình. Đệ quy không biến bạn thành lập trình viên "pro" – nó khiến bạn ngạo nghễ và để lại một đống "sh*t" khi bạn rời đi và người khác phải maintain đống đệ quy của bạn. Và đến lúc production crash, thì nhớ nhé: "Đệ quy đẹp trên sách"
Happy coding != recursion
