Tasarım Kalıplarının Kullanımı - Javascript ile Yazılım Geliştirmede İşinizi Kolaylaştıracak Araçlar (Bölüm 3)

js

Bu yazı, Tasarım Kalıpları dizinin 3. yazısıdır. Dizinin diğer yazılarına aşağıdaki içindekiler kısmından ulaşabilirsiniz.

İçindekiler

  1. Bölüm 1: Tasarım Kalıpları - Sorunlar ve İlkeler
  2. Bölüm 2: Tasarım Kalıpları Nedir?
  3. Bölüm 3: Tasarım Kalıplarının Kullanımı
  4. Bölüm 4: Tasarım Kalıplarını Uygulamak için Öneriler

Gerçek Hayatta Tasarım Kalıpları

1 - Modül Kalıbına Örnekler:

AMD (Asynchronous Module Pattern)

Türkçe adıyla Asenkron Modül Tanımı olarak require.js kütüphanesi ile geliştirme hayatımıza giren bu kalıp ile birbirine Dependency Injection yöntemi ile context’e dahil edilen modüller yaratabiliyor ve bunları istediğimiz sırada çalıştırabiliyoruz. Yazılım tasarımı itibariyle kolay ve yönetilebilir bir kod tabanı sağlaması, büyüyen kod bloklarını yönetmede ve onları çok küçük işlem bloklarına bölmemizde yardımcı olan bu tasarım kalıbı herhangi bir kütüphane ya da çatı ile de kolaylıkla entegre çalışabiliyor. Örnek kütüphane: requirejs.org

/**
 * productList.js
 * Bu dosyada ürünleri başka bir modülden çağırdığımız 
 * bir “getProducts” metodu ile çağırıyoruz.
 */

define(function (require) {
   var service = require('./service');
   var productsList = service.getProducts();
});
/**
 * service.js
 * Ürünleri API uç noktasından almamıza yarayacak 
 * metodu barındıran modül dosyası.
 */

defined(function () {
   return {
      getProducts : function (callback) {
         $.ajax({
            method : 'GET',
            url : 'localhost:8888/products',
            dataType : 'json',
            success : function (data) {
               if (callback) {
                  callback(data); 
               }
            }
         });
      }
   }
});
/**
 * app.js
 * Modülleri çağırıp çalıştırdığımız dosyamız.
 */

var service = requirejs(['app/service']);
var products;

service.getProducts(function (products) {
   products = products;
});

CommonJS

Senkron modül tanımlama kalıbı olarak da biliniyor. Hatta Node.js’in artık resmileşmiş diyebileceğimiz modül tanımlama yöntemi olduğunu söyleyebiliriz. Buna göre istediğimiz metodları ya da değişken / sabitleri barındıran dosyaları çağırabilmemiz bu yöntem ile mümkün. Sunucu tarafında built-in geliyor olmasının yanısıra, istemci-taraflı geliştirmelerimizde browserify’ı kullanabiliriz.

/**
 * user.js
 * Kullanıcının genel işlemlerinin yürütüldüğü dosya.
 */

var auth = require('./utility/auth.js');
module.exports = {
   getClientId : function () {
      return auth.getClientId();
   }
};

/** * app.js * Uygulama çalışırken gerçeklenecek metodların barındırıldığı dosya. */ var user = require('./user'); module.exports = function () { auth.setCookie('clientId', user.getClientId()); }
/**
 * init.js
 * Bütün bir app.js’te istenen metodları çalıştıran dosya.
 */

var init = require('./app');

init();

ES6 (Harmony) Modülleri

Yeni standartlaşan ve yavaş yavaş modern tarayıcılara entegre edilecek olan ECMAScript 6’nın modül yapısı oldukça sade ve kullanışlı.

/**
 * fibonacci.js
 * Fibonacci işlemini yaptığımız dosya.
 */

export fibonacci (num) {
   if (n <= 1)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}
/**
 * calculate.js
 * İşlemi gerçekleştireceğimiz dosya.
 */

import {fibo} from ‘fibonacci’;

console.log(fibo(4) + fibo(3));
console.log((fibo(3) + fibo(2)) + (fibo(2) + fibo(1)));

Javascript’te Namespacing Kalıpları

Javascript geliştirirken hepimizin aşina olduğu ancak bir süre sonra context set / get etme noktasında sıkıntı yaşama ihtimalimizin olduğu object literal notation tarzında çokça kullandığımız namespacing için belli başlı örneklerimiz mevcut. Bunların üzerinden de hızlıca geçersek zannedersem bazı noktalarda aslında bunların birçoğunu geliştirme günlüğümüzde zaten farkında olmadan yer aldığını farkedeceğizdir.

Single-global Variables var testModule = (function () {})();
Prefix Namespacing var testNS_someFunctionality = {}, var testNS_someOtherFunctionality = {}
Object-literal Notation Bkz. Module Revealing kalıbı.
Nested Namespacing testModule.some = testModule.some || {};
Immediately-Invoked Function Expressions aka. IIFE / iffy (function () {})();
Namespace Injection (function () {}).apply(ns.someMethod);
Automating Nested Namespacing moduleA.moduleB.moduleC.moduleD
Dependency Decleration var someFunction = moduleA.moduleB.moduleC.moduleD.someFunction
Deep Object Extension extend(destination, source)

Bütün bu kalıpların gün içerisinde birçok başka biçimde kullanımı olmasının yanısıra aslında bazılarını başka kütüphanelerden devşirerek ya da bizzat kullanarak gerçekliyoruz. Bunun bir örneği de Javascript’in istemci-taraflı DOM-manipülasyon kütüphanesi jQuery. Birçok kullanışlı aracı içerisinde barındıran jQuery elbette ki belli tasarım kalıplarını da kullanmıyor değil. Gözattığımızda şöyle bir tablo ile karşılaşıyoruz:

jQuery Kütüpnasinde Kullanılan Bazı Tasarım Kalıpları

Composite

Bir selector yazarken bir class ile tanımlama yapabiliyorken bir element ile tanımlama da yapabilmemizi sağlıyor.

var paragraphsWithClassProductName = $('.productName');
var paragraphs = $('p'); 

Facade

Gerçek API ile araya bir soyutlandırma katmanının koyulduğu kalıp.

$.ajax({
   url : '...',
   method : 'GET',
   dataType : 'json'
});

aslında XMLHTTPRequest nesnesini kullanarak yaratılmış bir metoda referans verip onu çalıştırıyor. Böylece kullanım kolaylığı sağlanıyor.

Observer

Publish / Subscribe pattern’ını andıran bu kalıpta belli olaylara beklenen veri yapıları karşılanıp kullanılıyor.

document.on('customEvent', function (data) {
   $('p').html(data.customized);
});

$(document).trigger('customEvent', {customized : 'This is some data...'});

Lazy Initialization

Belli bir işlem sırası sonrasında gerçekleşen bir yaklaşımı temsil ediyor ve aşağıdaki blok aslında DOMContentLoaded event’i tetiklendikten sonra çalışıyor.

$(document).ready(function () {
   ...
}); 

Builder

Dinamik olarak yeni element referansları ve o referanslardan da yeni elementler yaratmamızı sağlaya bir tasarım kalıbı olarak jQuery kütüphanesinde kullanılıyor.

var p = $('</p>').text('New paragraph');

Plugin patterns

jQuery plugin’leri yazarken tercih edeceğimiz tasarım kalıpları. Bu kalıbın kullanımı ile alakalı detaylı anlatımı "jQuery Plugin Anatomisi" yazımızda bulabilirsiniz.

(function ($) { 
   $.fn.somePlugin = function (options) {
      ...
      return this;
   }
})(jQuery);