Arayüz Kullanarak Katmanlar Arasındaki Bağımlılıkların Azaltılması

Bu örnek çalışmamızda arayüzler kullanılarak sınıflar arası bağımlılığın nasıl azaltılabileceği incelenecektir. Arayüz kullanılarak sınıflar arası bağımlılığın tersine çevrilmesi sağlanacak ve bu işlemin bize ne gibi katkılar sağladığı incelenmeye çalışılacaktır.

Örneğimizde kullanacağımız örnek bir senaryomuz bulunmaktadır. Bu senaryoya göre bir öğrenci sisteminde öğrenci harçlarının hesaplanması için birçok farklı harç hesaplam metodu bulunmaktadır. Bu farklı harç hesaplama türlerinden hangisinin seçilerek uygulamancağına programcı yapılan seçime göre karar verecektir. Örneğin sistemde harçHesaplama1 isimle harç yöntemi seçildiyse programcı bu yöntemi kullanarak hesaplama yapacaktır. Başka bir öğrenci için başka bir hesaplama yöntemi seçildiyse yine seçilen yönteme göre bir hesaplama söz konusu olacaktır. Senaryomuzun olabildiğince basit olarak belirlenmesine çalıştık. Böylece çalıştığımız konuya daha kolay odaklanabiliriz.

Yukarıdaki senaryoya göre önce arayüzler kullanılmadan doğrudan programcının buton arkasına kod yazarak bu hesaplamaları yaptığın düşünelim. Bu durumda programcı buton arkasında seçili olan harç tipinin ne olduğunu anlamak için if – else blokları yazmak zorunda kalcaktır. Sistem üzerinde çalışan geliştiricinin tüm harç tiplerinin nasıl hesaplandığını da bilmesi gerekecektir. Yani sistemin sunum katmanında çalışan bir programcı harç hesaplamanın detay bilgisine de sahip olması gerecektir. Halbuki sunum katmanında çalışan bir programcının asıl yapmak istediği şey sadece hesaplanan harç tutarının gösterilmesinden ibarettir. Harcın nasıl hesaplandığı ile ilgilenmesine gerek yoktur. Sunum katmanı olarak bahsettiğimiz kısım bir consol uygulaması olabilir, bir web uygulamasında buton arkasında çalışan kodlar olabilir, bir mvc projesinde controller metotları olabilir veya bir web servis uygulamasında kullanılan bir metot olabilir.

if (harcturu==”Lisans”)

{

}

else if (harcturu==”enstitu”)

{

}

else if (harcturu==”dönemlik”)

{

}….

Senaryomuza yeni bir harç tipi eklendiğinde programcı buton arkasına yazdığı kodları bulup yeni if – else blokları ekleyecektir. Tamamen farklı bir harç hesaplama ihtiyacı ortaya çıktığında bu if-else blokları çok fazlalaşacak ve işin içinden çıkılmaz bir hal alacaktır.

Şimdi yukarıdaki senaryomuzu bir de arayüzler kullanarak gerçekleştirmeye çalışalım. Başlangıçta arayüz ve sınıf tanımlamaları fazladan kod yazdığımızı hissettirebilir. Ancak bu sayede sistemimiz yeni gelişmelere çok daha elverişli şekilde cevap verebilecektir. Katmanlar birbirinden bağımsız hale gelecek ve sunum katmanında çalışan programcının harç hesabının detayını bilmesine gerek olmadan çalışabilmesi de sağlanmış olacaktır.

Çalışmamıza bir classLibrary projesi ekyeleyim. Önce harç hesaplam işlemlerimiz için ortak olan adımların tanımlandığı bir arayüz oluşturalım. Örneğimizde sadece tek bir ortak metot olduğunu varsayıyoruz.

public interface IHarcHesaplama

{

decimal HarcHesapla(int OgrenciId);

}

Şimdi tüm farklı harç hesaplama işlemlerini bünyesinde barındıracak sınıflarımızı oluşturalım. Tabiki oluşturulan sınıflar IharcHesaplama arayüzünden türetilerek oluşturulacaktır. Senaryomuzda şimdilik sadece iki farklı harç hesaplama yöntemi olduğunu kabul ediyoruz.

class EnstituHarc : IHarcHesaplama

{

#region IOgrenci Members

public decimal HarcHesapla(int OgrenciId)

{

return this.EnstituHarcHesapla(OgrenciId);

}

#endregion

private decimal EnstituHarcHesapla(int OgrenciId)

{

return 45 * 15;

}

}

İkinci harç hesaplama sınıfımız:

public class LisansHarc : IHarcHesaplama

{

#region IOgrenci Members

public decimal HarcHesapla(int OgrenciId)

{

return this.LisansHarcHesapla(OgrenciId);

}

#endregion

private decimal LisansHarcHesapla(int OgrenciId)

{

return 15 * 20;

}

}

