Tasarım Örüntüleri (Design Patterns)

Bir uygulama geliştirirken sistemin tasarımıyla ilgili sorunlarla birden çok defa karşılaşabiliriz. Karşılaştığımız problemi çözmek fazlaca zamanımızı alabilir. Burada kodu yazan programcının daha önceki tecrübelerinden yararlanması gerekir. Bahsettiğim problemler algoritmik bir düşünceden değil, tamamen kodun genel tasarımından kaynaklanan problemlerdir.

Tasarım örüntüleri, nesneye yönelik dizayn problemlerinin çözülmesi için tasarlanmış ve programlama dilinden bağımsız stratejilerdir. Bu stratejilerden her biri bir tasarım problemini çözmek için geliştirilmiştir. Türkçesi tasarım örüntüleri olan “Design Patterns”, 4 tane tecrübeli programcı tarafından kitap haline getirilmiş ve 1994 yılında piyasaya sürülmüştür. Sun tarafından Gang of Four (GoF) örüntüleri olarak adlandırılan bu dörtlünün kitabında 23 tane tasarım şablonundan bahsedilmektedir. Aslında yüzlerce tasarım örüntüsü vardır. Hatta bu güne kadar isimlerini bilmeseniz bile yazdığınız uygulamalarda mutlaka en az birini kullanmışsınızdır.

Tek bir problemi çözmek için tek bir örüntü kullanılır. Ancak çoğu zaman programcı bir sistemde birden fazla sorunla karşılaşır. Bu yüzden tüm sistemde birden fazla tasarım örüntüsü kullanılabilir. Çok fazla örüntü kullanmanın ilk bakışta sistemi çok karmaşıklaştırdığı düşünülse de, iyi belirlenerek kullanılmış tasarımları olan bir sistem, hiç tasarım örüntüsü kullanılmamış karmaşık bir sisteme tercih edilir.

Tasarım örüntüleri tekrar tekrar kullanılabildikleri için vaktimizi daha iyi değerlendirmemizi sağlar. Ayrıca tüm dünya tarafından kabul görerek çoğu programcı tarafından kullanıldıklarından dolayı başka programcıların tasarımı anlaması çok daha kolay olur.

Programcılığa yeni başlayan bir yazılımcıysanız size tavsiyem GoF’un 23 örüntüsünden en az birkaç tanesini bilmeniz. Yıllardır yazılımla uğraşan, nesneye yönelik kavramlarla ilgili tecrübeli olduğunu söyleyen fakat tasarım örüntülerinden haberi olmayan birçok programcı var. Sonuçta tasarım örüntüleri ile ilgili internette yüzlerce kaynak bulabilirsiniz. Ben de zamanım oldukça tek tek anlatmaya çalışacağım. Bu yazım sadece giriş niteliğinde olacak.

Tasarım örüntülerini üç ana başlıkta toplayabiliriz.

–          Yaratımsal Örüntüler (Creational Patterns) : Yaratımsal örüntüler nesneleri direk bizim yaratmamızdansa bizim için yaratan yapılardır. Bu sayede programlarımız daha esnek bir hal alarak belli bir durumda nesne yaratılmasına karar verebilir.

  • Abstract Factory
  • Builder
  • Factory Method
  • Prototype
  • Singleton

–          Yapısal Örüntüler (Structural Patterns) : Yapısal örüntüler sınıf-nesne arasındaki bağlantıdan sorumludurlar. Bu örüntülerde kalıtım kullanılarak arabirimler tasarlanır. Nesne yaratırken yeni fonksiyonaliteler eklenir.

  • Adapter
  • Bridge
  • Composite
  • Decorator
  • Facade
  • Flyweight
  • Proxy

–          Davranışsal Örüntüler (Behavioral Patterns) : Bu örüntülerin neredeyse tamamı nesneler arası iletişim ile ilgilenir.

  • Chain of Responsibility
  • Command
  • Interpreter
  • Iterator
  • Mediator
  • Memento
  • Observer
  • State
  • Strategy
  • Template Method
  • Visitor

MVC – Model View Controller

Veri tabanından sorgulama işlemleri yaparken, yazdığımız ekran kodu içerisine connection alma, sql çalıştırıp dönen sonuçları  görüntüleme kodları yazdığımızı düşünelim.

Daha sonra bir ekrana daha ihtiyacımız olduğunu düşünelim. O ekrandan da veri tabanına bağlanıp dönen sonuçları ekranda görüntüleyeceğiz. Bunu da ekran kodunun içine yazalım. Üçüncü bir ekran yazdık. Bu ekranda da birinci ekrandaki SQL’i kullanan kodu kullanmamız gerekiyor. Aynı kodları bu ekran sınıfına kopyalamamız mümkün ancak SQL’de bir değişiklik yapılması gerektiğinde aynı SQL’i kullanan tüm sınıfların güncellenmesi gerekir. Ayrıca veri tabanı bağlantısı için tüm sınıflarda ayrı ayrı bağlantı açtık, driver’ı register ettik. Veri tabanı bağlantı ayarları değişirse ne olacak? Yine gidip tek tek bütün sınıfları güncellemek gerekecek.

Büyük projelerde değiştirilmesi gereken yer sayısı bir, iki değil birkaç bini buluyor. Bu değişiklikleri yaparken de bazı yerlerin gözden kaçması mümkün ayrıca çok fazla iş yükü oluyor. Ufacık bir değişiklik yapmak için binlerce kopyanın güncellenmesi pek de mantıklı değil. Bir de güncelledikten sonra baktınız hoşunuza gitmedi tekrar birkaç saat uğraşarak eski haline almamız  gerekecek.

Bunun olmaması için bir tane sınıf oluşturuyoruz. Ortak olan tüm kodları buraya yazıyoruz. Mesela veri tabanı bağlantısı için bir sınıf yazıp connection her gerektiğinde bu sınıfı kullanabiliriz. Ya da SQL’ler için bir sınıf yazıp farklı ekranlardan bile olsa aynı SQL çağrılmak istendiğinde bu sınıf kullanılabilir. Böylece unutma şansımız olmuyor ve birden fazla yerde değişiklik yapmaya gerek kalmıyor.

İşte bu şekilde yazılan programlama mantığına çok katmanlı mimari adı veriliyor. Ekranlarımız, SQL’lerimizin olduğu sınıf, bağlantı sınıfı, loglama sınıfı, güvenlik sınıfı gibi birçok katman ortaya çıkıyor. Butona bastığımızda kod sırayla birbirini çağırıyor. Çok katmanlı mimariye uygun bütün projeler bu şekilde yazılıyor. Biz de yazdığımız uygulamanın ilerde gelişeceğine inanıyorsak mutlaka çok katmanlı mimariyi kullanıyoruz.

Katman sayısı yazılımcıya bağlıdır. Ancak en az görsel sayfalarımız, sayfalardan gelen istekleri ele alan kontrol sınıflarımız ve veri tabanı ile ilişkili olan sınıflarımız için 3 katman kullanmak tavsiye ediliyor. Dediğim gibi güvenlik için ayrı bir katman, loglama için ayrı bir katman, filtreler için ayrı bir katman, exception yönetimi için ayrı bir katman daha kullanılabilir. Bu tamamen programcının insiyatifindedir.

Görsel Katman : (View) Son kullanıcıya hizmet veren ekranlarımızın bulunduğu katmandır. Masaüstü uygulamaları için form sınıfları, web uygulamaları için HTML sayfaları, JS dosyaları, resimler vb. bu katmanda yer alır.

Kontrol Katmanı : (Controller) Kullanıcının isteklerini ilgili katmanlara ileten sınıfların bulunduğu katmandır. Örneğin web uygulamalarında yazılan servlet sınıfları bu katmanda yer alır.

Model Katmanı : (Model) Katmanlar arası iletişimi sağlayan bean sınıfları ve diğer tüm işleri yaptığımız iş sınıfları bu katmanda yer alır. Uygulama içerisinde kullanılan Thread sınıfları, veri tabanına istek ve yönlendirme yapan, ayrıca diğer tüm işleri yapan iş sınıfları da yine bu katmandadır.