Aynı yöntemi birden çok kez çağırırken siklomatik karmaşıklık


12

Code Review'daki bir soru sayesinde , Cyclomatic Complexity'nin aşağıdaki kod için tam olarak ne olduğu konusunda küçük bir anlaşmazlığa girdim (bu aslında bir şeyler öğrenme fırsatıdır).

public static void main(String[] args) {
    try {
        thro();
        thro();
        thro();
        thro();
        thro();
        thro();
        thro();
    }
    catch (NullPointerException e) {
    }
}

private static Random random = new Random();

public static void thro() throws NullPointerException {
    if (random.nextBoolean())
        throw new NullPointerException();
    System.out.println("No crash this time");
}

Eclipse'de bu kodu yazarken ve Eclipse metrikleri eklentisini kullanırken , ana yöntem için McCabe Cyclomatic Complexity'nin 2 olduğunu ve throyöntem için 2 olduğunu söylüyor.

Ancak, bir başkası bana throbirden çok kez çağrı yapmanın karmaşıklığının olduğunu söyler number of calls * method complexityve bu nedenle ana yöntemin karmaşıklığının 7 * 2 = 14 olduğunu iddia eder.

Farklı şeyleri mi ölçüyoruz? İkimiz de doğru olabilir miyiz? Veya buradaki gerçek siklomatik karmaşıklık nedir?


5
Yalnızca iki yol olduğu için işlevin CC değeri iki olur. CC programı daha yüksektir. Bu karanlıkta tam bir bıçak, ama kod analiz yazılımı tek bir seferde tüm karmaşık bir uygulamanın CC hesaplanamazlığı nedeniyle her işlevi ayrı bir kara kutu olarak kabul varsayalım.
Phoshi

@Phoshi Bunu bir cevap olarak yazar ve (mümkünse) ikisinin ayrılığının olduğunu gösteren bağlantılar sağlarsanız, bu cevabı memnuniyetle kabul ederim.
Simon Forsberg

CC ölçümlerdeki olası istisnalar neden olduğu tüm yolları, tanrı yardımına sayarsak 10. altındaki numarayı almak için bazı önemsiz kod üstlenmeden üzerinde soru soruldu adam
mattnz

Yanıtlar:


9

Doğru bu anlaşılır olduğunda, cyclomatic karmaşıklığı arasında main8 - kodu ile lineer bağımsız yolların sayısı olduğu. Ya yedi satırdan birinde bir istisna alırsınız ya da hiçbiri, ama asla birden fazla olamaz. Olası "istisna noktalarının" her biri, koddaki farklı bir yola tam olarak karşılık gelir.

McCabe bu metriği icat ettiğinde, istisna yönetimi göz önünde bulundurularak programlama dilleri yoktu.


Ama istisnayı atan çizgilerin hangisi gerçekten önemli?
Simon Forsberg

5
@ SimonAndréForsberg: evet, öyle. "Thro" kelimesinin çağrıldığında global bir sayacı arttırdığı bir yan etkiye sahip olduğunu düşünün (bu, kod boyunca olası yolları değiştirmez). Bu sayacın olası sonuçları 0 ila 7'dir, bu da CC'nin en az 8 olduğunu kanıtlar .
Doc Brown

Kullandığım metrik eklentisinin yöntem için yanlış bir değer bildirdiğini söyleyebilir misiniz main?
Simon Forsberg

@ SimonAndréForsberg: Evet, metrik eklentinizi bilmiyorum, ancak 2 belli ki 8 değil.
Doc Brown

Sorumda metrik eklentisine bir bağlantı var ....
Simon Forsberg

6

'Diğer adam' olarak, burada cevap vereceğim ve söylediklerim konusunda kesin olacağım (ki diğer formlarda özellikle hassas olmadığım).

Yukarıdaki kod örneğini kullanarak, siklomatik karmaşıklığı 8 olarak hesaplıyorum ve kodda bunu nasıl hesapladığımı göstermek için yorumlar var. İçinden başarılı bir döngü ele alacağız yolları tanımlamak için tümthro() 'main' 'kod yolu olarak çağrıları' (veya 'CP = 1'):

public static void main(String[] args) {
  try {
             // This is the 'main' Code Path: CP = 1
    thro();  // this has a branch, can succeed CP=1 or throw CP=2
    thro();  // this has a branch, can succeed CP=1 or throw CP=3
    thro();  // this has a branch, can succeed CP=1 or throw CP=4
    thro();  // this has a branch, can succeed CP=1 or throw CP=5
    thro();  // this has a branch, can succeed CP=1 or throw CP=6
    thro();  // this has a branch, can succeed CP=1 or throw CP=7
    thro();  // this has a branch, can succeed CP=1 or throw CP=8
  }
  catch (NullPointerException e) {
  }
}

Yani, bu ana yöntemde 8 kod yolunu sayıyorum, ki bu bana 8'lik bir Siklomatik Karmaşıklık.

Java terimlerinde, bir işlevden çıkmak için kullanılan her mekanizma karmaşıklığına sayılır, bu nedenle, başarı durumuna sahip bir yöntem ve örneğin, muhtemelen en fazla 3 istisna atan bir yöntem 4 belgelenmiş çıkış yoluna sahiptir.

Böyle bir işlevi çağıran bir yöntemin karmaşıklığı:

CC(method) = 1 + sum (methodCallComplexity - 1)

Benim görüşüme göre, yani dikkate başka şeyler düşünmek catchfıkra yok değil , yöntemin karmaşıklığı katkı catchsadece hedefidir throwsmultipl hedefi şube ve böylece bir catch bloğu throws sayıları 1 kez her biri için throwve her şey için sadece bir kez değil.


OutOfMemoryExceptions için olası şubeleri de mi sayıyorsunuz? Pedant olarak kod dallarına neden olabilirler, ancak kimse metriğin yararlılığını seyreltirken onları saymaz.
Telastyn

Hayır, değilim ... ve haklısın, ama bu argüman bağlamında, sadece yöntemin attığı bildirilen istisnaları sayıyorum. Ayrıca, bir yöntem üç istisna bildirir, ancak callinch kodu yapar catch (Throwable t) {...sonra o atmak için bildirdiği kaç istisna önemli değil sanırım.
rolfl
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.