Press "Enter" to skip to content

Effective Java Madde 59: Kütüphaneleri Öğrenin ve Kullanın

Diyelim ki 0 ile belli bir üst sınır değeri arasında rastgele sayılar üretmek istiyorsunuz. Birçok programcı bu işi yapmak için aşağıdaki gibi bir kod yazabilir:

 // Oldukça yaygın ama bozuk!!
static Random rnd = new Random();
static int random(int n) {
    return Math.abs(rnd.nextInt()) % n;
}

Bu metot doğru gibi görünse de oldukça hatalıdır. Seçtiğiniz n değerine bağlı olarak bazı sayıların diğerlerine kıyasla daha sık üretilmesi söz konusudur. Aşağıdaki kod önce dikkatlice seçilmiş bir aralıkta bir milyon tane rastgele sayı üretmekte, daha sonra da bu aralığın birince yarısı içinde kaç tane sayı üretildiğini yazdırmaktadır.

public static void main(String[] args) { 
    int n = 2 * (Integer.MAX_VALUE / 3); 
    int low = 0;
    for (int i = 0; i < 1000000; i++) {
        if (random(n) < n/2) {
            low++;
        }
    }
    System.out.println(low); 
}

Eğer random metodu düzgün çalışsaydı, bu programı çalıştırdığınızda yarım milyona yakın bir sayı yazdırması gerekirdi ancak 666,666’a yakın bir sayı yazdıracaktır. Yani random metodunun ürettiği sayıların üçte ikisi seçtiğimiz aralığın ilk yarısında, sadece üçte biri aralığın ikinci yarısında olmaktadır.

Bu random metodunun başka bir problemi de belli şartlar oluştuğunda tamamen çuvallaması ve seçtiğimiz aralığın dışında bir sayı döndürmesidir. Bunun sebebi de Math.abs metodunu kullanarak rnd.nextInt() tarafından üretilen negatif sayıları pozitife dönüştürmeye çalışmasıdır. Ancak nextInt() çağrısı Integer.MIN_VALUE döndürürse, Math.abs metodu da Integer.MIN_VALUE döndürecek ve eğer n değeri ikinin bir kuvveti değilse sonuçta negatif sayı üretilecektir. Bu hata büyük ihtimalle programınızın çökmesine sebep olacak ve hatanın neden kaynaklandığını anlamak çok zor olacaktır.

Bu hataları çözen ve daha doğru çalışan bir random metodu yazabilmek için ciddi matematik bilgisi gerekmektedir. Neyse ki buna gerek yok, çünkü yazılmışı var: Random.nextInt(int) Bu konulara oldukça hakim uzman bir mühendis, bu metodu tasarlamak, yazmak ve test etmek için büyük çaba ve zaman harcadı. Üstüne başka uzmanlara da danışarak metodun doğruluğunu teyit ettirdi. Daha sonra bu kütüphane defalarca test edildi, yayınlandı ve neredeyse yirmi yıldır milyonlarca yazılımcı tarafından kullanıldı. Bugüne kadar bir hata bulunamadı, ancak bulunursa da bir sonraki versiyonda çözüleceğini biliyoruz. Standart bir kütüphane kullandığınızda, bunu yazan uzmanların bilgisinden ve daha önce kullanan yazılımcıların tecrübelerinden istifade etmiş olursunuz.

Java 7’den itibaren artıkRandom kullanmamalısınız. Rastgele sayı üretmek için çoğu durumda ThreadLocalRandom tercih edilmelidir. Çünkü hem bu işi daha iyi yapmaktadır hem de daha hızlı çalışmaktadır. Benim makinamda ThreadLocalRandom, Random‘a kıyasla 3,6 kat daha hızlı çalışmaktadır. Fork-join havuzları ve paralel streamler içinse SplittableRandom kullanmalısınız.

Standart kütüphaneleri kullanmanın ikinci bir avantajı da, uygulama koduna odaklanmanıza olanak sağlamasıdır. Bu şekilde standart işleri halletmek için yeniden kod yazmanıza gerek kalmaz, zamanınızı ve enerjinizi sizi asıl ilgilendiren uygulamanın kritik parçalarına ayırabilirsiniz.

Standart kütüphaneleri kullanmanın üçüncü avantajı ise zaman geçtikçe performans iyileştirmeleri yapılmasıdır. Bunları kullanan çok sayıda kişi ve kuruluş olduğu için ve sık sık performans testlerinden geçirilir ve gerekirse yeniden yazılırlar. Java kütüphanelerinin bir çoğu zaman içerisinde defalarca yeniden yazılmış ve ciddi performans kazanımları elde edilmiştir. Bunları kullanan programcılar çaba sarf etmeden bu iyileştirmelerden faydalanabilirler.

