18 Mart 2011 Cuma

[Yazılım Felsefesi] UI Pattern'ler ve MVVM Üzerine Fikirsel Çalışmalar

Merhaba Arkadaşlar;

[Yazılım Felsefesi] başlıklı makalelerle, sizlerle hayallerimi paylaşacağım.. Sorun olarak alıglayıp; çözüm için zihnimi zorladığım fikirler üzerine fikirler ortaya atacağım..

Uzun zamandır düşündüğüm ama tam olarak çözüm üretemediğim sorun vardı:

Çok katmanlı Mimari'ye uygun olarak tasarlanan Bussiness katmanı -ya da -; sisteme dair Bussiness Logic kodlarını barındırıyor. Ancak UI Logic(ya da Application Logic) olarak ifade edebileceğimiz kodları hiç bir şekilde arayüz bağımsız hale getiremiyorduk.  Daha fazla detaya girmeden hemen kısaca bu kavramları açıklayalım:

  • Bussiness Logic: "Bir e-ticaret portalında satışın onaylanması için girilen Kredi Kartının, sipariş boyutunca provizyon vermiş olması gerekir." gibi sistemsel kural ve mantığa denir.
  • UI Logic(App Logic): "Adres girme ekranında İl combosu seçildiğinde, İlçesi combosu İl'de seçilen değere göre doldurulur." gibi ön arayüzü ya da kısaca Bussiness Katmanından önce bir model'in kullanıcı tarafından manüple edilmesi olaylarına bu ad verilir. "Hesaplar listesinde, 10.000 TL'den büyük aylık geliri olanların kırmızı görünmesi" gibi kural örnekleri de verilebilir.

Asp.Net MVC bu trendin başlancını bence çok güzel verdi. Model üzerine;

  • Validation
  • Control Type(Ön arayüzdeki gösterilecek kontrolün şekli (EditorFor(...) ya da DisplayFor(...) gibi))
  • FormatString
  • DisplayName(Alanın Kullanıcıya gösterilecek ismi)

gibi alanlar yerleştirerek UI'a bu bilgilerin konulmasının önüne geçmeye çalıştı.. Aslında Model üzerine konulabilecek bence önemli bir kısım daha var..

Model Based Security diye sallama bir tabir yaptım bu fikir için :) Amacım aslında Model'lerimize, nesne bazlı ya da property bazlı security ayarları koymak(bu Controller'ların üzerine Authorize(Role="Admin") gibi olabilir). Örnek vermek gerekirse;

  • ForumPost nesnesinin sadece CreateUser tarafından değiştirilebilmesi, 
  • Kisi modelinin Ad, Soyad bilgilerini CreateUser değiştirebilmekteyken, Maaş bilgisini sadece Admin değiştirebilmesi
  • Kisi modelinin tüm kayıtlarını Maaş hariç görebiliyor, kendi maaşını görebiliyor vb.

Her şeyin nesneye dayalı olması için bu da güzel bir teknik ama hala bazı isteklerimizi karşılamıyor. UI Logic için bir çözüm bulmalıyız.. Peki MVVM'e ne dersiniz?

Model-View-ViewModel tabiri bize biraz daha başlancıç oluşturuyor. ViewModel kelimesini de; Model of View'a çevirdiğimizde daha da anlaşılır. İlk aklıma gelen şey, "İl" combosuna bir dropdown gibi erişebilmemizi sağlayacak bir sınıf.. Aslında bu sınıf; ..aspx.cs sınıflarımız oluyor.. Bizim için korkutucu, sadece daha fazla karmaşıklığa neden olan sınıflar.. O zaman biraz daha farklı bir bakış açısından gitmeliyim..

Model'den sayfaya.. Test Driven yazarken; sayfayı hayal edip; kodsal olarak test etmek..

Sayfa üzerinde en sık kullandığımız Applicaiton Logic: Visible ve Enabled.. Peki Model üzerinde nasıl tasarlayabiliriz bunu ?

  • CanGet : Visibility
  • CanSet : Enabled
  • CanInvoke : Button Enabled

olarak ifade etsek model üzerinde ? Ortaya aşağıdaki gibi pseude-code çıksa?

 

model.Ensure(c=> c.Il.HasValue).AllowForSet(c=> c.Ilce);


 



Bu bize aslında testlerimizi de ortada bir UI yokken bile yapabilmemizi sağlamaz mı mesela:



 



public int IlceID{
get
{
if ( ! this.CanGet("IlceID"))
thow new Exception();
return _ilceId;
}
set
{
if ( ! this.CanSet("IlceID"))
thow new Exception();
return _ilceId;
}
}


 



gibi bir kodu rahatlıkla test edebiliriz.



 



public void TestWeCanNotSetIlceBeforeSetIl()
{
AdresModel adres= new AdresModel();
Assert.ThrowsException(()=>adres.IlceId=5);
}

public void TestWeCanSetIlceAfterSetIl()
{
AdresModel adres= new AdresModel();
adres.IlID=3;
Assert.DontThrowException(()=>adres.IlceId=5);
}


 



Tabii ki property'ler sürekli tekrar eden böyle bir koddan Proxy sınıflar aracılığıyla kurtarır ve temiz bir kod elde etmeye çalışırız. Zaten ChangeTracking amacıyla çoğu zaman model'lerimiz proxy nesneler halinde erişmekteyiz - ki bunu da bize ORM'lerimiz sağlar...



Peki bunu nasıl uygulayabilirim. Bir de bunu üzerine beyin jimnastiği yapalım:



 



Asp.Net MVC'de Model'lerin bind edilme mimarisi hazır zaten. Yaptığım ek değişiklikleri de Html.DisplayFor(...) mimarisi ile gerçekleyebilirim. Ancak Controller ile ViewModel'i birbirinden ayırmam çok zor olacak.



Asp.Net WebForms daha stateful olduğu için belki işime yarayabilir. Asp.Net'in kendi kontollerinden inherit alarak kendi Custom Contol'lerimi yazarsam bunları da Model'in property'lerine bind edecek bir sistem geliştirirsem güzel olabilir.



 



Bu fikri sevdim :) Şimdiden heyecanlanmaya başladım :)



Bakalım hayal ettiklerimi ne kadar gerçekleyebileceğimTongue out

Hiç yorum yok:

Yorum Gönderme