"Độ phức tạp chu kỳ" của mã của tôi có nghĩa là gì?


42

Tôi mới phân tích tĩnh mã. Ứng dụng của tôi có độ phức tạp Cyclomatic là 17.754. Bản thân ứng dụng chỉ có 37.672 dòng mã. Có hợp lệ để nói rằng độ phức tạp cao dựa trên các dòng mã? Chính xác thì sự phức tạp của Cyclomatic nói gì với tôi?


Điều đó hoàn toàn phụ thuộc vào những gì bạn đang làm. Nếu bạn đang cố gắng làm một cái gì đó đơn giản, thì nó rất, rất cao. Bạn không nên có tỷ lệ đó trong "hello world", ví dụ.
cwallenpoole

Câu trả lời:


48

Chính xác thì sự phức tạp của Cyclomatic nói gì với tôi?

Độ phức tạp theo chu kỳ không phải là thước đo các dòng mã, mà là số lượng đường dẫn độc lập thông qua một mô-đun. Độ phức tạp chu kỳ của bạn là 17.754 có nghĩa là ứng dụng của bạn có 17.754 đường dẫn duy nhất thông qua nó. Điều này có một vài hàm ý, điển hình là mức độ khó hiểu và kiểm tra ứng dụng của bạn. Ví dụ, độ phức tạp chu kỳ là số lượng các trường hợp thử nghiệm cần thiết để đạt được phạm vi bao phủ 100% chi nhánh, giả sử các thử nghiệm được viết tốt.

Một điểm khởi đầu tốt có thể là bài viết Wikipedia về độ phức tạp chu kỳ . Nó có một vài đoạn mã giả và một số biểu đồ cho thấy độ phức tạp của chu kỳ là gì. Nếu bạn muốn biết nhiều hơn, bạn cũng có thể đọc bài viết của McCabe nơi ông đã xác định độ phức tạp theo chu kỳ .

Ứng dụng của tôi có độ phức tạp Cyclomatic gồm 17.754 dòng mã. Bản thân ứng dụng chỉ có 37.672 dòng mã. Có hợp lệ để nói rằng độ phức tạp cao dựa trên các dòng mã?

Không có gì. Một ứng dụng có vài dòng mã và số lượng lớn các điều kiện được lồng trong các vòng lặp có thể có độ phức tạp cực kỳ cao. Mặt khác, một ứng dụng có một vài điều kiện có thể có độ phức tạp chu kỳ thấp. Đó là sự đơn giản hóa nó lớn, nhưng tôi nghĩ rằng nó có ý tưởng xuyên suốt.

Nếu không biết thêm về những gì ứng dụng của bạn làm, có thể có độ phức tạp chu kỳ cao hơn. Tuy nhiên, tôi sẽ đề nghị đo độ phức tạp theo chu kỳ ở cấp độ hoặc phương thức, thay vì chỉ ở cấp độ ứng dụng. Về mặt khái niệm, điều này dễ quản lý hơn một chút - tôi dễ hình dung hoặc khái niệm hóa các đường dẫn thông qua một phương thức hơn là các đường dẫn thông qua một ứng dụng lớn.


36

Độ phức tạp theo chu kỳ là một cách để xác định xem mã của bạn có cần được cấu trúc lại hay không. Mã được phân tích và một số phức được xác định. Độ phức tạp được xác định bằng cách phân nhánh (nếu các câu lệnh, v.v.) Độ phức tạp cũng có thể tính đến việc lồng các vòng lặp, v.v. và các yếu tố khác tùy thuộc vào thuật toán được sử dụng.

Số này hữu ích ở cấp độ phương pháp. Ở cấp độ cao hơn, nó chỉ là một con số.

Một số 17.754 chỉ mức độ phức tạp của cấp dự án (tổng mã), không có nhiều ý nghĩa.

Việc đi sâu vào độ phức tạp của lớp và mức phương thức sẽ xác định các vùng của mã cần được cấu trúc lại thành các phương thức nhỏ hơn hoặc được thiết kế lại để làm giảm độ phức tạp.

Hãy xem xét một CASEtuyên bố với 50 trường hợp trong một phương pháp. Có thể mỗi tiểu bang có logic kinh doanh khác nhau. Điều đó sẽ tạo ra độ phức tạp theo chu kỳ là 50. Có 50 điểm quyết định. Câu lệnh CASE có thể phải được thiết kế lại bằng cách sử dụng mẫu nhà máy để loại bỏ logic phân nhánh. Đôi khi bạn có thể cấu trúc lại (chia phương thức thành các phần nhỏ hơn) và trong một số trường hợp chỉ thiết kế lại sẽ làm giảm độ phức tạp.

Nói chung, đối với độ phức tạp của phương thức:

  • <10 Dễ bảo trì
  • 11-20 Khó bảo trì hơn
  • Hơn 21 ứng viên tái cấu trúc / thiết kế lại

