Statik Kod Analizi

Statik kod analizi, benim için her zaman yazılım geliştirme sürecinin önemli bir parçası olmuştur. Çalıştığım hemen her şirkette elimden geldiğince, statik kod analizini oturtmaya, kod yazılımına belli standartlar getirmeye çalışmışımdır. Fakat son dönemde, Amazon’da çalışmaya başladığımdan beri, statik kod analizine bakışım biraz değişti.

Statik Kod Analizi Derken?

Statik kod analizi denildiğinde herkesin aklında aynı şey canlanmıyor olabilir. Bu sebepten önden kısa bir bilgi vermek istiyorum. Statik kod analizi, kodunuzun araçlar tarafından taranarak önceden belirlediğiniz kriterlere göre incelenmesidir. Kodunuzun belli bir kaliteyi tutturmasını sağlamak için yapılır. Eğer düzgün yapıyorsanız, üzerinde kaç kişilik takım çalışıyorsa çalışsın kodunuz tek bir elden çıkmış gibi gözükür. Tanıdığım herkes kaliteli kod yazıyor zaten, ne gerek var bir daha analiz etmeye? diyebilirsiniz. Doğrudur bende kodum kötü diyene rast gelmedim. Ama gelin görün kurallar net olmayabilir ya da aynı sonuca çıkan birden fazla kural olabilir. Bakın en basit örnek, kodunuzun rahat okunabilmesi için “girintileme” yaparsınız değil mi, boşluk bırakırsınız. “Tab” karakteri mi “boşluk” karakteri mi kullanırsınız? Farklı yazılımcılar farklı cevaplar verecektir. Ondan en kaliteli yazılımcılarla da çalışıyor olsanız, belli kurallar koymalısınız. İşte bu kuralları koymanın ve uygulamanın en basit yolu statik kod analizidir.

Statik kod analizi tabi ki de sadece “girintileme” gibi basit kurallardan oluşmuyor. Çok daha detaylı kurallar bulunmakta. Ama bu kuralları üç başlık altında inceleyebiliriz.

  • Yapısal Kurallar: “girintileme” örneği bu başlık altına giriyor. Ama tabi ki de bu kadar değil. Exception handling, method ve sınıf isimleri, parametre ve property isimleri, method uzunlukları, sınıf uzunlukları, javadoc yazımı vs. gibi kodunuzun yapısıyla ilgili tüm kurallar bu başlığa giriyor.
  • Çok bilinen, hatalı kalıplar: Bilinen, sık karşılaşılan ve genelde buglara yol açan tüm kod blokları bu başlık altına giriyor. Örnek vericek olursak, String sınıfını yanlış karşılaştırmak, karmaşıklığı yüksek kod blogları geliştirmek, bilinen güvenlik açığına yol acabilecek hatalar,  vs.
  • Test Kapsamınız: Unit testlerinizin kodunuzun ne kadarını kapsadığı ölçümü bu başlık altına giriyor.

Sonar!?

Sonar (daha doğrusu sonarqube), tüm bu başlıkları bünyesinde toplayan harika bir araç. Server olarak kuruyorsunuz, kurduğunuzda belli başlı kurallar zaten açık geliyor. Yetmezse başka kuralları da aktif ediyorsunuz. Hatta kurallar kritiklik seviyelerine göre ayarlanmış durumda. Yani sonar gidip tab karakteri ile girintileme yaptın diye bas bas bağırmıyor. Uyarıyor sadece. Barındırdığı kuralları ne kadar sürede çözüleceğini de az buçuk biliyor ve buradan size “Technical Depth”‘te çıkartıyor. Uzun zamandır hayatta olan bir proje olduğu için, diğer açık kaynaklı projelerle de entegrasyonu bulunuyor. Hemen hemen tüm build araçlarıyla entegre olduğu gibi, üzerine Hudson/Jenkis gibi çok kullanılan CDI ortamlarıyla da rahatlıkla entegre edebiliyorsunuz.

Açık konuşmak gerekirse, eskiden ilk tercihimdi. Fakat artık değil. En büyük eksiği, build sonrasında çalışacak şekilde tasarlanmış olması. Bu durumda ne oluyor, yazılımcı lokalinde çalıştırıyor Build’i, geçtiğini görünce kodunu gönderiyor. Hudson/Jenksins kuruluysa, orada da Build oluyor. Sonra sonara gönderiliyor veri. Sonar inceleyip hataları söylüyor. Burdan sonra yazılımcının insiyatifine kalmış. Sonar’ı açıp ister bakar ister bakmaz. Build’i falan da kırmış değil. Hevesli olan arkadaşlar açıp bakıyor, ama kabul edelim onlarda kendilerine göre uygun bulduklarını çözüyor. Ee isteyenin tab isteyenin boşluk kullanmasına kim engel olacak? Basit dediğimiz örneğe bile çözüm getiremedik.  Eğer takım lideri açıp Sonar’ı bakacaksa, yani manuel müdahelede bulunacaksa, o zaman açar kodu inceler neden Sonar’a baksın. Kaldı ki, Sonar’ı açıp baktığında da hüsranla karşılaşabiliyor. Öyle projeler gördüm ki daha üzerinde 2-3 ay çalışılmış olunmasına rağmen, Sonar üzerinden Technical Depth’i 2-3 ay gözüküyor. İnsanın morali bozulur, bir daha sonarın yüzünü görmek istemez. Çok normal…

Çözüm

Bu sebepten statik kod analizinin düzgün çalışması için build srasında yapılması ve bir değer bile kurallara uymuyorsa build’in kırılması lazım. Daha kod SCM’e ya da Hudson/Jenkins’e düşmeden yazılımcı kodunun durumunu bilmeli. Mesela tüm public alanlara javadoc yazılacak diye karar mı alındı, o zaman tek bir bile javadoc’suz sınıf olduğunda build’in kırılması gerekiyor. Aynı şekilde “girintileme” boşluk karakteri ile oluşturulacak mı denildi, aksi bir durum ile karşılaşıldığında Build’in kırılması gerekiyor.

Amazon’da da yapılan aynı bu. Belli kurallar var. Bu kurallar belli toollar üzerinden build sırasında çalıştırılıyor. Tek bir kural bile geçmezse build kırılıyor. Daha lokalinizde durumu biliyorsunuz. Kabul etmeliyim, ilk başta sinir bozucu olabiliyor. Özellikle size çok ters gelen kurallar varsa. Mesela, “Javadoc’un ilk satırının nokta ile bitmesi gerekir” diye bir kural var, bana çok ters gelen. Diğer kurallara çok takıldığım olmuyor. Çoğu zaten alışık olduğum, benim de desteklediğim kurallar. Ama buna bir süre alışamadım. Hala ara da sırada bu kurala düşüyorum. Fakat gelin görün ki zamanla bu hatayı yapmamaya başlıyorsunuz. Anlayacağınız, Build’in kırmanın getirdiği utanç iyi bir motivasyon kaynağına dönüşebiliyor.

Build’in kırılması

Peki tamam da build’in kırılmasını nasıl sağlayacağız? Sonardan vazgeçemeyenler için, müjdeli haber sonarın eklentisinin yanında bir iki eklenti daha kullanarak build’i kırabiliyorsunuz. Ama çok sağlıklı değil. Hatalı build kırılımlarına (mesela sonar beklenilen sürede cevap vermezse vs) yol açabiliyor. Bu da Build’inizin dengesiz olmasına sebep oluyor. Öte yandan Build’inizin güvenilir olması lazım, aynı versiyonu bin kere de çalıştırsanız aynı sonucu almalısınız.

Fakat gelin görün ki sonarın kendi bünyesinde kullandığı araçları (hatta daha fazlasını), maven üzerinden plug’in olarak kullanmanız mümkün. Örneğin:

Eklentilerini kullanmanız mümkün. Bunları genelde rapor üretmek için kullanıyorlar. Eğer böyle kullanırsanız, Sonar ile aynı kapıya çıkıyor. Fakat bunları build sırasında kontrol yapıp, build’inizi kırmak için de kullanabiliyorsunuz. Bu ayarların nasıl yapılacağına burada değinmeyeceğim. Yazının gereksiz uzayacağını düşünüyorum. Eğer örnek istiyorsanız, bu adresten CheckStyle, Findbugs ve Jacoco üçlüsünün bir arada nasıl ayarlanacağına bakabilirsiniz.

Grand-Parent-Pom

Eğer tek tek bu plugin’leri ayarlamak zor geliyorsa, Grand-Parent-Pom projesinden yararlanabilirsiniz.

Tek yapmanız gereken, parent-pom’unuzu Grand-Parent-Pom’dan türetmek.

Böylelikle tüm kontroller projenize otomatik olarak eklenmiş olacak. Detaylı bilgiye projenin github sayfasından erişebilirsiniz.

  • Mesut Özen

    pom.xml’i checkstyle conditionları şişirmek istemiyorsanız conditionları farklı bir xml’e alıp configLocation ile bu dosya parametre geçilebilir 🙂

    • bhdrkn

      Merhaba Mesut Bey;

      Çok haklısınız, böyle bir parametre var ve gayet başarılı bir şekilde çalışıyor. Benim bu parametreyi kullanmama sebebim, dosyayı dağıtamamam. GrandParentPom pom olarak dağıtılıyor. Bu durumda da mvn central a başka bir dosya yükleyemiyorsunuz.

      Her alt projenin kendi dosyasını sağlaması gerekiyor. Bundan dolayı bu parametreyi kullanmadı.

      Ama projenin ilgi görmesi çok güzel. Beğenmediğiniz ya da iyileştirmek istediğiniz yerler olursa pull request göndermekten çekinmeyin.

      İyi çalışmalar