Dördüncü bir avantaj ise bu kütüphanelere zaman içerisinde yeni özellikler eklenmesidir. Bir eksik bulunduğunda yazılımcı toplulukları bunu rapor ederler ve bir sonraki versiyonda bu eksiklik giderilebilir.

Son olarak, standard kütüphaneler kullandığınızda kodunuz daha çok yazılımcı tarafından kolayca anlaşılabilecek ve bakım yapılması kolaylaşacaktır.

Bütün bu avantajlar söz konusu iken, yeniden kod yazmaktansa standart kütüphaneleri kullanmanın daha mantıklı olacağı açıktır, ancak yine de birçok yazılımcı bunu yapmaz. Neden? Çünkü bu kütüphanelerin varlığından habersizler. Birçok özellik her yeni versiyonda bu kütüphanelere eklenmektedir, bu sebeple bunları takip etmek ve yeniliklerden haberdar olmak işinize yarayacaktır. Java platformunun yeni versiyonları çıktığında, yeni eklenen özellikler bir web sayfasında yayınlanır. Bunları takip etmek son derece önemlidir. Buna bir örnek vermek gerekirse, diyelim ki komut satırından aldığınız bir URL’in içeriğini ekrana bastıran bir program yazmak istiyoruz (Linux’daki curl komutunun yaptığı iş diyebiliriz). Java 9’dan önce bu kodu yazmak biraz uzun ve zahmetliydi, ancak Java 9’da InputStream‘e eklenen transferTo metodu sayesinde çok kolaylaştı. Bu işi tam olarak yapan programın kodu aşağıdaki gibi olacaktır:

// URL içeriğini transferTo kullanarak yazdırır
public static void main(String[] args) throws IOException { 
    try (InputStream in = new URL(args[0]).openStream()) {
        in.transferTo(System.out); 
    }
}

Büyüklükleri nedeniyle bütün standart kütüphanelerinin dokümantasyonunu okuyup anlayabilmek çok mümkün olmasa da, her programcı en azından java.lang, java.util, java.io, ve bunların alt paketlerine aşina olmalıdır. Diğer kütüphaneleri ise ihtiyaç duydukça öğrenip kullanabilirsiniz.

Bazı kütüphanelerden özellikle bahsetmemizde fayda var. Örneğin her yazılımcının collections ve streams kütüphanelerini (Madde 45-48), ayrıca java.util.concurrent paketinin belli bölümlerini bilmesi gerekmektedir. Bu paket hem üst düzeyde paralel programlayı kolaylaştıran yardımcı kodlar sunmakta, hem de daha uzman kişiler için alt düzeyde kodlar yazmayı mümkün kılmaktadır. Madde 80 ve 81’de, üst düzeyde kullanım kolaylığı sunan bazı bölümler incelenmektedir.

Bazen, bir kütüphanenin ihtiyacınızı karşılamadığı durumlarla karşılaşabilirsiniz. İhtiyacınız özelleştikçe bunu yaşama ihtimaliniz de artacaktır. En nihayetinde bu kütüphaneler da sınırlı sayıda özelliği desteklemek zorundadır. Standart kütüphanelerin ihtiyacınızı karşılamadığı durumlarda alternatiflere yönelebilirsiniz. Java kütüphanelerinin yeterli olmadığı durumlarda, yüksek kaliteli üçüncü parti kütüphaneleri tercih edin. Bunlara iyi bir örnek Google’ın açık kaynaklı Guava kütüphanesidir. Eğer alternatifler içerisinde de aradığınızı bulamazsanız, kendiniz yazmak zorunda kalabilirsiniz.

Özetle, tekerleği yeniden icat etmeyin! İhtiyacınız olan şeyin başka yazılımcılar tarafından da yaygın olarak kullanılabileceğini düşünüyorsanız, büyük ihtimalle bir kütüphane bunu sağlıyor olacaktır. İhtiyacınızı gideren bildiğiniz bir kütüphane varsa kullanın, yoksa da araştırıp bulmaya çalışın. Genel olarak konuşmak gerekirse, bu kütüphanelerde bulacağınız kod sizin kendi yazacağınız koddan daha iyi olacaktır ve zamanla daha da gelişecektir. Bu sizin yazılımcı olarak yeteneklerinizi küçümsemek anlamına asla gelmez. Kütüphane kodları sizin tek başınıza verebileceğinizden çok daha fazla ilgi ve özenle yazıldığı için, daha kaliteli olması son derece doğaldır.

Share

2 Comments

  1. Musa
    Musa May 11, 2022

    Devamı gelicekmi hocam bittimi kitap yoksa

    • seckintozlu
      seckintozlu May 11, 2022

      Kitabin devami var ama bitirmeye firsatim olmadi, ilerleyen zamanlarda devam etmek istiyorum

Leave a Reply

%d bloggers like this: