Code rác (spaghetti code, bừa bộn, big ball of mud) là mã nguồn hỗn loạn, cấu trúc kém, khó đọc, khó bảo trì và khó sửa đổi mà không có nguy cơ làm hỏng thứ gì đó. Thuật ngữ này mô tả một codebase nơi các phụ thuộc chồng chéo, không có kiến trúc thống nhất và các nguyên tắc code sạch bị vi phạm. Theo TIOBE Index, 2025, các dự án có mức nợ công nghệ cao cần trung bình gấp 4 lần thời gian để thêm chức năng mới so với các codebase được tổ chức tốt.
Điểm chính
Code rác (cũng gọi là spaghetti code, bừa bộn, big ball of mud) là một phép ẩn dụ cho một codebase đã mất cấu trúc và biến thành một mạng lưới phụ thuộc rối rắm. Trong code như vậy, bất kỳ thay đổi nào ở một nơi sẽ làm hỏng nơi khác, và thêm chức năng mới trở thành một nhiệm vụ đầy rủi ro.
Trong phát triển di động, code rác đặc biệt nghiêm trọng: một ứng dụng xây dựng trên “sự bừa bộn” bắt đầu chậm, treo trên các thiết bị cũ và khó vượt qua review code. Một dự án iOS không có kiến trúc có thể không qua được App Review vì không ổn định.
Theo Stripe, lập trình viên dành tới 42% thời gian làm việc để đọc và hiểu code hiện có. Trong các dự án có code rác, con số này vượt quá 60%, khiến việc phát triển trở nên cực kỳ kém hiệu quả.
Spaghetti code là thuật ngữ lâu đời nhất, xuất hiện từ những năm 1970. Nó mô tả code có luồng điều khiển hỗn loạn, giống như mì sợi rối.
Big ball of mud là thuật ngữ do Brian Foote và Joseph Yoder đưa ra năm 1997 để mô tả các hệ thống không có kiến trúc rõ ràng phát triển một cách hỗn loạn.
Code rác làm chậm việc đưa tính năng mới ra thị trường. Nhóm dành thời gian không phải để tạo ra giá trị, mà để cố gắng hiểu cách code hiện có hoạt động và làm sao không làm hỏng bất cứ thứ gì.
Theo McKinsey, các công ty có chất lượng code thấp chi tiêu nhiều hơn 20-40% cho bảo trì sản phẩm, và tốc độ ra mắt tính năng mới thấp hơn 2-3 lần so với các công ty có chất lượng code cao.
Nhận biết code rác có thể thực hiện qua một tập hợp các chỉ báo khách quan, một số được đo tự động. Càng nhiều chỉ báo trùng khớp, vấn đề càng nghiêm trọng.
Trong ngành, các chỉ số chất lượng code như Halstead Complexity, Maintainability Index và Technical Debt Ratio được sử dụng. Hiểu các chỉ số này giúp đánh giá khách quan tình trạng của một codebase.
Dấu hiệu phổ biến nhất của code rác là các khối code lặp lại. Thay vì trích xuất một hàm chung, lập trình viên sao chép code từ nơi này sang nơi khác với những thay đổi tối thiểu.
Mức trùng lặp lên tới 5% được coi là bình thường. Nếu trùng lặp vượt quá 15%, đó là một tín hiệu nghiêm trọng. Các công cụ như Simian và PMD Copy Paste Detector giúp phát hiện sao chép tự động.
Một phương thức dài hơn 100 dòng là dấu hiệu rõ ràng của code rác. Phương thức như vậy thường làm quá nhiều và vi phạm Nguyên tắc Đơn trách nhiệm (Single Responsibility).
Các lớp có hơn 1000 dòng code cũng có vấn đề. Chúng chứa các chức năng không liên quan, gây khó khăn cho việc kiểm thử, hiểu và sửa đổi code.
Độ phức tạp vòng (Cyclomatic Complexity) của McCabe là một chỉ số cho thấy số lượng đường dẫn độc lập trong code. Giá trị trên 15 được coi là có vấn đề.
Các phương thức có độ phức tạp trên 30 nằm trong “vùng thảm họa.” Chúng chứa quá nhiều nhánh, khiến việc kiểm thử và hiểu chúng không thể thực hiện được nếu không phân tích sâu.
Code rác không xuất hiện “tự nhiên” — nó luôn là kết quả của các quy trình và quyết định nhất định trong nhóm. Hiểu nguyên nhân giúp ngăn chặn nó trong tương lai.
Theo JetBrains Developer Ecosystem 2024, 67% lập trình viên thừa nhận viết code tệ hơn khả năng do thiếu thời gian. Đây là nguyên nhân chính tích tụ nợ công nghệ.
Nguyên nhân phổ biến nhất là thời hạn chặt chẽ. Nhóm viết code “thế nào cũng được”, chỉ để kịp thời hạn. Tái cấu trúc, kiểm thử và review code bị hoãn lại “để sau.”
Vấn đề là “để sau” không bao giờ đến — thời hạn mới xuất hiện trong sprint tiếp theo, và nợ công nghệ chồng chất như quả cầu tuyết.
Không có review code, mỗi lập trình viên viết theo phong cách riêng, sử dụng mẫu riêng và để lại “dấu vết” riêng. Theo thời gian, codebase mất tính thống nhất.
Các nhóm thực hành review code bắt buộc cho mọi pull request có ít lỗi hơn 60% trong sản xuất, theo nghiên cứu của SmartBear 2024.
Nếu một dự án bắt đầu mà không có kiến trúc rõ ràng, code rác là điều không thể tránh khỏi. Những “giải pháp nhanh” đầu tiên đặt nền móng mà sau này khó xây dựng điều gì chất lượng trên đó.
Trong phát triển di động, việc chọn kiến trúc (MVC, MVP, MVVM, Clean Architecture) phải là một quyết định có ý thức được đưa ra trước khi bắt đầu viết code, không phải kết quả của sự tiến hóa.
Chống lại code rác đòi hỏi một cách tiếp cận hệ thống và kỷ luật từ toàn bộ nhóm. Không có một công cụ hay thực hành nào giải quyết được vấn đề — cần một tập hợp các biện pháp.
Nguyên tắc chính là ngăn chặn code rác ngay tại giai đoạn viết, không phải sửa nó sau này. Phòng ngừa luôn rẻ hơn so với việc tái cấu trúc một “đống bừa bộn” hiện có.
Phong cách code thống nhất là nền tảng để ngăn chặn code rác. Các tiêu chuẩn mã (Code Style) cần được ghi lại và tự động kiểm tra bởi các công cụ lint.
Cho iOS sử dụng SwiftLint, cho Android sử dụng Ktlint và Detekt. Cấu hình các quy tắc trong tệp cấu hình cho phép tự động từ chối các pull request vi phạm tiêu chuẩn.
Tái cấu trúc không phải là sửa lỗi, mà là cải thiện cấu trúc code mà không thay đổi hành vi. Nó nên là một phần thường xuyên của quy trình phát triển, không phải một dự án riêng biệt.
Nên dành 20% thời gian của mỗi sprint cho tái cấu trúc và trả nợ công nghệ. Điều này ngăn chặn sự tích tụ “sự bừa bộn” và duy trì tốc độ của nhóm về lâu dài.
Mỗi pull request phải được ít nhất một lập trình viên xem xét. Review code không chỉ phát hiện lỗi mà còn cả vi phạm kiến trúc, vấn đề phong cách và các nguồn tiềm ẩn của code rác.
Một thực hành tốt là danh sách kiểm tra cho review code bao gồm kiểm tra sao chép, độ dài phương thức, độ phức tạp vòng và mức độ bao phủ kiểm thử. Không có danh sách kiểm tra, người review bỏ sót tới 50% vấn đề.
Các công cụ phân tích code hiện đại cho phép tự động phát hiện code rác, đo lường nợ công nghệ và giám sát chất lượng. Tích hợp các công cụ này vào đường ống CI/CD cung cấp giám sát liên tục.
Nên sử dụng ít nhất một trình phân tích tĩnh và một công cụ đo lường chỉ số. Ngoài ra, có thể kết nối một nền tảng tổng hợp dữ liệu chất lượng code.
Theo SonarSource, các nhóm sử dụng phân tích tĩnh giảm số lỗi sản xuất xuống 30% ngay trong quý đầu tiên sau khi áp dụng.
CodeClimate và Codacy là các nền tảng tổng hợp các chỉ số chất lượng code, theo dõi xu hướng và hiển thị các “điểm nóng” — các tệp có nợ công nghệ cao nhất.
Cho các dự án Android, Detekt cung cấp hơn 100 quy tắc phân tích tích hợp sẵn, bao gồm kiểm tra độ phức tạp vòng, độ dài phương thức và trùng lặp code.
Câu hỏi thường gặp
Loại bỏ hoàn toàn code rác trong một dự án lớn đã phát triển nhiều năm là điều thực tế không thể. Mục tiêu không phải là “code sạch”, mà là mức nợ công nghệ có thể kiểm soát, không cản trở việc phát triển.
Bắt đầu bằng cách đo lường trạng thái hiện tại: chạy một trình phân tích tĩnh, lấy các chỉ số và xác định các mô-đun có vấn đề nhất. Sau đó hệ thống, sprint sau sprint, tái cấu trúc các khu vực quan trọng nhất.
Tái cấu trúc mà không kiểm thử không phải là tái cấu trúc, mà là viết lại code mù quáng. Không có kiểm thử, không thể xác minh rằng hành vi không thay đổi. Trước khi tái cấu trúc code legacy, hãy bao phủ nó bằng các kiểm thử đặc tính.
Áp dụng kiểm soát cổng cho mỗi pull request: kiểm tra tự động bằng lint, phê duyệt review code, mức bao phủ kiểm thử trên ngưỡng quy định. Không có code nào vào nhánh chính mà không qua tất cả các cổng.
Hãy cho thấy chi phí của nợ công nghệ bằng tiền: bao nhiêu giờ được dành cho việc bảo trì code rác, bao nhiêu lỗi phát sinh từ nó, nó làm chậm việc ra mắt tính năng mới như thế nào. Các chỉ số SonarQube Technical Debt Ratio là một lập luận thuyết phục.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm