30 Temmuz 2014 Çarşamba

Parasoft C/C++ Test Metrics Notlarım

Giriş
Konuyla ilgili olarak Parasoft C/C++ Test Statik Analiz başlıklı yazıya göz atabilirsiniz.

Eğer Parasoft pahalı geliyorsa Visual Studio ile de Code Metric alınabiliyor. Ancak bu araç sadece managed code için çalışıyor.

Builtin Metrics Konfigürasyonu
Builtin > Static Analysis > Metrics konfigürasyonu kullanılarak metrikler ölçülebilir. Esasında bu konfigürasyon herşey için yeterli. Kendi statik analiz projemiz ile metrik ölçümünü aynı konfigürasyon içine koyabiliriz ancak bence bu tercih edilmemeli.

Kendi Konfigürasyonumuz İçin Metrik Ayarlaması

Metrikler Number of Fields/Methods etrafında yoğunlaşıyor.

Coupling Between Objects    <30
Inheritance Depth                  <5
Lack of Cohesion                 < 0.9

Number of private fields         < 20
Number of private methods     < 20
Number of protected fields      < 20
Number of protected methods < 20
Number of public fields          < 20
Number of public methods      < 20

Number of constructors          <6
Number of fields                    < 30
Number of instance fields      < 10
Number of instance methods < 30
Number of methods               < 50

Number of static fields           < 20
Number of static methods      < 20



İlginç metrikler "Coupling Between Objects" (çok fazla bağımlılık) ve "Lack of Cohesion" (sınıfın birden fazla iş yapması)
Functionally Cohesive ve Sequentially Cohesive arasındaki farkı anlatan bir yazı burada.

Metrik Sonuçları
Metrik sonuçları Parasoft > Show View > Metrics veya Parasoft > Show View > Quality Tasks altında görülebilir. İlk pencere okuması daha kolay bir sunum sağlıyor.

Olmayan metrikler
Kodlama standartlarına konmasına rağmen olmayan bazı metrikler var. Demek ki bu metrikler aslında çok önemli değil.

Length of Method
Metodların uzunluğu konusunda bir çok fikir öne sürülüyor. 20, 65 veya 100 satırı geçmemeli diyenler var.

Clean Code: A Handbook of Agile Software Craftsmanship, Robert Martin:

The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that. Functions should not be 100 lines long. Functions should hardly ever be 20 lines long.


29 Temmuz 2014 Salı

Outlook Notlarım

E-Postanın To Kısmı
İsmin baş kısmını yazıp Ctrl + K tuşlarına basınca ismi tamamlar.

23 Temmuz 2014 Çarşamba

Fork-Join Framework

Fork-Join Nedir?
Verilen işin sürekli daha küçük parçalara bölünerek işlenmesi ve sonucun birleştirilerek elde edilmesidir. Fork-join ve Java 8 ile gelen stream framework bazı açılardan benzeşiyor. Her ikisi de işleri daha küçük parçalara ayırıyorlar

ForkJoin anladığım kadarıyla Doug Lea'nin bir makalesi üzerine geliştirilmiş.

ForkJoin Pool sınıfı

ForkjoinPool böl ve fethet yöntemi uygulanabilen işlerde çok faydalı.Diğer thread pool'lardan farklı olarak threadler daemon olarak yaratılıyorlar. Dolayısıyla shutdown() metodunun çağırılmasına gerek kalmıyor.

ForkJoinPool ile iki çeşit ForkJoinTask kullanılabiliyor. Bunlar RecursiveAction ve RecursiveTask.
RecursiveAction ile sonuç dönülemezken, RecursiveTask ile dönülebiliyor

Not : ForkJoinPool'un amacı dışında böl ve fethet yöntemi kullanılmadan, sadece bir sabit newFixedThreadPool gibi kullanıldığı bir örnek burada.


RecursiveTask Nasıl Çalışır?

Bu örnekte alt görevler fork() metodu ile başlatılıyor ve join() metodu ile sonuçları birleştiriliyor. Aşağıdaki şekli buradan aldım.

ForkJoin kullanımını eleştiren bir yazıdan ise aşağıdaki şekli aldım.
Result solve(Problem problem) {
       if (problem is small)
         directly solve problem
       else {
        split problem into independent parts
        fork
 new subtasks to solve each part
        join all subtasks
        compose result from subresults
    }
}

invoke Metodu ile Sonuç Nasıl Alınır?
Pool'dan sonucu alma örneği
ForkJoinPool pool = new ForkJoinPool();
Long result = pool .invoke (new MyRecursiveTask()); //Sonucu al
Burada ForkJoinPool kullanımına da bir başka örnek var.
Bu sınıf ile kullanılan RecursiveTask'ın compute(), fork() ve join() metodlarını iyi anlamak lazım. Büyük lokma önce daha küçük parçalara ayrılıyor. Daha sonra küçük lokmaların 1 tanesi hariç, diğerleri iş kuyruğuna ekleniyorlar. Kuyruğa eklenmeyen küçük lokma mevcut thread tarafından çalıştırılıyor.

fork() metodu daha küçük parçaya ayrılan yeni işi kuyruğa ekler. Her thread'in kendi kuyruğu var, ancak gerekirse diğer thread'ler iş çalma (work stealing) yapabilirler.
compute() metodu daha küçük parçaya ayrılan yeni işi kuyruğa eklemeden mevcut thread ile çalıştırır.
join() metodu kuyruktaki çalıştırılan işin bitmesini bekler.



Bir başka örnekte ise verilen dizinin alt dizinlerini listeme var.

RecursiveAction Örneği :
Bu kullanım şekilinde genellikle global tüm action nesneleri tarafından erişilebilen bir nesneye işlem uygulanıyor. Örneği buradan aldım

//Default parallelism level = Runtime.getRuntime().availableProcessors()
ForkJoinPool fjpool = new ForkJoinPool(64);
int arrayLength = 100000000;
int array[] = new int[arrayLength];
RecursiveAction task = new RandomFillAction(array, 0, array.length);
fjpool.invoke(task);

class RandomFillAction extends RecursiveAction {
    int low;
    int high;
    private int[] array;
    splitSize = 40000; //Some threshold size to spit the task
   
    public RandomFillAction(int[] array, int low, int high) {
        this.low = low;
        this.high = high;
        this.array = array;
    }

    @Override
    protected void compute() {
        if (high - low > splitSize) {
            // task is huge so divide in half
            int mid = (low + high) >>> 1;
            invokeAll(Arrays.asList(new RandomFillAction(array, low, mid), 
                                                 new RandomFillAction(array, mid, high))
                          );
        } else {
            //Some calculation logic
            Random random = new Random();
            for (int i = low; i < high; i++) {
                array[i] = random.nextInt(10000);
            }
        }
    }
}  

Bir başka örnekte ise RecursiveAction nesnesi global bir listedeki nesneleri metodlarını çağırıyor. Örnekteki computeDirectly metodu en küçük bölünmenin gerçekleştiği yeri gösteriyor.

ForJoinPool ve Thread Sayısı
ForJoinPool (int parallelism)
ile kaç tane thread ile çalışmasını istediğimizi belirtiyoruzÖrnek:

Eğer parametre vermezsek bu sayı CPU sayısına eşit oluyor. Örnek:

ForkJoinPool ve Thread'in Beklemesi
Buradaki soruda ForkJoinPool'un CPU sayısından daha fazla thread'e sahip olamayacağı yazıyor. Eğer thread'lerden birisi I/O için beklerse, diğer bekleyen işler için yeni bir thread yaratılmıyorBurada bu konuyu açıklayan şimdiye kadar gördüğüm en iyi cevap var.

5 Temmuz 2014 Cumartesi

