NodeJS Adım 5 – Modüler Programlama

Adım Adım Nodejs yazı dizimizin bir önceki bölümünde asenkron programlamadan ve callback fonksiyonundan bahsettik. Bu bölümde de Modüler Programlama ile devam edeceğiz.

Program yazarken kodlarımız bazen 10 bazen 100 bazen 1000 bazen binlerce satıra ulaşabilir. Büyüdükçe de yönetimi zor içinden çıkılmaz bir hale gelir. Ve zaman zaman aynı kodları sürekli sürekli yazarız. Bunu önlemek için sürekli sürekli yazdığımız kodları fonksiyonlara taşırız. Ama kodlarımız çok olduğunda buda yetersiz gelir. Tekrarlayan fonksiyonlar ortaya çıkabilir. Bu seferde fonksiyonlar çok fazla olur ve onlar yönetilemez, içinden çıkılamaz bir hale gelir. Bunu önlemek içinde aynı amaca hizmet eden fonksiyonları ayrı ayrı dosyalarda birleştiririz. Örneğin I/O işlemeleri için yazılmış fonksiyonları bir dosyada toplayabiliriz. Çoğu zaman yeterli olsa da programlarımız büyümeye devam ettikçe dosyalarında yönetimi zorlaşabilir. Yüzlerce dosyayı gruplandırıp yönetmek kolay olmayabilir. Bu sorunu da çözmek için belirli amaca hizmet eden dosyalardan oluşan dosya grupları oluştururuz.

Yazdığımız kodları yönetilebilir hale getirmek, kod karmaşasını ortadan kaldırmak ve tekrar kullanılabilir kodlar oluşturmak için mantıksal olarak aynı işleri yapan kod veya dosyaların bir araya getirilerek oluşturulduğu, tek başına çalışamayan ana programlar tarafından kullanılarak çalıştırılan program parçalarına modül(yada kütüphane yada paket) denir. nodejs üzerinde kullanılan bir çok modül bulunmaktadır. Bunlardan bazıları nodejs çalışırken otomatik yüklenir(daha önce kullandığımız process gibi) bazılarını da kodlama sırasında kodlar yardımı ile biz yükleriz(daha önce kullandığımız fs modülü gibi).

Modülün ne olduğunu öğrendiğimize göre artık kendi modüllerimizi nasıl yazacağımıza bakalım. Bu bölümün ilk örneğinde ayrı bir dosyaya kendi modülümüzü yazıp ana dosyamız içerisinde onu nasıl kullanabileceğimize bakacağız. İlk olarak modülümüzü yazalım ve modul1.js isimli bir dosyaya kaydedelim. Kodlarımız şu şekilde :

 

var fs = require('fs');

module.exports = function (dosyaAdi, callback) {
    var dosyaIcerigi = fs.readFile(dosyaAdi, function (hata, data) {
        if (hata) {
            return callback(hata);
        }
        callback(null, data.toString());
    })
}

Basit bir modül yazdık. Bu modülde modüle yollanan dosya ismine göre dosya okuyup içeriğini geri gönderiyoruz. Adım adım bakacak olursak ilk satırda fs modülünü çağırdık. Daha sonra module.exports = function(…) … kodları ile dosyamızı bir modüle çevirmiş olduk. Bu kodlar sayesinde bu dosyayı çağıran her program yazmış olduğumuz modülü bir fonksiyon olarak kullanabilecek. Modül fonksiyonunun içeriğine bakacak olursak parametre olarak iki değer alıyor. Birincisi dosyaAdi adında bir değişken. Bu değişkene modülü kullanan program bir dosya adı yollayacak. Bizde bunu fonksiyon içerisinde kullanacağız. İkinci olarakta callback adında bir değişken alıyor. Evet gelelim en önemli noktalardan birisine. Modüller doğası gereği asenkron çalışırlar. Asenkron çalışan her fonksiyonun bir callback fonksiyonu olacak ki işi ne zaman bitmişse bilelim ve yollamış olduğumuz callback çalışsın. Bizim modülümüzde asenkron ve bizde işimiz bittiğinde bunu kullanıcıya bildirmeliyiz. Bunun içinde bize bir calllback yollanmalı ve bunu program sonunda çalıştırmalıyız. callback değişkeni bunun için var.

Fonksiyonumuz içerisinde fs modülü içerisindeki readFile fonksiyonu ile bize yollanan dosyaAdi değişkeni içerisindeki dosyayı okuyoruz. readFile’ın callback fonksiyonu içerisinde ilk olarak hata kontrolü yapıyoruz. eğer hata varsa bize yollanan callback değişkeninin ilk parametresine veriyoruz ve geri dönderiyoruz. Burası biraz garip gelebilir. Evet callback bir değişken ama sonuçta bize bir fonksiyon yollanacak. Yani callback türü fonksiyon olan bir değişken. Bu yüzden biz onu fonksiyon olarak kullanabiliriz. Devam edelim. Eğer hata yoksa kodlarımız devam edecek. Bir sonraki satırda callback değişkeninin ilk parametresine null, ikinci parametresine okumuş olduğumuz dosyanın içeriğini stringe çevirip veriyoruz. callback fonksiyonunun ilk parametresine null yani boş değer yolladık. Çünkü ilk parametre hata için kullanıldı. Biz yine de ilk parametreye yollayabilirdik. Hata oluşmazdı. Ama kullanıcı ilk parametreden gelen değerin hata mı yoksa dosya içeriğimi olduğunu anlayamazdı. Bazı şeyler biraz havada kalmış olabilir ama modülümüzü kullanırken her şey daha da netleşecek. Gelelim modülümüzü kullanmaya. program.js dosyasındaki kodlarımız şu şekilde:

 

