Siklomatik Karmaşıklığı Anlamak


11

Son zamanlarda Siklomatik Karmaşıklık ile karşılaştım ve daha iyi anlamaya çalışmak istiyorum.

Karmaşıklığın hesaplanmasına giren farklı faktörlerin pratik kodlama örnekleri nelerdir? Özellikle, Wikipedia denklemi için M = E − N + 2P, aşağıdaki terimlerin her birinin ne anlama geldiğini daha iyi anlamak istiyorum:

  • E = grafiğin kenar sayısı
  • N = grafiğin düğüm sayısı
  • P = bağlı bileşenlerin sayısı

Bir kod bloğunda E veya N karar noktalarının sayısı (eğer, foreach, for, vb. İçin) sayısı olduğundan şüpheleniyorum , ancak hangisinin diğerinin hangisini veya ne anlama geldiğinden emin değilim. Ayrıca, P'nin işlev çağrılarına ve sınıf örneklerine atıfta bulunduğunu tahmin ediyorum , ancak görebildiğim açık bir tanım yok. Birisi, her birinin açık kod örnekleriyle biraz daha fazla ışık tutabilirse, yardımcı olacaktır.

Takip olarak, Siklomatik Karmaşıklık% 100 yol kapsamı için gerekli olan birim test sayısı ile doğrudan ilişkili mi? Örnek olarak, karmaşıklığı 4 olan bir yöntem, bu yöntemi kapsamak için 4 birim testin gerekli olduğunu gösteriyor mu?

Son olarak, düzenli ifadeler Siklomatik Karmaşıklığı etkiler mi, eğer öyleyse, nasıl?


McCabe'nin orijinal makalesini Wikipedia'dan alabileceğinizi ve Google Kitaplar'ın McCabe'nin orijinal makalesi için kullandığı kitabı getireceğini buldum. İlginç bir şekilde, McCabe'nin orijinal teoremi yanlış kullandığını (ve yönlendirilmemiş bir grafikle başlaması gerektiği ve ilk etapta güçlü bir şekilde bağlanmasına gerek olmadığı için kafa karıştırıcı bir şekilde açıkladığını) göreceksiniz, ancak sayılar yine de doğru şekilde çıkıyor ( doğru formül M = E + 1-N + P olacaktır, ancak P her zaman 1 olduğu gibi, uyuyor ...) Modern "İstisna işleme" nin bu metriğin çalışmalarına bir anahtar attığı düşünülmektedir.
David Tonhofer

... ve özyinelemeli çağrılar hakkında (muhtemelen bir işlevler zincirinden geçiyor). Biri fonksiyon grafiklerini birleştiriyor mu? "&&" gibi kısa devre yapan boole operatörlerine ne dersiniz? "Ref? .X" gibi korumalı operatörler, ref boşsa null verir? Oh, sadece başka bir ölçüm. Ama burada küçük bir üniversite projesi için biraz çalışma var.
David Tonhofer

Yanıtlar:


8

Formüle ilişkin olarak: düğümler durumları, kenarlar durum değişikliklerini temsil eder. Her programda, ifadeler program durumunda değişiklikler getirir. Her ardışık ifade bir kenar ile temsil edilir ve ifadenin yürütülmesinden sonraki (veya önce ...) programın durumu düğümdür.

Bir dallanma ifadeniz varsa ( iförneğin) - o zaman iki düğümünüz var, çünkü durum iki şekilde değişebilir.

Siklomatik Karmaşıklık Numarasını (CCN) hesaplamanın başka bir yolu, yürütme grafiğinde kaç "bölge" olduğunu hesaplamaktır (burada "bağımsız bölge", başka daireler içermeyen bir dairedir). Bu durumda CCN, bağımsız bölgelerin artı 1 sayısı olacaktır (önceki formülün size verdiği tam sayı ile aynı olacaktır).

CCN, dallanma kapsamı veya aynı yol kapsamı için kullanılır . CCN, tek bir dişli uygulamada teorik olarak mümkün olan farklı dallanma yollarının sayısına eşittir (" if x < 2 and x > 5 then" gibi dallar içerebilir , ancak bu ulaşılamaz bir kod olarak iyi bir derleyici tarafından yakalanmalıdır). En azından bu sayıda farklı test senaryosuna sahip olmalısınız (bazı test vakaları öncekiler tarafından kapsanan yolları tekrar ediyor olabilir, ancak her vakanın tek bir yolu kapsadığını varsaymak daha az olabilir). Herhangi bir olası test senaryosuyla bir yolu kapatamıyorsanız - ulaşılamaz bir kod buldunuz (buna rağmen neden erişilemediğini kendinize kanıtlamanız gerekecek , muhtemelen bir x < 2 and x > 5yerlerde iç içe gizlenmiş).

