2008-10-15 34 views
18

Gần đây, công ty chúng tôi đã bắt đầu đo độ phức tạp chu kỳ (CC) của các hàm trong mã hàng tuần và báo cáo các chức năng nào đã được cải thiện hoặc xấu đi. Vì vậy, chúng tôi đã bắt đầu chú ý nhiều hơn đến CC của các chức năng.Tìm kiếm giải thích về cấu trúc mã để giảm độ phức tạp chu kỳ

Tôi đã đọc rằng CC có thể được tính không chính thức là 1 + số điểm quyết định trong một hàm (ví dụ: nếu câu lệnh, cho vòng lặp, chọn v.v ...) hoặc số lượng đường dẫn thông qua hàm ...

tôi hiểu rằng cách dễ nhất để giảm CC là sử dụng Extract Method refactoring nhiều lần ...

có somethings tôi không chắc chắn, ví dụ: CC của các đoạn mã sau là gì?

1)

for (int i = 0; i < 3; i++) 
    Console.WriteLine("Hello"); 

Console.WriteLine("Hello"); 
Console.WriteLine("Hello"); 
Console.WriteLine("Hello"); 

Cả hai đều làm điều tương tự, nhưng phiên bản đầu tiên có CC cao hơn vì câu lệnh for?

2)

if (condition1) 
    if (condition2) 
     if (condition 3) 
      Console.WriteLine("wibble"); 

if (condition1 && condition2 && condition3) 
    Console.WriteLine("wibble"); 

Giả sử các ngôn ngữ không đánh giá ngắn mạch, chẳng hạn như C#, sau đó hai đoạn mã có tác dụng tương tự ... nhưng là CC của mảnh đầu tiên cao hơn bởi vì nó có 3 điểm quyết định/nếu phát biểu?

3)

if (condition1) 
{ 
    Console.WriteLine("one"); 

    if (condition2) 
     Console.WriteLine("one and two"); 
} 

if (condition3) 
    Console.WriteLine("fizz"); 

if (condition4) 
    Console.WriteLine("buzz"); 

Hai đoạn mã làm những việc khác nhau, nhưng họ có cùng CC? Hay câu lệnh if lồng nhau trong đoạn đầu tiên có CC cao hơn không? tức là lồng nhau nếu các câu lệnh phức tạp hơn về mặt tinh thần để hiểu, nhưng điều đó được phản ánh trong CC?

Trả lời

8
  1. Có. Ví dụ đầu tiên của bạn có một điểm quyết định và điểm thứ hai của bạn thì không, vì vậy cái đầu tiên có CC cao hơn.
  2. Có thể, ví dụ đầu tiên của bạn có nhiều điểm quyết định và do đó CC cao hơn. (Xem bên dưới để được giải thích.)
  3. Có thể.Rõ ràng họ có cùng số điểm quyết định, nhưng có nhiều cách khác nhau để tính CC, có nghĩa là ...

... nếu công ty của bạn đo lường CC theo cách cụ thể thì bạn cần phải làm quen với phương pháp đó (hy vọng họ đang sử dụng các công cụ để làm điều này). Có nhiều cách khác nhau để tính CC cho các tình huống khác nhau (báo cáo trường hợp, toán tử Boolean, v.v.), nhưng bạn sẽ nhận được cùng một loại thông tin từ số liệu bất kể bạn sử dụng quy ước nào.

Vấn đề lớn hơn là những gì người khác đã đề cập, rằng công ty của bạn dường như tập trung nhiều hơn vào CC hơn là mã phía sau nó. Nói chung, chắc chắn, dưới 5 là tuyệt vời, dưới 10 là tốt, dưới 20 là okay, 21-50 nên là một dấu hiệu cảnh báo, và trên 50 phải là một dấu hiệu cảnh báo lớn, nhưng đó là những hướng dẫn, chứ không phải quy tắc tuyệt đối. Bạn có lẽ nên kiểm tra mã trong một thủ tục có CC trên 50 để đảm bảo nó không chỉ là một đống mã lớn, nhưng có thể có một lý do cụ thể tại sao quy trình được viết theo cách đó và không khả thi (đối với bất kỳ số lý do) để cấu trúc lại nó.

Nếu bạn sử dụng các công cụ để cấu trúc lại mã của bạn để giảm CC, hãy đảm bảo bạn hiểu công cụ đang làm gì và chúng không đơn giản chuyển một vấn đề sang một nơi khác. Cuối cùng, bạn muốn mã của bạn có ít lỗi, để hoạt động bình thường và tương đối dễ bảo trì. Nếu mã đó cũng có một CC thấp, tốt cho nó. Nếu mã của bạn đáp ứng các tiêu chí này và có CC trên 10, có thể đã đến lúc phải ngồi xuống với bất kỳ quản lý nào bạn có thể và bảo vệ mã của bạn (và có thể khiến họ kiểm tra chính sách của họ).

4