Düzenli İfade Örnekleri

Bazı düzenli ifade örneklerini aşağıya ekledim.

Düzenli İfadelerde Kullanılan Özel Karakterler Sınıfları
Özel karakter sınıfları belli bir kümedeki karakterlerle eşleşirler
Basit bir şekil aşağıda.

Harfler

[a-z] aralığında boşluk karakteri (space) de aralığa dahildir.

Sayılar
\d ile bir sayı karakteri ifade edilir.

\D ile sayı olmayan bir karakter ifade edilir.
Örnekte "046 55.5" şeklindeki bir telefon numarası non-digit karakterler silinerek "046555" haline getiriliyor.
Regex.Replace(value, @"\D", "") 

Boşluk
\s ile boşluk (space) karakteri ifade edilir. Anladığım kadarıyla \t (tab) karakteri de boşluk olarak kabul ediliyor.

Boşluk olmayanlar 
 \S ile space olmayan karakterler ifade edilir. Örneğin (\S+)\s+(.+?) ile space olmayan bir grup, sonra bir veya daha fazla boşluk, sonra ise yakalamak istediğimiz grubu buluruz. Space olmayan karakterleri [^\\s] şeklinde de ifade edebileceğimizi sanıyorum. 

Kelime
\w ile bir word (kelime) ifade edilir. [A-Za-z0-9_] ifadesinin kısa halidir. string.replaceAll java doesn't work with lookaround regex? örneğinde \w ifadesine { karakterinin dahil edilmediği görülebilir. 

Kelime Olmayanlar
\W \w kısaltmasının tam tersini yapar. Yani alfanümerik olmayan imla işareti gibi "," ";" "." gibi karakterleri bulur.

Çapalar (Anchor)
Çapalar ile düzenli ifade moturu bir sonraki karakteri işlemez. Ama koşulun tutup tutmadığını değerlendirir.

\b ile word boundary ifade edilir. Örneğin \bcat\b ifadesi ile The cat scattered his food all over the room. cümlesinde sadece cat kelimesi ile eşleşilir.
\B \b kısaltmasının tam tersini yapar
^ ile string'in başı belirtilir. Multiline modu kullanılmıyorsa cümle içinde \n karakterini dikkat almaz.

Quantifiers 

Grubun Uzunluğunu Kontrol Etme Örnekleri
0 ila 11 tane arasında olması gerektiğini belirtmek için \d{0,11} yazıyoruz. Tamı tamına 11 tane olması için \d{11} yazıyoruz. Bir başka örnek ise burada.

Eğer bir quantifier  bir kaç defa tekrar edecekse örneğin, parantez içine alma gerekebilir. Örnek:
^(\d{1}){2} // iki defa tekrar etsin
Greedy

Düzenli ifadeler default olarak greedy çalışırlar. Örneğin \s+ ile azami eşleşme yapılırken \s+? ile reluctant çalışması sağlanır. Yani ? işareti greedy çalışmayı engeller.

Escape yapılması gereken özel karakterler
  • { karakteri aslıda "kaç tane"anlamına gelen kısaltma olduğu için - örneğin \d{2}'nin escape ile işaretlenmesi gerekir. Dolayısıyla \d\\{2 şeklinde yazılmalı.
İçerildiğini Bulma Örnekleri
Bir ifadenin içerildiğini bulmak
".*true.*" örneğinde string içinde true kelimesinin geçip geçmediği geçtiği bulunabilir.

Bir veya birkaç karakterin içerildiğini bulmak
.*[x-z].* örneğinde x-z arasındaki (her ikisi de dahil) herhangi bir karakterin içerildiği kontrol edilir.

Bir ifade ile başlanılmadığını bulmak
"^[^\\d].*" örneğinde string'in sayı ile başlayıp başlamadığı bulunabilir

İçeriği Yakalama Örnekleri
Bir ifade ile başlamak ve geri kalanı yakalamak