Düzenli ifadelere gelince - elbette diğer herhangi bir kod parçasını etkiler. Bununla birlikte, normal ifade yapısının CCN'si tek bir birim testinde karşılamayacak kadar yüksektir ve normal ifade motorunun test edildiğini varsayabilir ve ifadelerinizin test ihtiyaçlarınız için dallanma potansiyelini göz ardı edebilirsiniz ( regex motoru, tabii ki).


2
+1: Aslında, normal ifade motorunun test edildiğine güvenmelisiniz . Eğer güven yoksa, o bir tane yapmak güven.
S.Lott

"CCN, tek iş parçacıklı bir uygulamada mümkün olan farklı yürütme yolu sayısına eşittir" CCN, sadece kodun anlamına göre değil topolojisine dayandığından yanlıştır . Bu yolların iyi bir yüzdesinin ayarlanamayan girdi durumunu talep ettikleri için kullanılması imkansız olabilir (bazı x'ler 5 ve ayrıca 2'den azdır). Açıkçası, CCN'nin test senaryolarının yürütülmesine karar vermek için kullanılması sapık olduğunu düşünüyorum. CCN, geliştiriciye "burada denize girmiş olabilirsiniz, lütfen yeniden düzenleme yapmayı düşünün" diyen bir sayıdır. Ve o zaman bile, yüksek CCN için iyi bir neden olabilir.
David Tonhofer

1
@David bunu ele almak için bir cümle ekledi. CCN bir şube kapsamıdır ve daha düşük bir düzeyde yüksek CCN için asla iyi nedenler yoktur (genellikle bireysel işlev başına yaptırmayı öneririm).
littleadv

Şube kapsamı ve yol kapsamı aynı değildir. Şube kapsamı tüm şubeleri kapsamayı hedeflerken, şube kapsamı tüm şube kombinasyonlarını kapsamayı amaçlamaktadır.
Mouviciel

13

Bu konuda boş yere yazdığım bazı açıklamalar ...

Özellikle, M = E - N + 2P'nin Wikipedia denklemi için

Bu denklem çok yanlış .

Bir nedenden ötürü, McCabe gerçekten orijinal belgesinde ("Bir Karmaşıklık Ölçümü", IEEE Yazılım Mühendisliği İşlemleri, Vo .. SE-2, No.4, Aralık 1976), ancak haklı göstermeden ve gerçekten doğru olduktan sonra ilk sayfadaki formül

v (G) = e - v + p

(Burada formül öğeleri yeniden etiketlendi)

McCabe özellikle C.Berge, Graphs and Hypergraphs (aşağıda G&HG olarak kısaltılmıştır) kitabına referansta bulunmaktadır . Doğrudan bu kitaptan :