CC không phải là thuốc chữa bách bệnh để đo lường chất lượng. Rõ ràng một câu lệnh lặp lại không phải là "tốt hơn" so với một vòng lặp, ngay cả khi một vòng lặp có một CC lớn hơn. Lý do vòng lặp có một CC lớn hơn là đôi khi nó có thể được thực hiện và đôi khi nó có thể không, dẫn đến hai "trường hợp" khác nhau mà cả hai nên được kiểm tra. Trong trường hợp của bạn, vòng lặp luôn luôn được thực thi ba lần vì bạn sử dụng hằng số, nhưng CC không đủ thông minh để phát hiện điều này.

Tương tự với các chuỗi ifed trong ví dụ 2 - cấu trúc này cho phép bạn có một statment sẽ được thực hiện nếu chỉ condition1 và condition2 là đúng. Đây là trường hợp đặc biệt không thể xảy ra trong trường hợp sử dụng & &. Vì vậy, nếu chuỗi có một tiềm năng lớn hơn cho các trường hợp đặc biệt ngay cả khi bạn không sử dụng điều này trong mã của bạn.

6

Sau khi duyệt qua mục nhập wikipedia và trên số original paper của Thomas J. McCabe, có vẻ như các mục bạn đã đề cập ở trên là các vấn đề đã biết với chỉ số.

Tuy nhiên, hầu hết các chỉ số đều có ưu và khuyết điểm.Tôi cho rằng trong một chương trình đủ lớn giá trị CC có thể trỏ đến có thể là các phần phức tạp của của mã của bạn. Nhưng CC cao hơn đó không nhất thiết có nghĩa là phức tạp.

+0

Bạn đang đề cập đến bài báo gốc nào? bạn có thể cung cấp một liên kết? – RickL

+0

Đã thêm liên kết và tên (Thomas J McCabe) – moogs

+0

Cảm ơn, tôi đã lướt qua giấy, thật khó đọc vì nó theo kiểu kỹ thuật chính xác. – RickL

0

[Tắt chủ đề] Nếu bạn ủng hộ khả năng đọc trên điểm số tốt trong các số liệu (Có phải J.Spolsky nói rằng "đo được gì, được làm"? - nghĩa là số liệu bị lạm dụng thường xuyên hơn tôi không nghĩ) thường tốt hơn để sử dụng một boolean được đặt tên để thay thế câu lệnh điều kiện phức tạp của bạn.

sau đó

if (condition1 && condition2 && condition3) 
    Console.WriteLine("wibble"); 

trở thành

bool/boolean theWeatherIsFine = condition1 && condition2 && condition3; 

if (theWeatherIsFine) 
    Console.WriteLine("wibble"); 
+0

Có, tôi thường làm điều này nếu nó cải thiện khả năng đọc. Điều thú vị là, Refactoring - Cải thiện thiết kế của mã hiện tại sẽ khuyên bạn nên thực hiện phương thức Extract trên biến điều kiện hơn là Extract ... – RickL

1

Đây là sự nguy hiểm của việc áp dụng bất kỳ số liệu một cách mù quáng. Chỉ số CC chắc chắn có rất nhiều công đức nhưng cũng như với bất kỳ kỹ thuật nào khác để cải thiện mã, nó không thể được đánh giá đã ly hôn khỏi bối cảnh. Chỉ ra sự quản lý của bạn tại cuộc thảo luận của Casper Jone về các phép đo dòng mã (mong muốn tôi có thể tìm thấy một liên kết cho bạn). Ông chỉ ra rằng nếu các dòng mã là một thước đo tốt về năng suất thì các nhà phát triển ngôn ngữ lắp ráp là những nhà phát triển hiệu quả nhất trên trái đất. Tất nhiên họ không hiệu quả hơn các nhà phát triển khác; nó chỉ mang lại cho họ nhiều mã hơn để hoàn thành những gì các ngôn ngữ cấp cao hơn làm với ít mã nguồn hơn. Tôi đề cập đến điều này, như tôi đã nói, vì vậy bạn có thể cho các nhà quản lý của bạn biết cách sử dụng số liệu một cách mù quáng để áp dụng một cách mù quáng mà không cần đánh giá thông minh về những gì chỉ số nói cho bạn.

Tôi khuyên rằng nếu không, quản lý của bạn sẽ khôn ngoan để sử dụng biện pháp CC như một cách để phát hiện các điểm nóng tiềm năng trong mã cần được xem xét thêm. Nhắm mục tiêu một cách mù quáng cho mục tiêu của CC thấp hơn mà không cần tham chiếu đến khả năng bảo trì mã hoặc các biện pháp mã hóa tốt khác chỉ là ngu xuẩn.

+2

"Đo lường sản phẩm phần mềm theo các dòng mã giống như đo một chiếc máy bay nặng bao nhiêu." Bill Gates (Tôi tin)

4

