CRAP: Chỉ số đo lường 'mã nguồn rác' trong lập trình
Bài viết trên blog Google Testing giới thiệu CRAP (Change Risk Anti-Patterns), một chỉ số do Alberto Savoia và Bob Evans phát triển nhằm phát hiện các đoạn mã nguồn khó bảo trì. Chỉ số này kết hợp độ phức tạp vòng (cyclomatic complexity) với độ phủ kiểm thử tự động để đánh giá rủi ro của từng phương thức trong mã nguồn.

CRAP: Cách đo lường và nhận diện "mã nguồn rác" trong lập trình
CRAP là viết tắt của Change Risk Anti-Patterns (tạm dịch: các mẫu phản thiết kế gây rủi ro khi thay đổi mã nguồn) — một thuật ngữ nghe có vẻ khiếm nhã nhưng lại ẩn chứa mục đích nghiêm túc: bảo vệ lập trình viên khỏi những đoạn mã thực sự tệ hại.
Xuất phát từ thực tế
Khi một lập trình viên hay kiểm thử viên phải làm việc với mã nguồn của người khác, họ hiếm khi nhận xét bằng những thuật ngữ kỹ thuật khô khan như "độ phức tạp vòng trung vị không chấp nhận được" hay "giá trị ghép nối hiệu ứng quá cao". Thay vào đó, họ thường tóm gọn bằng một câu đơn giản: "Đoạn code này như rác!".
Chính vì vậy, Alberto Savoia và cộng sự Bob Evans đã quyết định tạo ra một từ viết tắt vừa dễ nhớ, vừa khớp với ngôn ngữ mà người dùng mục tiêu thực sự sử dụng — đủ sức thu hút sự chú ý của bất kỳ lập trình viên nào: "Này, code của bạn là CRAP!"
Vậy điều gì khiến một đoạn code trở thành CRAP?
Không có cách nào hoàn toàn khách quan để xác định "độ rác" của mã nguồn. Tuy nhiên, dựa trên kinh nghiệm, trực giác cùng một chút nghiên cứu và nhiều bằng chứng thực nghiệm, các tác giả nhận thấy tồn tại những mẫu có thể đo lường được, phản ánh khả năng xuất hiện của mã nguồn kém chất lượng.
Chỉ số này ban đầu được xây dựng cho Java nhưng sau đó đã được chuyển thể sang nhiều ngôn ngữ và nền tảng khác như .NET, Ruby, PHP, Maven, Ant. Nó cũng xuất hiện trong các công cụ phân tích mã nguồn cả miễn phí lẫn thương mại, ví dụ như Cobertura của Hudson hay Clover của Atlassian.
Công thức CRAP1
Đây là công thức đầu tiên được đưa ra để phát hiện các phương thức Java kém chất lượng:
CRAP1(m) = comp(m)² × (1 − cov(m)/100)³ + comp(m)
Trong đó:
- CRAP1(m): điểm CRAP1 của phương thức m
- comp(m): độ phức tạp vòng (cyclomatic complexity) của phương thức m
- cov(m): độ phủ kiểm thử tự động theo đường cơ sở (basis path coverage) cho phương thức m
Nếu CRAP1(m) > 30, phương thức đó bị coi là "CRAPpy" (rác).
Công thức này không phải sinh ra từ hư không — nó là kết quả của một quá trình thử và sai kéo dài, dựa trên việc phân tích mã nguồn của nhiều dự án Java mã nguồn mở lẫn thương mại cùng các bộ kiểm thử JUnit đi kèm. Nhóm tác giả đã xếp hạng mức độ "rác" của các đoạn code, tham khảo ý kiến đồng nghiệp, rồi điều chỉnh liên tục cho đến khi đạt được đường cong phù hợp nhất với đánh giá chủ quan của con người.
Vì sao CRAP1 là một chỉ số hợp lý?
Việc viết kiểm thử tự động cho những đoạn code phức tạp, rối rắm là vô cùng khó khăn. Do đó, code kém chất lượng thường đi kèm với rất ít hoặc không có kiểm thử tự động nào.
Ngược lại, sự hiện diện của kiểm thử tự động ngụ ý rằng:
- Đoạn code đó có khả năng kiểm thử ở một mức độ nhất định — điều này thường đi đôi với thiết kế tốt hơn, có chủ đích hơn
- Lập trình viên đã quan tâm đủ, hiểu đủ và có đủ thời gian để viết kiểm thử — một dấu hiệu tích cực cho những người kế thừa mã nguồn sau này
Giới hạn của CRAP1
Như mọi chỉ số phần mềm khác, CRAP1 không hoàn hảo và không đầy đủ. Các tác giả thừa nhận rõ ràng rằng:
- Có thể có độ phủ kiểm thử cao nhưng các bài kiểm thử lại kém chất lượng
- Đôi khi mã phức tạp là điều không thể tránh khỏi hoặc thậm chí tốt hơn — một phương thức phức tạp đôi khi dễ hiểu hơn ba phương thức đơn giản cộng lại
- Công thức CRAP1 hiện chưa tính đến các chỉ số thiết kế bậc cao hơn liên quan đến khả năng bảo trì, như độ gắn kết (cohesion) và độ ghép nối (coupling)
Áp dụng CRAP vào dự án của bạn
Mặc dù Savoia và Evans không còn tích cực phát triển Crap4J trong những năm gần đây, nhiều lập trình viên khác đã tiếp tục chuyển thể CRAP sang nhiều ngôn ngữ và môi trường khác nhau. Nếu muốn thử áp dụng CRAP cho dự án của mình, cách tốt nhất là tìm kiếm theo ngôn ngữ và công cụ bạn đang dùng.
Một số ví dụ:
- .NET: có các dự án như crap4n và crap4net
- PHP: đã có bản triển khai CRAP cho PHPUnit
- COBOL: dường như vẫn chưa ai làm — đây có thể là cơ hội của bạn!
Lời kết
CRAP là một ví dụ thú vị về cách cộng đồng lập trình viên biến những quan sát chủ quan thành chỉ số đo lường được. Dù không hoàn hảo, nó vẫn là công cụ hữu ích giúp các nhóm phát triển phần mềm nhận diện sớm những đoạn mã có nguy cơ gây khó khăn khi bảo trì về sau.
Với các đội ngũ phát triển phần mềm tại Việt Nam — đặc biệt trong bối cảnh nhiều dự án outsourcing và sản phẩm nội địa đang ngày càng chú trọng chất lượng mã nguồn — việc áp dụng các chỉ số như CRAP có thể giúp cải thiện đáng kể quy trình kiểm thử và duy trì tính bền vững của hệ thống.