Tanım (sayfa 27, G&HG'nin alt kısmı):

Bir (yönlendirilmemiş) grafik G'nin (birkaç bağlantısı kesilmiş bileşene sahip olabilen) siklomatik sayısı v (G) şu şekilde tanımlanır:

v (G) = e - v + p

burada e = kenar sayısı, v = köşe sayısı, p = bağlı bileşen sayısı

Teorem (sayfa 29 G&HG'nin üstü) (McCabe tarafından kullanılmaz):

Bir grafiğin G siklomatik sayısı v (G), maksimum bağımsız döngü sayısına eşittir

Bir döngü , aynı tepe noktasında başlayan ve biten bir köşe dizisidir ve dizideki birbirini takip eden her iki köşe, grafikte birbirine bitişiktir.

Sezgisel olarak, bir döngü grubu olan , bağımsız döngü hiçbiri yürür atma diğerlerinden inşa edilmesi mümkün bulunmaktadır.

Teorem (G&HG'nin sayfa 29'u) (McCabe tarafından kullanıldığı gibi):

Güçlü bir şekilde bağlı G grafiğinde, siklomatik sayı maksimum doğrusal olarak bağımsız devre sayısına eşittir.

Bir devre izin köşe ve kenarlar herhangi bir tekrarlı bir döngüdür.

Her tepe noktasına her bir tepe noktasından belirlenen yönden kenarlardan geçerek ulaşılabiliyorsa, yönlendirilmiş bir grafiğin güçlü bir şekilde bağlandığı söylenir .

Not biz geçirilen burada o yön verilmemiş grafiklerle için kuvvetle bağlı grafiklerde (yönlendirilir ... Berge bu tamamen açık yapmaz)

McCabe şimdi bir "McCabe Siklomatik Karmaşıklık Numarası" (CCN) hesaplamak için basit bir yol elde etmek için yukarıdaki teoremi uygulamaktadır:

Bir prosedürün “atlama topolojisini” temsil eden yönlendirilmiş bir grafik verildiğinde (talimat akış grafiği), benzersiz giriş noktasını temsil eden belirlenmiş bir tepe noktası ve benzersiz çıkış noktasını temsil eden belirlenmiş bir tepe noktası (çıkış noktası tepe noktasının “yapılandırılması gerekebilir” birden çok döndürme durumunda ekleyerek), çıkış noktası tepe noktasından giriş noktası tepe noktasına yönlendirilmiş bir kenar ekleyerek, böylece giriş noktası tepe noktasını başka bir tepe noktasından erişilebilir hale getirerek güçlü bir şekilde bağlı bir grafik oluşturun.

McCabe şimdi, değiştirilmiş talimat akış grafiğinin siklomatik sayısının "sezgisel 'minimum yol sayısı'" anlayışımıza uyduğunu (ve kafa karıştırıcı diyebilirim) ve bu sayıyı karmaşıklık ölçüsü olarak kullanacağız.

Harika, yani:

Değiştirilmiş talimat akış grafiğinin siklomatik karmaşıklık sayısı, yönlendirilmemiş grafikteki "en küçük" devreler sayılarak belirlenebilir. Bunun insan veya makine tarafından yapılması özellikle zor değildir, ancak yukarıdaki teoremi uygulamak bize bunu belirlemenin daha kolay bir yolunu verir:

v (G) = e - v + p

kenarların yönlülüğünü göz ardı ederse.

Her durumda, sadece tek bir prosedür düşünüyoruz, bu yüzden tüm grafikte sadece bir bağlı bileşen var ve bu yüzden:

v (G) = e - v + 1.

Eklenen "girişten çıkış" kenarı olmadan orijinal grafiği dikkate alırsanız, basitçe elde edilir:

ṽ (G) = ẽ - v + 2

ẽ = e - 1 olarak

Makalesinde McCabe'nin örneğini kullanarak açıklayalım:

McCabe örneği

İşte burada:

  • e = 10
  • v = 6
  • p = 1 (bir bileşen)
  • v (G) = 5 (açıkça 5 döngüyü sayıyoruz)

Siklomatik sayının formülü şöyle diyor:

v (G) = e - v + p

5 = 10-6 + 1 verir ve bu yüzden doğru!

Makalesinde belirtildiği gibi "McCabe siklomatik karmaşıklık numarası"

5 = 9 - 6 + 2 (makalede nasıl yapılacağı konusunda başka açıklama yapılmamıştır)

ki bu doğru olur (v (G) verir) ama yanlış nedenlerle, yani kullanırız:

ṽ (G) = ẽ - v + 2

ve böylece ṽ (G) = v (G) ... vay!

Peki bu önlem iyi mi?

İki kelimeyle: Pek değil

  • Özellikle istisna işleme ve özyineleme resme girerse, bir prosedürün "talimat akış grafiği" nin nasıl oluşturulacağı tam olarak açık değildir. McCabe'nin fikrini , özyineleme, istisna ve basit bir yürütme yapısı olmayan bir dil olan FORTRAN 66'da yazılan koda uyguladığını unutmayın .
  • Kararlı bir prosedür ve bir döngü içeren bir prosedürün aynı CCN'yi vermesi iyi bir işaret değildir.

resim açıklamasını buraya girin


1
@JayElston İyi yakalama. Gerçekten de öyle. Sabit!
David Tonhofer

1
Orijinal kağıda bağlantı için büyük +1. O sırada yazılan makalelerin çoğu, herhangi bir orta seviye programcı için oldukça okunabilir ve okunmalıdır.
Daniel T.

1

Takip olarak, Siklomatik Karmaşıklık% 100 yol kapsamı için gerekli olan birim test sayısı ile doğrudan ilişkili mi?

Evet, temel olarak. Ayrıca, ne zaman yeniden düzenleme yapıldığının bir göstergesi olarak siklomatik karmaşıklığı kullanmak da iyi bir fikirdir. Deneyimlerime göre, test edilebilirlik ve tekrar kullanılabilirlik daha düşük CC için büyük ölçüde artar (pratik olsanız da - aşırı refraktör kullanmayın ve bazı yöntemler doğaları nedeniyle yüksek CC'ye sahip olacaktır - bunu denemek ve zorlamak her zaman mantıklı değildir. ) alt.

Son olarak, düzenli ifadeler Siklomatik Karmaşıklığı etkiler mi, eğer öyleyse, nasıl?

Evet, kesin olmak istiyorsanız, çoğu kod analiz aracı bunları bu şekilde dikkate almıyor gibi görünmektedir. Düzenli ifadeler sadece sonlu durum makineleridir, bu yüzden CC'lerinin FSM grafiğinden hesaplanabileceğini tahmin ediyorum, ancak oldukça büyük bir sayı olurdu.


+1 - RegExes için CC hesaplamanın eğlenceli bir görev olmadığını tahmin ediyorum.
VirtuosiMedia
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.