js-aop

JavaScript ile Aspect-Oriented Programlama

Yazılım dediğin kaya gibi sağlam olmalı!.  Erm  siz Türkler nasıl diyoğ “S.O.L.I.D”  olmalı.  Bütünün sağlam olması içinse, küçük parçaların sağlam olması gerekir. Bunun için bu ufak parçalar Tek işten sorumlu olmalı (Single Responsibility principle) Geliştirmeye açık, değiştirmeye kapalı olmalı (Open-closed principle) Türetilen sınıflardaki API davranışı değişmemeli (Liskov substitution principle) Her ayrı konulu iş için ayrı […]

Yazılım dediğin kaya gibi sağlam olmalı!.  Erm  siz Türkler nasıl diyoğ “S.O.L.I.D”  olmalı.  Bütünün sağlam olması içinse, küçük parçaların sağlam olması gerekir. Bunun için bu ufak parçalar

  • Tek işten sorumlu olmalı (Single Responsibility principle)
  • Geliştirmeye açık, değiştirmeye kapalı olmalı (Open-closed principle)
  • Türetilen sınıflardaki API davranışı değişmemeli (Liskov substitution principle)
  • Her ayrı konulu iş için ayrı interface’ler sunmalı (Interface segregation)
  • Somut sınıflar yerine, daha soyutlaştırılmış sınıflardan oluşmalı, bu sayede bağımlılıkları azaltılmış olmalı (Dependency inversion principle)

Aspect-oriented (İlgiye yönelik) programlama ise, çok kullanılan bazı durumlarda (loglama, performans ölçümü, yetki kontrolü), S.O.L.I.D’in “S” sinin “suistimal” edilmesini önlemek için ortaya çıkmıştır.

Örnek vermek gerekirse,  bir methodumuz var, yapması gereken iş basit : “gelen metni AJAX ile bir yere göndermek”.

Bunun için yazdığımız methodun JavaScript syntax’li pseudo kodu aşağıda;

...
var sendText = function (text) {
    //ajax ile save.php'ye gönderiyor
    $.ajax("save.php", {textToSave : text});
}
...
sendText('JavaScript çok güzel');

Ama gerçek dünyada her zaman bu iş bu kadar basit olmuyor. Gün geliyor “oraya gelen text’i bir loglayalım” veya “bu işlemi sadece adminler yapabilsin” gibi bir istek geliyor. Ve kodumuz şuna dönüşmeye başlıyor.

...
var sendText = function (text) {
   console.log(text); //hm, bu methodun işi bu değil ki?
   if(loggedUser.auth == "admin") { //admin kontrolü de bunun işi değil gibi sanki?
       $.ajax("save.php", {textToSave : text});
   }
   else {
       alert('Yetkiniz yok!');
   }
}
...
sendText('JavaScript çok güzel');

Amanın! Methodumuzun adına bakın ve bir de yaptığı işlere bakın! Kodumuzun sağlamlığı tehlikeye girmeye başladı. İşte tam bu noktada aspect-oriented programlama yardımımıza koşuyor.
Bir çok dilde native olarak veya harici bir çok AOP framework’ü bulabilirsiniz. Bu yazı, JavaScript’te bu işin “basitçe” nasıl yapıldığını anlatmaya çalışacak.

JavaScript, runtime’da methodların implementasyonlarına erişme ve bunları manipüle edebilme (reflection) yeteneğine sahiptir. Peki bunu nasıl yapacağız?

Bizim esas kodumuz ilk örnekteki şu kod olmalı.

...
var sendText = function (text) {
    //ajax ile save.php'ye gönderiyor
    $.ajax("save.php", {textToSave : text});
}
...

sendText('JavaScript çok güzel');

Bu koda dokunmadan, hem loglama hem da yetki kontrolü yapmak istiyoruz. Büyülü sözleri söyleyip, klavyeye dokunmaya başlıyoruz…

...
var sendText = function (text) {
    //ajax ile save.php'ye gönderiyor
    $.ajax("save.php", {textToSave : text});
}
...

//kara büyü burada yapılıyor, yukarıdaki kodu hiç değiştirmeden bu
//kodları ekleyebiliyoruz, üstelik istersek bu kodları farklı
//bi dosyaya koyabilir, sadece bu dosya varsa böyle
//kontrollerin yapılmasını sağlayabiliriz
//bu şekilde aynı zamanda "yetki kontrolünü" tek bir yerden yönetebiliriz
var sendTextAOP = sendText;

sendText = function (text) {
    console.log(text);
    if (user.auth == "admin") {
        sendTextAOP(text);
    }
    else {
        alert('yetkiniz yok');
    }
};

...

sendText('JavaScript çok güzel');

Vay, çok güzel değil mi?  Esas olay, sendTextAOP (isim herhangi bir şey olabilir) gibi bir temporary değişkene, üstte tanımladığımız esas methodu eşitlemek. Daha sonra ise sendText methoduna loglama ve yetki kontrolü ekliyor ve diğer işlemleri, gerçek methodun yapmasını sağlıyoruz.

Bu sayede, loglama, yetki kontrolü gibi genel işlemleri, orijinal methodun içeriğini değiştirmeden yapabiliyoruz.

Diğer dillerde/frameworklerde “joinpoint”, “crosscutting” gibi kavramlar duyup, bunları JavaScript’te arayanlar için de JavaScript ile yazılmış çeşitli frameworkler bulunduğunu belirtir, bu yazıma böylece son veririm :)