var m1=require('./modul1');

m1(process.argv[2],function (hata,data) {
    if (hata) {
        console.log("Bir hata oluştu.");
        return;
    }
    console.log(data);
});


5-1-node-module

İlk satırda yazmış olduğumuz modülü çağırıp m1 değişkenine atadık. Bizim modülümüz tek bir fonksiyondan oluşuyor. Dolayısıyla m1 değişkeninin türü aslında bir fonksiyon. Yani biz m1 değişkenini bir fonksiyon gibi kullanacağız. Kodlarımıza devam edelim. Modülümüzün ilk değişkeni okuyacağımız dosyanın ismiydi. Biz dosya ismini konsoldan parametre olarak alacağız. Almış olduğumuz bu parametreyi de m1 değişkenine yani modülümüzün ilk parametresine vereceğiz. İkinci parametre olarakta bir fonksiyon yazıyoruz. Bu fonksiyon bizim modülümüzdeki callback değişkenine denk geliyor. Yani modülümüzün işi bittiğinde yada hata olduğunda bu fonksiyon çalışacak. (Modülümüzü hatırlayın.). Bu fonksiyonda ilk olarak hata kontolü yaptık. Daha sonra gelen data değişkenini console ekranına yazdırdık. Evet kodlarımız bu kadar. Daha iyi anlaşılması için modul1.js dosyasını ve program.js dosyalarını yan yana koyarak inceleyebilirsiniz. Tabi şu noktada çok önemli. Bizim modülümüzün ne işe yaradığı, yada callback fonksiyonunun yapısının nasıl olduğu gibi bilgileri bizden başka kimse bilemez. Bunun için her hazırladığımız modülün bir dokümantasyonu olmalı. Ki modülü kullanacaklar bilsin. Sadece biz kullanacak olsak bile aradan zaman geçince unutabiliriz.

Peki fs modülünde olduğu gibi içerisinde birden fazla fonksiyon olan bir modülü nasıl hazırlarız. İkinci örneğimizde Matematik adında bir modül yapacağız. Modülümüzün 4 tane fonksiyonu olacak : Topla, Çıkar, Çarp, Böl. Matematik.js dosyası şu şekilde:

 

var Mat = function () { };

Mat.prototype.Topla = function (a, b) {
    return Number(a) + Number(b);
}

Mat.prototype.Cikar = function (a, b) {
    return Number(a) - Number(b);
}

Mat.prototype.Carp = function (a, b) {
    return Number(a) * Number(b);
}

Mat.prototype.Bol = function (a, b) {
    return Number(a) / Number(b);
}

module.exports = new Mat();

Kodlarımıza bakacak olursak Mat adında bir javascript sınıfı oluşturduk. Bu nesneye Topla, Cikar, Carp, Bol adında 4 tane fonksiyon oluşturduk. Fonksiyon içerikleri basit. Tek dikkat edilecek nokta Number() kullanımı. Bunu fonksiyonu kullanma sebebimiz fonksiyona yollanan parametreleri sayıya çevirmek. Aksi halde javascript hata vermez ama işlem sonucu yanlış olur. En son satırda da oluşturmuş olduğumuz Mat sınıfının bir nesnesini modül olarak atadık. Gelelim modülümüzü kullanmaya. program.js kodları şu şekilde:

 

var m1 = require('./Matematik');

var t1 = m1.Topla(process.argv[2], process.argv[3]);

var t2 = m1.Cikar(t1, process.argv[4]);

var t3 = m1.Carp(t2, process.argv[5]);

var t4 = m1.Bol(t3, process.argv[6]);

console.log(t1, t2, t3, t4);

5-2-node-module

İlk satırda Matematik modülümüzü çağırdık. Daha sonraki 4 satırda konsoldan aldığımız parametreleri kullanarak 4 işlem yaptık. Her birinin sonucunu değişkenlere atadık. En son satırda da bu sonuçların tamamını konsol ekranına yazdırdık. Kodlarımız bu kadar. Dikkat ettiyseniz modülümüz içerisindeki fonksiyonlar asenkron değiller. Biz kodlarımız içerisinde herhangi bir asenkron işlem yapmadığımız için kodlarımızda asenkron olmadı. Önceki örnekte modülümüz içerisinde asenkron bir fonksiyon kullanmıştık. Bu nedenle modülümüz asenkron olmuştu.  

Evet, bu bölümde  modül oluşturmayı ve oluşturmuş olduğumuz modülleri kullanmayı gördük. Aslında 5 farklı modül oluşturma yöntemi var. Biz burada ikisini gördük. Bunlar işimizi rahatlıkla görecektir.

Bir sonraki bölümde bu modülleri daha etkili bir şekilde nasıl kullanabileceğimize bakacağız.

Makalede kullanılan kodlara buradan ulaşabilirsiniz.


Bloga e-posta ile abone ol

Bu bloga abone olmak ve e-posta ile bildirimler almak için e-posta adresinizi girin.