SORU
19 EYLÜL 2008, Cuma


Koşullu az cyclomatic karmaşıklığı ile giriş

Okuduktan sonra "What’s your/a good limit for cyclomatic complexity?" fark ettim ki birçok meslektaşım, bizim proje üzerinde QA bu yeni politikası ile rahatsız olmuştuk: 10 cyclomatic complexity başına işlevi. artık

Anlamı: en fazla 10 '', 'başka','', '' ve diğer kod akışı dallanma deyimi. yakalamak deneyin Doğru. 'Do you test private method?', böyle bir politikayı çok iyi bir yan etkisi vardır. içinde de açıkladığım gibi

Ama: başında bizim (200 kişi - 7 yıl uzun) projesi, biz mutlu günlüğü (ve hayır, biz kolay bir temsilci için bir çeşit 'Aspect-oriented programming' yaklaşımı için günlükleri).

myLogger.info("A String");
myLogger.fine("A more complicated String");
...

Ve sistemimizin ilk sürümleri canlı gitti, çünkü günlük bir noktada kapalı oldu, çünkü değil, ama büyük bir hafıza sorunu yaşadıkgünlük parametreleri(dizeleri), her zaman hesaplanmış, daha sonra geçer 'ınfo()' veya 'iyi()' fonksiyonları, sadece keşfetmek için bu seviye günlük oldu, ve o günlük yok edildi yaşanıyor!

QA geri geldi ve bizim programcılar istismarcılar yapmaya çağırdı. Her zaman.