Yukarıda tanımladığımız sınıfları inceyecek olursak her bir sınıf içinde arayüzden gelen ortak metodu tanımladık. Ortak metodumuz aslında farklı harç hesaplama işlemlerini yapan sınıfımıza özel olarak yazılmış başka bir metodu çağırmakta ve sonucu döndürmektedir. Bu tasarım sayesine iki farklı harç hesaplama sistemi birbirinden tamamen bağımsız sınıflarda ele alınmaktadır. Birinde yapılan bir düzenleme diğerini kesinlikle etkilemeyecektir. Yeni bir harç sistemi ihtiyacı olduğunda tek yapılması gereken şey aynı arayüzden türeyen yeni bir sınıf oluşturmaktır.

Buraya kadar yapılan işlemlerde sunum katmanında çalışan programcıdan harç hesaplama detaylarını gizlemiş olduk. Ancak hala bir takım eksiklerimiz var. Sınıfları kullanmak isteyen programcı kendisi bu sınıfları türeterek oluşturmak zorundadır. Yani sunum katmanında bu sınıfları kullanan programcı uygun türden sınıfı oluşturmak için yine if-else blokları yazarak sınıfları oluşturacaktır.

Decimal harcTutari;

if(harcturu==”Lisans”)

{

LisansHarcHesaplama harc = new LisansHarcHesaplama();

harcTutari = harc.HarcHesapla(123);

}

else if(harcturu==”YuksekLisans”)

{

EnstituHarcHesaplama harc = new EnstituHarcHesaplama();

harcTutari=harc.HarcHesapla(123);

}…

Nesne oluşturma görevini de sunum katmanındaki programcıdan almamızı sağlacak yöntem bir fabrika sınıfı oluşturmaktır. Bazı durumlarda sunum katmanındaki programcının sınıflar oluşturulurken belirtilmesi gereken detaylardan haberi olmayabilir. Örneğin oluşturulan sınıfların bir takım özelliklerinin (property) varsayılan değerler ile doldurulması gerekebilir ve bu işlemin son katmandaki programcının bilgisi dahilinde olmaması istenebilir. Böyle ihtiyaçlarda sunum katmanındaki if-else bloklarından programcıyı kurtarmak ve ortak bir fabrika sınıfından ihtiyaç duyulan uygun sınıfın oluşturularak döndürülmesi sağlanabilir. Şimdi fabrika sınıfımızı oluşturalım. Kütüphanemize yeni bir harç fabrikası ekliyoruz. Böylece ihtiyaç olan nesnesinin oluşturlması işlemini de client tarafında kod yazan programcıdan almış oluyoruz.

/// <summary>

/// Bu metot kütüphaneyi kullanacak programcıya ihtiyaç duyduğu türdeki harç nesnesini oluşturur.

/// </summary>

/// <param name=”HarcTipi”></param>

/// <returns></returns>

public IHarcHesaplama HarcOlustur(string HarcTipi)

{

if (HarcTipi==”Lisans”)

{

LisansHarc HarcHesapla = new LisansHarc();

return HarcHesapla;

}

else

{

EnstituHarc HarcHesapla = new EnstituHarc();

return HarcHesapla;

}

}

}

Fabrika sınıfınımızı da oluşturduktan sonra bu kütüphaneyi kullanacak programcının harç hesaplama için yapması gereken işlem aşağıdaki gibi olacaktır.

HarcFabrikasi fabrika = new HarcFabrikasi();

IHarcHesaplama harc = fabrika.HarcOlustur(“Lisans”);

decimal hespalananHarc = harc.HarcHesapla(4587);

Yukarıda görüldüğü gibi kütüphanenin kullanıldığı yerde yazılan kodlar sadeleşmiş ve detay işlemlerin nasıl yapıldığının bilinmesi zorunluluğu da ortadan kalkmıştır. Yeni bir harç türü eklendiğinde IharcHesaplama arayüzünden türüyen yeni bir sınıf oluşturulması ve fabrikadan bu sınıfın döndürülmesi yeterli olmaktadır. Yeni bir ekleme işlemi görüldüğü üzere client tarafında yazılan kodlarda bir değişikliğe ihtiyaç duymamaktadır. Bağımlılıklar tersine çevrilmiştir. Yani client tarafındaki işlemler kutuphaneye yapılan yeni eklemelerden etkilenmemiştir. Ayrıca fabrika tasarım deseni sayesinde programcıya uygun sınıfların üretilmesi sağlanmıştır.

Bu çalışmamızda bağımlılıkların tersine çevrilmesi ve fabrika deseninin kullanılması konusunu inceledik. Arayüz kullanımı ve esnek tasarım desenlerinin sağladığı örnekleri incelemeye devam edeceğiz. Sürçi lisan ettiysek affola.

Bir Cevap Yazın