Giống như tất cả các chỉ số phần mềm, CC không hoàn hảo. Được sử dụng trên cơ sở mã đủ lớn, nó có thể cung cấp cho bạn ý tưởng về nơi có thể là một vùng có vấn đề.

Có hai điều cần lưu ý ở đây:

  1. Big cơ sở mã đủ: Trong bất kỳ dự án không tầm thường, bạn sẽ có các chức năng có giá trị CC thực sự cao. Vì vậy, cao rằng nó không quan trọng nếu trong một ví dụ của bạn, CC sẽ là 2 hoặc 3. Một chức năng với một CC của chúng ta hãy nói hơn 300 chắc chắn là một cái gì đó để phân tích. Không quan trọng nếu CC là 301 hoặc 302.
  2. Đừng quên sử dụng đầu của bạn. Có nhiều phương pháp cần nhiều điểm quyết định. Thường thì chúng có thể được tái cấu trúc bằng cách nào đó để có ít hơn, nhưng đôi khi chúng không thể. Không đi với một quy tắc như "Refactor tất cả các phương pháp với một CC> xy". Hãy xem chúng và sử dụng bộ não của bạn để quyết định phải làm gì.

Tôi thích ý tưởng phân tích hàng tuần. Trong kiểm soát chất lượng, phân tích xu hướng là một công cụ rất hiệu quả để giải quyết các vấn đề trong quá trình tạo ra. Điều này tốt hơn rất nhiều so với việc phải đợi cho đến khi chúng trở nên lớn đến mức chúng trở nên rõ ràng (xem SPC để biết thêm chi tiết).

+0

Có, chúng tôi có thể thấy những gì đã thay đổi trong tuần qua, vì vậy bạn có thể thấy chức năng trong danh sách mà bạn đã làm và ghi nhớ những thay đổi của bạn xem tại sao CC lại tăng lên. Thật không may, ngưỡng của chúng tôi khá thấp và thường khó giảm CC dễ dàng. – RickL

+0

Vâng, đó là vấn đề tôi có với các quy tắc cố định. Họ có thể là ok cho 80 hoặc 90 phần trăm các trường hợp, nhưng vẫn còn 10% nơi họ hút. – Treb

1

Độ phức tạp của chu trình tương tự như nhiệt độ. Cả hai đều là số đo và trong hầu hết các trường hợp, vô nghĩa không có ngữ cảnh. Nếu tôi nói nhiệt độ bên ngoài là 72 độ không có nghĩa là nhiều; nhưng nếu tôi thêm vào thực tế là tôi đã ở Bắc Cực, con số 72 trở nên đáng kể. Nếu ai đó nói với tôi rằng một phương pháp có độ phức tạp chu kỳ là 10, tôi không thể xác định được phương pháp đó là tốt hay xấu mà không có ngữ cảnh của nó.

Khi tôi viết mã xem xét một ứng dụng hiện có, tôi thấy độ phức tạp của chu trình là một chỉ số “điểm bắt đầu” hữu ích. Điều đầu tiên tôi kiểm tra là các phương thức có CC> 10. Những phương thức “> 10” này không nhất thiết là xấu. Họ chỉ cung cấp cho tôi một điểm khởi đầu để xem xét mã.

Quy tắc chung khi xem xét một số CC:

  • Mối quan hệ giữa CC# và # kiểm tra, nên CC# < = #tests
  • Refactor cho CC# chỉ khi nó làm tăng khả năng bảo trì
  • CC trên 10 thường cho biết một hoặc nhiều Code Smells
0

Tôi không có chuyên môn về chủ đề này, nhưng tôi nghĩ tôi sẽ cung cấp cho hai ents. Và có lẽ đó là tất cả những điều này đáng giá.

Độ phức tạp của Cyclomatic dường như chỉ là một phím tắt tự động cụ thể để tìm đoạn mã có khả năng (nhưng không chắc chắn) có vấn đề. Nhưng không phải là vấn đề thực sự để giải quyết một thử nghiệm? Có bao nhiêu trường hợp kiểm tra mã yêu cầu? Nếu CC cao hơn, nhưng số lượng các trường hợp thử nghiệm là như nhau và mã là sạch hơn, đừng lo lắng về CC.

1.) Không có điểm quyết định ở đó. Có một và chỉ có một con đường thông qua chương trình ở đó, chỉ có một kết quả có thể với một trong hai phiên bản. Đầu tiên là ngắn gọn hơn và tốt hơn, Cyclomatic Complexity bị damned.

1 trường hợp kiểm tra cho cả hai

2.) Trong cả hai trường hợp, bạn viết "có thể" hoặc bạn thì không.

2 trường hợp thử nghiệm cho cả

3.) Đầu tiên có thể dẫn đến không có gì, "một", hay "một" và "một đến hai". 3 đường dẫn. Thứ hai có thể dẫn đến không có gì, cả hai, hoặc cả hai. 4 đường dẫn.

3 trường hợp kiểm tra cho 4 trường hợp thử nghiệm thứ nhất

Các vấn đề liên quan