Cũng xem xét rằng độ phức tạp cao hơn làm cho mã khó hơn để kiểm tra đơn vị.

Độ phức tạp cao nhất tôi đã thấy trên một phương thức duy nhất là 560. Đó là khoảng 2000 dòng if câu lệnh trong một phương thức. Về cơ bản không thể nhầm lẫn, không thể kiểm chứng, đầy lỗi tiềm năng. Hãy tưởng tượng tất cả các trường hợp thử nghiệm đơn vị cần thiết cho logic phân nhánh đó! Không tốt.

Hãy thử và giữ tất cả các phương thức dưới 20 và nhận ra rằng có một chi phí để tái cấu trúc bất kỳ phương pháp nào để làm cho nó ít phức tạp hơn.


Đây là một câu trả lời tốt hơn.
Pacerier

2
@Pacerier Trong trường hợp đó, chỉ cần đưa ra câu trả lời;).
Zero3

> "Nói chung, đối với độ phức tạp của phương thức" Trích dẫn?
Benny Bottema

Một trong những ứng dụng ban đầu của McCabe là hạn chế sự phức tạp của các thói quen trong quá trình phát triển chương trình; ông khuyến nghị các lập trình viên nên tính độ phức tạp của các mô-đun mà họ đang phát triển và chia chúng thành các mô-đun nhỏ hơn bất cứ khi nào độ phức tạp chu kỳ của mô-đun vượt quá 10.
Jon Raynor

"Câu lệnh CASE có thể phải được thiết kế lại bằng cách sử dụng mẫu nhà máy để loại bỏ logic phân nhánh." Tại sao? Điều đó không loại bỏ sự phức tạp của logic; nó chỉ che giấu nó và làm cho nó ít rõ ràng hơn, và do đó khó bảo trì hơn.
Mason Wheeler

1

Đó là số lượng đường dẫn riêng biệt trong ứng dụng của bạn. Kiểm tra bài viết này của IBM về CC .

Nó có vẻ cao nhưng trong trường hợp của bạn, đó là việc bổ sung CC của tất cả các phương thức của bạn cho tất cả các lớp và phương thức của bạn. Các ví dụ của tôi đã được mở rộng rất nhiều vì tôi không biết mã của bạn được cấu trúc như thế nào nhưng bạn cũng có thể có một phương thức quái vật với 37672 dòng mã hoặc 3767 phương thức với khoảng 10 dòng mã. Ý tôi là ở cấp độ ứng dụng, chỉ báo này không có ý nghĩa gì nhiều, nhưng ở cấp độ phương thức, nó có thể giúp bạn tối ưu hóa / viết lại mã của bạn thành các phương thức nhỏ hơn để chúng ít bị lỗi hơn.

Những gì cá nhân tôi đã đọc rất nhiều lần là các phương pháp có CC cao hơn 10 có rủi ro về khuyết tật cao hơn.

Tôi sử dụng Sonar để kiểm tra chất lượng mã của các ứng dụng của mình và theo mặc định tôi nghĩ rằng nó sẽ đưa ra cảnh báo nếu bạn có phương thức với +10 CC. Tuy nhiên, điều đó có nghĩa là không có gì. Một ví dụ cụ thể: nếu bạn sử dụng Eclipse để tạo một equalsphương thức dựa trên các thuộc tính của bean của bạn, CC sẽ nhanh chóng vượt lên trên mái nhà ...


1
Cài đặt mặc định của PMD cũng là để cảnh báo độ phức tạp theo chu kỳ là 10. Nhìn vào mức độ phức tạp ở cấp độ mỗi phương thức cũng cho phép bạn bỏ qua các phương thức có thể có lý do chính đáng cho CC cao, chẳng hạn như equalscác phương thức được tạo .
Thomas Owens

Tôi không chắc nên đã kiểm tra, nhưng Sonar sử dụng PMD để có được biện pháp này. Vì vậy, tất cả có ý nghĩa :-)
Jalayn

-1

Nó cho phép bạn sử dụng công cụ nào. Một số công cụ nguồn mở ngoài kia lấy lớp làm mô-đun hoặc mức cấu trúc khác làm mô-đun. Do đó, một dự án càng lớn, độ phức tạp Cyclomatic càng cao. Tuy nhiên, theo hiểu biết cá nhân của tôi, nó nên dựa trên cơ sở chức năng. Kể từ khi một dự án càng lớn, các chức năng mà nó tham dự phải có.

Tôi khuyên bạn nên sử dụng công cụ có tên Lizard và bạn có thể tìm mã tài nguyên và tải xuống tệp zip tại github. Nó cũng có phiên bản trực tuyến nếu không có nhiều thông tin bí mật trong mã của bạn.

CCN có ý nghĩa mà bạn nên quan tâm là trên cơ sở chức năng khác với bất kỳ cơ sở nào khác. Ngoài ra, giữ cho CCN unber 15 của mỗi chức năng sẽ là phạm vi lý tưởng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.