Javascript ile Zircir Modeli – Chaining Pattern

Zincir modeli bir nesnenin metodlarını bir biri arkasına kullanabilmemize olanak tanır.


var myComponent = new Component().metdhodA().methodB(5).MethodC();

Yukarıda zincir halinde çağırmaya karşılık eğer bu methodlar bu işe uygun yazılmasaydı veyada bu şekilde kullanım tercih edilmeseydi normal kullanım aşağıdaki gibi olacaktır.


var myComponent = new Component();

myComponent.metdhodA();
myComponent.methodB(5);
myComponent.MethodC();

Zincir modeli başta JQuery olmak üzere özellikle DOM elemanlarının manipülasyonunda oldukça tercih edilmektedir.

Bunun ile birlikte kullanılmasının iyi yanları olduğu gibi handikaplarıda vardır. Olumlu taraflarından belkide ilk başta geleni kodun adeda bir cümle gibi okunup anlaşılır olmasını sağlamakdır. Bir başka olumlu tarafı ise zincir modelini kurarken kodunuzun metodlarını daha hedefe yönelik ve temiz tutma gereklilidir. Böylece bir method tek bir amaca hizmet eder halde kalacaktır. Elbette zincir methodu kod açısından daha az yer tutacaktır.

Handicap oluşturabilecek noktaları ise hata oluştuğunda, hata satırında yola çıkıp hangi methodda hata olduğunu bulmak güçleşebilir. Aslına bakarsanız bugünkü geliştirici araçların yön göstermesi ile bu o kadarda büyütülecek bir sorun olmaktan çıkmıştır.

Gelelim bu modeli nasıl uygulayacağız. Normalde constructor olarak kullandığınız bir fonksiyondan geriye bişey döndürmesseniz this otamatik olarak dönen değerdir. Bir fonksiyonu new ile çağırmak onun constructor görevi görmesini sağlar. Bunun yanında methodlardan geriye this dönerseniz devamına o nesneye ait diğer methodları zincir şeklide ekleyebilrisiniz. Şimdi zincir şeklinde kullanılmaya uygun bir sınıf oluşturalım ve kullanım örneği verelim..

var BlogText = function() {
    this.text= "";
};

BlogText.prototype = {
    setText: function (str) {
        this.text = str;
        return this;
    },
    capitaliseFirstLetter: function () {
        this.text = this.text.charAt(0).toUpperCase() + this.text.slice(1);
        return this;
    },
   allLowercase: function () {
        this.text = this.text.toLowerCase();
        return this;
    }
}

var blogText = new BlogText().setText("Programlama NOTLARI").allLowercase().capitaliseFirstLetter();
alert(blogText.text); // Programlama notlari

JSFiddle

Kodda görüldüğü üzere oldukça kolay uygulanabilen bir model ama kodunuzu daha elegan bir hale getiriyor ;)

Tagged with: , ,
JavaScript kategorisinde yayınlandı

Javascript’te Kendini Tanımlayan Fonksiyonlar (Self-Defining Functions)

Javascript dili bir fonksiyonu tekrar ve tekrar tanımlanmasına izin verir. Eğer aynı fonksiyon aynı kapsam alanı (scope) içinde birden fazla  tanımlanmışsa sonra gelen bir öncekinin tanımını iptal eder ve böylece en son deklere edilen o fonksiyonu nihayi olarak tanımlar. Bu özellik dikkat edilmez ise olası hatalara yol açabilceği gibi, faydalı kod modelleri oluşturmamızada olanak verir.

Global olarak tanımlanmış bir fonksiyon kod içinde herhangi bir yerde tekrar tanımlanabileceği gibi, kendi içinde de tekrar tanımlana bilir. Yani ilk çağırmada yaptığı işi tamamen revize ederek sonraki çağırmalarda fonksiyonuna farklı görevler biçebilirsiniz. Peki kendini tanımlıyan bir fonksiyonun kullanım alanı neler olabilir? Şöyle bir senaryo belirliyelim..

Sayfa içinde ajax kodu ile doldurmanız gereken bir ağaç yapısı olsun fakat bu ağaç yapısının birinci seviye elemanlar statik bir liste olup ana kategorileri oluştursun ve bu ilk sıra elemanların altına gelecek olan elemanlarda dinamik olarak bir ajax isteği ile gelsin. Ağaç (tree) komponenti kaynak olarak bir Javascript fonksiyonu verelim ve bu fonskiyonun ismi getChilds olarak belirleyelim ve parametre olarak altına eleman eklenmesi istenen nesnenin id’si (parentId) ve ekleme yapıcak callback fonksiyonunu alsın. Bu durumda hemen bir değişken tanımlayıp bu değişkene ilk istek aşamasında olduğumuzu belirten true atamsını yapabiliriz ve arkasından da her gelen istekte bu değişkenin değerini kontrol ederek işleme devam edebilriz. Bunu iki bakımdan tamsiye etmem. Atıyacağınız bu tip bayrak değişkenler global namespace’i kirletmeye başlıcaklardır ve de her seferinde gereksiz bir durum kontrolü yapmak zorunda kalacaksınız. Bunun yerine aşağıdaki gibi bir fonksiyon tanımlaması ile bu fonksiyonu çağıran tarafın başka bir değişkenle ilgilenmeden bu işi bitirmesini sağlayabilirsiniz.

var getChilds = function (parentId, callback) {
    
    callback([{name: 'Genel', id: 0}, {name: 'Özel', id: 1}]);

    // fonksiyon burada tekrar tanımlıyoruz
    getChilds = function (parentId, callback) {
        
        ajaxcall(parentId, 
                 // success
                 function(resultArray){
                    callback(resultArray);
                 });
    };
};

getChilds(1, addToTree);
getChilds(2, addToTree);

Kod içindeki ajaxcall sizin kullandığınız kütüphanye göre değişeçektir.

Buradaki kullanım işlemindeki gibi ilk çalıştırmada özel bir işlem gereği olan yerlerde bu modeli uygulayabilriz. Full çalışan bir kod örneği veremediğim için üzgünün fakat ana prensibi anlatmaya yettiğini düşünüyorum. Her türlü soru ve önerilerinizi bekliyorum.

Tagged with: , ,
JavaScript kategorisinde yayınlandı

Javascript ile Hatırlama Modeli – Güçlü hafıza düşünme kapasitenizi artırır.

Yüksek işlem gücü, hafıza kapasitesi ve erişim hızı ile birleşince, ister makine olsun ister insanlar arsında, çözümleme yapma ve sonuca ulaşmada üstün diyebileceğimiz sonuçlar ortaya çıkarmaktadır.  İyi ve performanslı yazılımlar ortaya çıkarmak için de bu iki kaynak tan dengeli bir biçimde faydalanmak gerekir. Özellikle Javascript ile istemci taraflı (client-side) kod geliştirmekte ne vakit hafıza kullanımından yardım almak gerektiği yüklü işlemler gerçekleştirirken düşünmek gerekiyor.

Bu yazıda performans artışına yönelik hatırlama modelini (Memoization Pattern) tanıtmaya çalışacağız. Aslında bu model çözüm olarak günlük hayatta pek çok defa karşımıza çıkmaktadır. Marketin manav bölümünde tartım işlemi yapan market çalışanı buna basit bir örnek olabilir. Bu çalışanın amacı önünde kuyruk oluşturmadan olabildiğince seri ve hatasız gelen müşterilerin tartımını yapıp fiyat etiketlendirme sini yapmaktır. Biz bu işi tartım ve etiketleme diye iki ayrı ardışık fonksiyon olarak düşünelim. Bu kısmı biraz sizi sıkma uğruna detaylı anlatacağım. Biz olayı dışarıdan gözlemleyelim. Mevcut çalışan oldukça seri hareket ediyor ve üçünü bir kişi kuyruğa girmeden önündeki müşteriyi gönderiyor. Bu sırada vardiya değişimi ile tartıdaki çalışanlar görev değişimi yapsın. Eğer yeni gelen kişi meyve ve sebzelerin kodlarına aşina değilse belli bir süre kuyrukta birikme olacaktır. Ama belli bir süre sonra hatırlama modelini (Memoization Pattern) devreye girecek ve sıra akışı eski performansını sağlayacaktır. Bu yaşanmış tecrübede tartım yapma süresi çalışanlar arasında değişmiyorsa hızdaki değişim etiketin çıkartılma süresi ile alakalıdır. Önceki vardiyadaki çalışan gireceği kodları artık listeye bakma hata reflex olarak yapıyor olabilir. Bunu yapabilmesi için kodları hafızaya almış olması gerekir. Yeni gelen ise belli bir süre sonra yeterli çeşitlilik ve sayı olmaya başlayınca onu yavaşlatan liste kontrolü işinden kurtularak hafızadan kodları alıp etiketlemede sürat kazanacaktır. Peki bu modeli biz niye programlama yaparken kullanmayalım?

Eğer yüklü bir işlem yapıyorsak, yaptığımız işlemin parametre sayısı olasılık olarak yüksek değilse, buna karşılık üretilen sonuçların boyutu küçükse yapmanız gereken her gelen istekte parametreleri ve sonucu hafızada tutmak bunun ardından sonraki gelen isteklerde ilk önce hafızada bu parametreler sorgulanmış olup olmadığına bakmak ve eğer kaydedilmiş bir cevap varsa hiç işlem yüküne girmeden sonucu hafızadan vermek. Bu uzun açıklamadan sonra şimdi elimizi koda bulaştırmanın vakti geldi.

var calculateFactorial = function (num) {
    // cache de ayni sayi için hesaplanmış sonuç var mı?
    if (!calculateFactorial.cache[num]) {

        // factorial hesaplanması        
        var result = 1;
        for (var i = 2; i <= num; i++) {
            result = result * i;
        }

        // sonucu cache atıyoruz
        calculateFactorial.cache[num] = result;

        return result;
    }

    // cacheden sonuçu dönüyoruz

    return calculateFactorial.cache[num];
};

// cache nesnesi
calculateFactorial.cache = {};

console.time && console.time("time1");
console.log(calculateFactorial(60));
console.time && console.timeEnd("time1"); // 8.092ms 

console.time && console.time("time2");
console.log(calculateFactorial(60));
console.time && console.timeEnd("time2"); //  0.250ms 

console.time && console.time("time3");
console.log(calculateFactorial(6));
console.time && console.timeEnd("time3"); // 0.206ms 

Koda buradan da ulaşabilirsiniz JSFiddle

Görüldüğü üzere faktöriyel 60′ı ikinci kez istediğimizde neredeyse faktöriyel 6′yı hesaplama süresi kadar ancak süre geçti. Bu işlemi 10 kez tekrarlandığını düşünün zaman olarak kazancımız sadece bu işlem başına 70 saniyenin üstünde olacaktır. Bu modelin anlatımında yukarıda kullandığımız kodda geçen cache objesinin fonksiyon üstünden kullanımı javascript’in aslında fonksiyon olarak deklere edilen şeylerin arka tarafta bir objeden başka bir şey olamaması sayesinde oluyor. Böylece global değişken tanımı yapmak zorunda kalmadan oldukça temiz bir şekilde ihtiyacımı olan cache desteğiniz sağlamış oluyoruz.

Her ne kadar uygulama kısmı kolay olan bir model olsa da genelleştirme yapmak işimizi daha kolaylaştıracaktır. Örnek olarak underscore.js kodundan bu modeli uygulayan “_.memoize” fonksiyonuna bakalım

// Memoize an expensive function by storing its results.
  _.memoize = function(func, hasher) {
    var memo = {};
    hasher || (hasher = _.identity);
    return function() {
      var key = hasher.apply(this, arguments);
      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
    };
  };

Burada memoize fonksiyonu ilk parametre olarak işlemi yapacak fonksiyonu ve opsiyonel olarak ta hesabı yapacak bir callback fonksiyonu verilebilmekte. Kullanım örneği;

// http://documentcloud.github.io/underscore/#memoize
var fibonacci = _.memoize(function(n) {
  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
});

Şimdilik noktayı burada koyuyoruz. Diğer yazılarımda performans için faydalı olabilecek diğer modelleri de incelemeye çalışacağım..

Tagged with: , , ,
.., JavaScript kategorisinde yayınlandı

Javascript Döngüleri(Loops) ve Performans İpuçları

Eğer web ile ilgili ön yüz programlaması yapıyorsanız bir yerinden Javascript ile işiniz oluyordur. Genelde sayfa içinde Javascript tercihi dinamizmin ve hız için tercih edilir. Bu faydalar birlikte sevimli ve heyecan verici duran bu teknolojinin eğer bilinmese ve dikkat edilmese hız yerine donma şikayetlerinin kaynağı haline gelebilir. Özetle performans ilk tasarım aşamasından sona mutlak üzerine eğilmeniz gereken bir olgudur.

Performans deyince ilk bakmamız gereken kod parçacıkları döngü içeren ve özellikler DOM elemanları ile uğraştığımız yerlerdir. Ve işte başlıyoruz..

