23 Kasım 2015 Pazartesi

XAF Ortamında İş Modelini Çoklu Kalıtım Kullanarak Tasarlamak 2

Bir önceki yazıda, XAF ortamında çoklu kalıtım konusuna giriş yapmış, devam edeceğimizi söylemiştim. Bu yazıda, ara yüzler kullanılarak tasarlanan, çoklu kalıtıma dayalı iş modelimizin veri tabanı yapısının nasıl değiştirilebileceği ve iş mantığının yardımcı sınıflar aracılığı ile nasıl uygulanabileceği üzerinde duracağız.

Hatırlayacağınız gibi, çoklu kalıtım kullanılarak yapılan tasarımın, XAF tarafından oluşturulan veri tabanı üzerindeki yansısı, tasarımımızda ki nesne hiyerarşisinin tekrarlanması şeklinde olmakta idi. Bir başka deyişle, modelimizde kullandığımız ICari, IBanka, IStok, IPersonel gibi nihai elemanlar ve IAdres, IHesap, IMemo, IKodluEleman gibi paylaşılan elemanların her biri için ayrı bir veri tabanı tablosu oluşturulmakta ve bunlar OID anahtarlarının aynılığı üzerinden biribirlerine bağlanmakta idi. Bunun XAF altında kullanıldığında, esasen bizim açımızdan transparan olduğundan, bununla ilgilenmemize gerek olmayacağından ancak aynı veri tabanı başka uygulamalar tarafından da kullanılacaksa sorun olacağından söz etmiştik.

Tasarım aşamasında çoklu kalıtım kullanarak avantajlarından yararlanmak ancak veri tabanı üzerinde daha standart bir şema elde etmek nasıl mümkün olur? Standart haliyle XAF ara yüz tanımlarının kendisine bildirilmesi ile her kalıcı eleman (persistent) için bir veri tabanı tablosu yaratmaktadır. Eğer ilgili alanların soyutlama amacıyla yaratılmış eleman arayüzlerine ait ayrık tablolarda değil de, doğrudan nihai elemanların tabloları içinde tutulmasını istiyorsak, yapacağımız şey, soyutlama amacıyla kullandığımız elemanların kalıcı olmadığını bildirmektir. Bu bildirimi "NonPersistent" özelliğini kullanarak sağlayabiliriz.


[DomainComponent]
[NonPersistentDc]
public interface IAdres
{
     ...

}

[DomainComponent]
[NonPersistentDc]
public interface IKodluEleman
{
     ...
}

[DomainComponent]
[NonPersistentDc]
public interface IMemo
{
     ...
}

[DomainComponent]
[NonPersistentDc]
public interface IHesap
{
     ...
}

Soyutlama amaçlı kullandığımız elemanlar artık veri tabanı içinde barındırılmayacakları için XAF'e bildirilmeleri de gerekmemektedir. Bu durumda "Setup" fonksiyonu içinde ki kodlarımızı aşağıda ki şekle getirmemiz gerekecektir:

using DevExpress.Persistent.BaseImpl;
// ... 
public override void Setup(XafApplication application) {
    base.Setup(application);
    XafTypesInfo.Instance.RegisterEntity("Personel", typeof(IPersonel));

    XafTypesInfo.Instance.RegisterEntity("Cari", typeof(ICari));
    XafTypesInfo.Instance.RegisterEntity("Stok", typeof(IStok));
    XafTypesInfo.Instance.RegisterEntity("Banka", typeof(IBanka));
}

Bu adımlar sonucunda XAF veri tabanı üzerinde yalnızca nihai elemanlar için tablolar yaratacak, soyutlama ara yüzlerinde tanımlanmış olan alanları, kullanıldıkları nihai elemanlara ait tablolar içinde barındıracaktır.

İş Mantığı (Domain Logic)

Modelimiz, salt veriyi içeren sınıflar üzerine kurulu ise, buraya kadar tartıştığımız özellikler işimizi görmemize yetecektir, ama pek çok durumda, yarattığımız model sınıfları içinde o sınıfa özgü fonksiyonlar, olaylar ve olay karşılayıcıları, ilgili nesne özellikleri üzerinde operasyon yapan metodlar bulunacaktır. XAF'i sınıf tanımlamaları üzerinden kullandığımız (ve tekli kalıtımla yetinmeye razı olduğumuz durumlarda) sorun yok, gereken fonksiyonları, olay karşılayıcılarını o sınıf üstünde yazabiliriz. Örneğin Cari elemanına mail göndermek için kullandığımız bir fonksiyon ihtiyacımız olduğunu düşünelim. Bu fonksiyonu doğrudan Cari sınıfı içine yazabiliriz:
public class Cari : TicariIsletme
{

     ...

     public void SendMailToMe(string Title, string Message)
     {
         ...
     }

}

Ancak eğer çoklu kalıtım olanaklarından yararlanmak için "Domain Component" kullanmaya karar verdi isek, elimizde yalnızca ara yüz bildirimleri kalmaktadır. Açıktır ki, ara yüz bildirimleri içine uygulama (implementation) yazamayız. Yazdığımız ara yüzlerin uygulandığı sınıfları bulup onlar içine yazmak akla gelebilir ama bu, öncelikle bu sınıflar, XAF tarafından çalışma anında (runtime) tanımlandıkları, tasarım anında var olamdıkları için imkansızdır. Dahası, mümkün olsa idi dahi, ara yüzün uygulandığı bütün sınıfları bulmak ve yazmak istediğimiz kodu her bir sınıf içinde tekrarlamak zorunda kalacak idik ki, nesne tabanlı paradigmanın vaat ettiklerine tam anlamıyla ters bir iş yapıyor olacaktık. XAF bu problemi aşmak için "DomainLogic" denilen bir yardımcı sınıf kullanımına olanak verir. DomainLogic sınıfları düz birer sınıftırlar ve istediğimiz fonkiyonları vb. barındırabilirler. Ara yüz içine koyamadığımız uygulama kodlarını DomainLogic sınıfı üzerine koyabiliriz. Yarattığımız DomainLogic sınıfını ilgili olduğu ara yüz ile ilintilendirmek için DomainLogic özelliği ile donatmamız yeterli olacaktır. Örnek olarak IHesap elemanımız için Borç, Alacak bilgilerini sıfırlayacak bir işlev ihtiyacımız olduğunu düşünelim. 

[DomainComponent]
public interface IHesap
{
     double Borc{get;set;}
     double Alacak{get;set;}

     void ClearValue(IHesap instance);}

[DomainLogic(typeof(IHesap))]
public class IHesapLogic
{
     public static void ClearValues(IHesap instance)
    {
      instance.Borc = 0;
      instance.Alacak = 0;
     }        
}

Görüldüğü gibi IHesapLogic sınıfı DomainLogic özelliği ile IHesap ara yüzüne bağlanmıştır. XAF IHesap ara yüzünü uygulayan sınıfların her bir nesnesi için bir IHesapLogic nesnesi yaratacak ve uygulayan sınıf üstünden çağrıların yapılmasına olanak verecektir. Örneğimizde IHesap ara yüzünü uygulayan ICari elemanımız için ClearValues işlevi geçerli olacaktır.

Çoklu kalıtım model ağacımızın basitleşmesine, daha modüler kod geliştirebilmeye olanak sağlayan yöntem olarak çok vaatkar görünmekte. Kuşkusuz gerçek bir proje ile uğraşırken ayrıntılar önemli olacaktır. Ayrıntılar ve daha çok öğrenmek için aşağıdaki link yardımcı olacaktır:

https://documentation.devexpress.com/#eXpressAppFramework/CustomDocument113261




Hiç yorum yok:

Yorum Gönder