if(myLogger.isLoggable(Level.INFO) { myLogger.info("A String");
if(myLogger.isLoggable(Level.FINE) { myLogger.fine("A more complicated String");
...

Ama şimdi, o '---taşındı' 10 cyclomatic karmaşıklık seviyesi fonksiyon sınırı savunuyorlar bu ayrıntı onlar koymak onların işlevi keçe gibi bir yük, çünkü her "(isLoggable())" olarak sayılan 1 cyclomatic karmaşıklık!

Eğer öyleyse bir işlevi vardır 8 'Eğer', 'başka' ve böylece, bir sıkıca bağlı değil-kolayca paylaşılabilir algoritma ve 3 günlük kritik eylemler... onlar sınır ihlali olsa bile koşullu günlükleri olmayabilirgerçektenparçası dedi bu fonksiyonun karmaşıklığı...

Bu durumu nasıl hitap edersin ?
İlginç kodlama evrim birkaç (nedeniyle 'çatışma') projem, ama ben önce senin fikirlerini almak istiyorum. bunu gördüm


Tüm cevaplar için teşekkür ederim.
Sorun '' ilgili, ama 'bağımsız değerlendirme' ile ilgili olan bir yöntemin çağrılması, bir şey yapar hemen önce çok pahalı yapmak, değerlendirme) . biçimlendirme olmadığı konusunda ısrar ediyorum ^br> Öyle bir yazmış yukarıda "Bir Dize", aslında demek istedim aFunction () ile aFunction() döndüren bir Dize ve bir çağrı için karmaşık bir yöntem toplama ve bilgi işlem her türlü günlük verilerini Görüntülenmesine tarafından logger... ya da değil (bu nedenle sorun, vezorunlulukistismarcılar, yapay asıl sorun, bu nedenle artışın kullanmak 'cyclomatic karmaşıklık'...)

Ben şimdi 'variadic' nokta bazılarınız teşekkürler John () tarafından gelişmiş. fonksiyon olsun
Not: bir hızlı test java6 gösteren benim varargs function mu değerlendirmek argümanları önce olmak denir, bu yüzden uygulanamayacağı için işlev çağrısı, ama 'Günlük retriever nesne' (ya da 'fonksiyonu sarıcı'), hangi olabilirdi sadece demem gerekirse. Anladım.

Şimdi bu konuda benim deneyim attılar.
Orada oy için önümüzdeki Salı gününe kadar giderim, sonra cevaplar birini seçin.
Yine, bütün öneriler için teşekkür ederim :)

CEVAP
19 EYLÜL 2008, Cuma


Geçerli oturum ile çerçeveler, gereksiz bir soru

Slf4j veya log4j 2 gibi güncel günlük çerçeveleri çoğu durumda görevlisi ifadeleri gerekmez. Bir olay koşulsuz olarak kaydedilir böylece parametreli log deyimi kullanıyorlar, ama mesaj biçimlendirme yalnızca olay etkinleştirilmişse oluşur. Mesaj inşaat, bunun aksine, ön uygulama tarafından yerine logger tarafından gerektiği gibi yapılır.

Eğer bir antika kitaplığa günlük kullanım için, daha fazla arka plan ve parametrik mesaj ile eski kütüphane güçlendirme için bir yol almak için okumaya devam edebilirsiniz.

Bekçi ifadeleri gerçekten karmaşıklık ekler.

Cyclomatic karmaşıklık hesaplama günlük gardiyan tablolar hariç düşünün.

Öngörülebilir yapısından dolayı, istismarcılar kontrolleri gerçekten kodun karmaşıklığına katkıda bulunmayan söylenebilir.

Esnek olmayan Ölçümler dışında iyi programcı bir dönüş kötü hale getirebilir. Dikkatli olun!

Karmaşıklık hesaplama araçları o derece uygun olabilir mi varsayarak, aşağıdaki yaklaşım iş çevresinde bir teklif olabilir.

Koşullu gerek günlük

Ben herhangi bir Güvenlik ifadeleri bu gibi bir kod vardı çünkü tanıtıldı varsayalım:

private static final Logger log = Logger.getLogger(MyClass.class);

Connection connect(Widget w, Dongle d, Dongle alt) 
  throws ConnectionException
{
  log.debug("Attempting connection of dongle "   d   " to widget "   w);
  Connection c;
  try {
    c = w.connect(d);
  } catch(ConnectionException ex) {
    log.warn("Connection failed; attempting alternate dongle "   d, ex);
    c = w.connect(alt);
  }
  log.debug("Connection succeeded: "   c);
  return c;
}

Java, günlük tabloların her bir yeni StringBuilder oluşturur ve her nesne bir dize için birleştirilmiş toString() yöntemi çağırır. Bu toString() yöntemleri, sırayla, muhtemelen oluşturmak StringBuilder örnekleri kendi ve çağırmak toString() yöntemler üyeleri, ve bu yüzden, karşısına bir potansiyel olarak büyük nesne grafiği. (Java önce 5 StringBuffer kullanıldığı için daha pahalı olduğunu, ve tüm faaliyetlerini eşitlenir.)

Bu özellikle eğer log deyimi ağır idam kod bazı yolu ise nispeten daha pahalıya mal olabilir. Ve yazılı olarak yukarıda, pahalı ileti biçimlendirme eğer logger giriş seviyesi çok yüksek olduğundan sonucu iptal bağlıysa bile oluşur.

Bu form, bekçi tabloların giriş yol açar:

  if (log.isDebugEnabled())
    log.debug("Attempting connection of dongle "   d   " to widget "   w);

Bu koruma ile, bağımsız değişkenler d w ve dize birleştirme değerlendirme sadece gerektiğinde yapılır.

Basit, verimli günlük oluşturma için bir çözüm

Ancak, eğer logger (veya sarıcı yazıyorsunuz etrafında seçtiğiniz paket günlüğü) alır biçimlendiricisi ve bağımsız değişkenler için biçimlendirici iletiyi inşaat olabilir geciken kadar belli ki kullanılacak, süre ortadan nöbetçi ifadeleri ve onların cyclomatic karmaşıklığı.

public final class FormatLogger
{

  private final Logger log;

  public FormatLogger(Logger log)
  {
    this.log = log;
  }

  public void debug(String formatter, Object... args)
  {
    log(Level.DEBUG, formatter, args);
  }

  … &c. for info, warn; also add overloads to log an exception …

  public void log(Level level, String formatter, Object... args)
  {
    if (log.isEnabled(level)) {
      /* 
       * Only now is the message constructed, and each "arg"
       * evaluated by having its toString() method invoked.
       */
      log.log(level, String.format(formatter, args));
    }
  }

}

class MyClass 
{

  private static final FormatLogger log = 
     new FormatLogger(Logger.getLogger(MyClass.class));

  Connection connect(Widget w, Dongle d, Dongle alt) 
    throws ConnectionException
  {
    log.debug("Attempting connection of dongle %s to widget %s.", d, w);
    Connection c;
    try {
      c = w.connect(d);
    } catch(ConnectionException ex) {
      log.warn("Connection failed; attempting alternate dongle %s.", d);
      c = w.connect(alt);
    }
    log.debug("Connection succeeded: %s", c);
    return c;
  }

}

ŞimditoString() tampon pozisyonlarını aramaları basamaklı hiçbiri ortaya çıkargerekli olmadıkça! Bu etkin koruma tablolara yol açan performans isabet ortadan kaldırır. Küçük bir ceza, Java, otomatik boks logger geçmesi herhangi bir basit tür argümanlar olurdu.

Kod giriş yaparak düzensiz dize birleştirme gittiğine göre muhtemelen her zamankinden daha temiz. Biçim dizeleri de yazılım bakım ve yerelleştirme yardımcı olabilecek taburcu (ResourceBundle kullanarak), eğer daha temiz olabilir.

Daha da geliştirmeleri

Ayrıca unutmayın, Java, bir MessageFormat nesne olabilir yerine kullanılan bir "biçim" String verir size ek özellikler gibi bir seçenek biçimine kolu kardinal sayılar daha düzgün. Başka bir alternatif "değerlendirme", temel yerine 22 ** yöntemi. tanımlamak için bazı arabirim çağıran kendi biçimlendirme yeteneği uygulamak olurdu

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Abe Olandres

    Abe Olandres

    16 EYLÜL 2006
  • Skrillex

    Skrillex

    6 NİSAN 2010
  • TomSka

    TomSka

    30 Mayıs 2006