Dizi boy bilgisini Saklayarak Kullanın (Array Length Caching)

Aşağıdaki inceleyeceğimiz kod örneklerinde sayfamızın içindeki tüm div elemanları arasında dönüyoruz.

// sayfada ki tüm div elementlerini alıyoruz
var divs = document.getElementsByTagName('div')

// loop 1
for(var i=0; i&lt;divs.length; i++){
  arr[i].innerHTML = i;
}

Bu örnekte en büyük performans hatası sınır şartını her bir döngüde tekrar istenmesidir. Bu ilk etapta şaşırtıcı gelebilir fakat kod her seferinde yani i değişkeninin her artırımı için tekrar boy bilgisini çekecektir ve eğer silme ekleme gibi işlemler gerçekleşiyorsa ‘length’ özelliği bundan etkilenecektir. Peki ne yapmak gerekir.

// sayfada ki tüm div elementlerini alıyoruz
var divs = document.getElementsByTagName('div')

// loop 1
var max = divs.length;
for(var i=0; i&lt;max; i++){
  arr[i].innerHTML = i;
}

Yukarıda olduğu gibi boy bilgisini bir değişkene atadığımız da her seferinde boy için diziye gidilmeyeceğinden emin oluruz. Bu durumda akla şu soru geliyor, pek çok kütüphanede Each, ForEach benzeri yapılarla dizi veya koleksiyonlar (collections)üzerinde dönülüyor. Bun kütüphanelerde bu performans iyileştirmesine dikkat ediyorlar mıdır. En çok kullanılan kütüphanelerin başında gelen JQuery kodunun ilgili kısmına bakalım.

