Cách tính Cyclomatic complexity

Ưu và nhược điểm của Độ phức tạp Cyclomatic như một thước đo

Trong blog này, chúng ta sẽ xem xét Độ phức tạp Cyclomatic là gì, cách tính toán nó và một số công cụ bạn có thể sử dụng trong môi trường viết mã hàng ngày của mình. Chúng tôi cũng sẽ xem xét mức độ hữu ích của nó như là một số liệu để đo lường mức độ phức tạp của mã của bạn.

Đầu tiên, làm cách nào để đo độ phức tạp của mã?

Hãy dành một phút để quan sát ba đoạn mã sau, tất cả đều hoạt động giống nhau. Đoạn trích nào sau đây là "hay nhất" ?

Câu trả lời cho câu hỏi đó rất chủ quan và phụ thuộc vào số liệu bạn đang sử dụng để đo lường cái nào là "tốt nhất" . Một số có thể thích Option 1vì nó có số dòng mã ít nhất, tuy nhiên, một số có thể cho rằng tùy chọn này hy sinh khả năng đọc với chi phí ngắn gọn.

Tiếp theo từ ví dụ đó, làm thế nào để bạn đo lường độ phức tạp của mã ? Một số chỉ số thường được sử dụng bao gồm:

  • Các dòng mã hoặc độ dài
  • Số lượng phụ thuộc
  • Kiểm tra vùng phủ sóng
  • Làm thế nào nó dễ dàng để kiểm tra
  • Nó dễ đọc như thế nào
  • Sử dụng các mẫu phổ biến hoặc các tính năng ngôn ngữ
  • Đặt tên biến tốt
  • Số lượng sao chép

Chúng ta hãy đi sâu vào Độ phức tạp Cyclomatic, là một số liệu thường được sử dụng để đo độ phức tạp của mã. Giống như tất cả các phương pháp được liệt kê ở trên, Cyclomatic Complexity không phải là một phương pháp hoàn hảo để tính toán mã phức tạp hay tốt như thế nào, tuy nhiên nó là một số liệu thú vị để hiểu và ghi nhớ.

Cyclomatic Complexity là gì?

Định nghĩa

Độ phức tạp theo chu kỳ là thước đo mức độ phức tạp của mã của bạn. Nó đại diện cho số lượng đường dẫn độc lập tuyến tính thông qua một chương trình. Số lượng phức tạp càng cao, mã của bạn càng phức tạp .

Với một lưu đồ của một sơ đồ, độ phức tạp chu kỳ có thể được tính bằng công thức:

E - N + 2*P where: - E: # edges - N: # nodes - P: # connected components

Đây là một ví dụ về tính toán độ phức tạp chu kỳ của một thuật toán.

Thuật toán:

if [a == 10] { if [b > c] { a = b; } else { a = c; } } print[a]; print[b]; print[c];

Độ phức tạp:

Đồ thị trên có 8 cạnh , 7 nút1 thành phần liên thông . Do đó, chúng ta có thể tính độ phức tạp như sau:

E = 8 N = 7 P = 1 complexity = 8 - 7 + [2 * 1] = 3

Có rất nhiều công cụ có sẵn cho phép bạn phân tích độ phức tạp theo chu kỳ của mã của bạn. Chúng có thể được thêm vào môi trường phát triển cục bộ hàng ngày của bạn để cho phép bạn thấy độ phức tạp của mã bạn đang viết:

  • Đối với JavaScript, một eslintquy tắc cho phép đặt ngưỡng độ phức tạp theo chu kỳ://eslint.org/docs/rules/complexity
  • Phần mở rộng VSCode CodeMetrics [dành cho JavaScript]: //marketplace.visualstudio.com/items?itemName=kisstkondoros.vscode-codemetrics
  • checkstyle cho Java, có thể được sử dụng trong IDE hoặc CI của bạn: //github.com/checkstyle/checkstyle
  • JArchitect dành cho Java: //www.jarchitect.com/
  • SonarQube cho 27 ngôn ngữ lập trình: //www.sonarqube.org/

Mặc dù Độ phức tạp của Cyclomatic là một số liệu rất hữu ích, nhưng có những ưu và nhược điểm khi thực thi nó như một thước đo.

Ưu điểm của việc sử dụng Cyclomatic Complexity làm thước đo:

  • Độ phức tạp Cyclomatic cao có thể là dấu hiệu cho thấy chức năng hoặc mô-đun của bạn đang làm quá nhiều việc và cần được chia nhỏ
  • Sử dụng linter giúp ghi nhớ sự phức tạp của nhà phát triển trong khi viết mã và có thể được ghi đè để chỉ tăng độ phức tạp khi cần thiết
  • Một số vấn đề trong mã của chúng tôi về bản chất là phức tạp và việc thực thi một quy tắc cứng thông qua một linter sẽ là một ý tưởng tồi. Ngay cả trong eslint complexitytài liệu quy tắc, nó cho biết nếu bạn không thể xác định giới hạn độ phức tạp thích hợp cho mã của mình, thì tốt nhất bạn nên tắt quy tắc này.
  • Trong một số trường hợp, phức tạp hơn thì dễ đọc hơn

Ví dụ này cho thấy rõ ràng rằng Độ phức tạp Cyclomatic thấp hơn không phải lúc nào cũng tương ứng với mã tốt hơn.

Các số liệu khác về độ phức tạp của mã

Cùng với Độ phức tạp Cyclomatic, đây là một số số liệu khác có thể được sử dụng để phân tích độ phức tạp của mã của bạn:

  • Khớp nối liên quan [ca]
  • Khớp nối hiệu quả [ce]
  • Không ổn định

Đối với JavaScript, eslintcó một số quy tắc khác có thể hữu ích để áp dụng các hạn chế đối với số dòng, cấp độ lồng hoặc số lượng tham số trong mã của bạn:

  • max-depth //eslint.org/docs/rules/max-depth
  • max-lines //eslint.org/docs/rules/max-lines
  • max-lines-per-function //eslint.org/docs/rules/max-lines-per-function
  • max-nested-callbacks //eslint.org/docs/rules/max-nested-callbacks
  • max-params //eslint.org/docs/rules/max-params

Tóm tắt:

  • Độ phức tạp theo chu kỳ cao nên là một gợi ý rằng mã của bạn có thể được chia nhỏ / đơn giản hóa, nhưng không phải là một quy tắc cứng
  • Sử dụng độ phức tạp cao làm chỉ số mà bạn nên kiểm tra kỹ lưỡng
  • Sử dụng linter hoặc phần mở rộng để giúp lưu ý đến sự phức tạp của chu kỳ

[1] Doag.org, [2017]. Chỉ số chất lượng mã được phân cấp //www.doag.org/formes/pubfiles/8909795/2017-IDE-Jeroen_Resoort-Code_Quality_Metrics_Demystified-Praesentation.pdf

Video liên quan

Chủ Đề