each: function( obj, callback, args ) {
		var value,
			i = 0,
			length = obj.length,
			isArray = isArraylike( obj );
...
if ( isArray ) {
				for ( ; i &lt; length; i++ ) {
					value = callback.call( obj[ i ], i, obj[ i ] );

					if ( value === false ) {
						break;
					}
				}
			}

Evet JQuery each fonksiyonu boy bilgisini aynen bizim de yaptığımız gibi saklamış, burada fonksiyonun başında tüm değişkenleri tek bir var içinde atama yapmak da ayrıca tavsiye edebileceğim bir kod paternidir.

Ama eğer Jquery veya benzeri bir kütüphane kullanılmıyorsa alışkanlık olarak büyük küçük demeyip her döngüde bu şekilde kodlamak ta fayda var. Buradaki performans kazanımı tarayıcıdan tarayıcıya değişmekle birlikte özellikle eski tarayıcılarda çok ciddi boyutlara ulaşabilir.

Bununla birlikte döngüleri tersten işlemekte bir çözüm olabilir. Bu sizi ekstra değişken tanımlamasından da kurtarır. Tabi eğer işleme sırası sizin için önemli ise elbette ekstra efor harcayıp dizi ters çevirmeye değmez.

// sayfada ki tüm div elementlerini alıyoruz
var divs = document.getElementsByTagName('div')

// loop 2
for(var i=divs.length; i--){
  arr[i].innerHTML = i;
}

Görüldüğü üzere çok daha kısa bir kod bloğu oluşturduk. Daha önce kullanımını görmediyseniz bu şekil yazımda 0 kontrolü yapmanıza gerek yok. Kendisi 0′a gelince duracaktır. Ayrıca bir değeri sıfır ile kıyaslamak her zaman diğer sayılarla kıyaslamaktan daha hızlıdır. Burada — ve ya ++ şeklindeki kullanımlara da değinebiliriz. Eğer JSLint gibi bir kod kalite kontrol aracı kullanıyorsanız, sizi bu kullanımlar konusunda uyaracaktır. Bu kullanımlar yerine i+=1 veya i=i+1 de yeğlenebilir. Eğer bu derece kendinizi sıkmak istemiyorsanız jslint kurallarından jslint plusplus kuralını kaldırabilirsiniz.

Tagged with: ,
.., JavaScript kategorisinde yayınlandı

HTML 5 – WebStorage

Yeni bir projeye başlarken mimarinin belirlenmesi noktasındaki kilit soruların başında kullanıcı ara yüzünün masaüstü veya web uygulaması olması seçimidir. Bu noktada giderek artan eğilim web uygulaması yapmak yönünde olmaktadır. Geliştirme kolaylığı, bakım maliyetlerin düşük olması, farklı platformlara hitap edebilme gibi nedenler ile eğer yapılmak istenenler bir tarayıcının kabiliyetlerini aşmıyorsa tercih genelde web uygulaması yönündedir.

Web uygulamalarının masaüstü uygulama ile yarışabilir hale gelmesini sağlayan HTML 4 ile kullanılabilen AJAX, CSS, özeleşmiş Javascript kütüphaneleri gerçekten muazzam bir iş başarmış gibi gözüküyor. HTML’ in yetmediği yerlerde veya tercihan tercih edilmediği durumlarda da Flash eklentisi ve kısmi kullanımı ile Java Appletler ve diğer Active X nesneleri de oldukça başarılı işler çıkartmış durumda.

Fakat bu ek teknolojiler ile birlikte bile halen HTML 4 ün bir ayağı aksak durumdadır. Web için ürün geliştiricileri zorlayan noktaları ve Masaüstü uygulamalar ile aradaki kabiliyet farkını kapatmak için şimdi önümüzde heyecan verici yeni bir markup dili hızlı adımlarla yerini alma aşamasında.

Web’de işinizi aksatan büyük eksikliklerden biri istemci tarafta veri depolayabilmek. Bu noktada eldeki tek yaygın seçenek çerez (cookie) kullanımı. HTML 4 için çerez bilgileri her istek gönderiminde sunucuya iletilmektedir. Buda tutulacak bilginin artışını ile ilgili performans ve hat kullanımında artış getirmektedir. HTML 5 veri saklamak adına iki yeni obje tanıtmaktadır.

  • localStorage – zaman limiti olmadan veri saklamak için
  • sessionStorage – tek oturum için veri saklamaya yönelik

Sayfalarımıza localStorage ile sadece Javascript yazarak hiç sunucu taraflı kod yazmadan, kullanıcı için veri saklama ve gerektiğinde okuma kabiliyeti kazandırabiliriz. Bunun için ilk akla gelebilecek örnek uygulama GMail tarzı offline maillerinize okuyabilmek olabilir ve bu şekilde bir uygulamanın multi-browser destekli olması işi çok daha eğlenceli hale getirecektir.

 

Hâlihazırda kullandığınız tarayıcının HTML 5 desteğini görmek üzere bu linkten yararlanabilirsiniz http://html5test.com/

Tüm yenilikler için http://dev.w3.org/html5/html4-differences/

 

html, HTML 5 kategorisinde yayınlandı

JavaScript Debugging

jsbin.com http://jsbin.com/

http://jsbin.com/ Javascript ve kodunuzu yazıp test edebileceğiniz, popüler Javascript framework’lerini tek seçimle ekleyebileceğiniz oldukça akıllıca düşünülmüş bir site. Yazdığını kodun linkini başkasına gönderme veya saklamaya da imkan sağlıyor.

http://jsfiddle.net jsbin ile benzer özelliklere sahip fakat kendinize hesap oluşturmanıza imkan veren bir site.

html, JavaScript, Online Araçlar kategorisinde yayınlandı

XML Dosyasından XSD üretme

Visual Studio Tools içinde gelen XSD.exe ile komut satırından elinizdeki bir XML dosyası için XSD şeması elde edebilirsiniz. Komut istem penceresini programlar menüsündeki
(Start -> Visual Studio 2005/2008/2010 -> Visual Studio Tools -> Visual Studio Command Prompt) linkten başlatabilirsiniz.

XML dosyasından XSD şeması çıkarmak için aşağıdaki komutu kullanabilirsiniz. Bu şekilde kullanım aynı isimli bir XSD dosyası üretecektir.


xsd ornek.xml

Üretilen XSD dosyasından da .cs kaynak kodu üretebilirsiniz.


xsd ornek.xsd /classes

Elinizdeki kod dosyasını projenize katarsanız ürettiğiniz şemaya uygun XML dosyaları için Serialize/Deserialize işlemleri yapabilirsiniz. Buda sizi XML dosyası üretirken veya okurken taglarla uğraşmaktan bir basamak yukarı taşır ve pek çok olası hatadan kurtarır.

.NET Framework, XML kategorisinde yayınlandı

Enter your email address to follow this blog and receive notifications of new posts by email.

Diğer 12 takipçiye katılın

Arşiv
Takip Et

Her yeni yazı için posta kutunuza gönderim alın.