Web projelerini ASP.NET MVC ile geliştirenlerden olduğum için Silverlight tarafında da kendi çabalarımla model view tarzı çalışmalarla uğraşmaktaydım. Silverlight tarafında da katmanları birbirinden izole eden böyle bir yapı var mı diye araştırırken MVVM(Model View and ViewModel) yazılım tasarımıyla karşılaştım.
Yazılım tasarımları yeni başlayanlar için pek bir şey ifade etmeyebilir. Fakat uzman yazılımcılığa adım attıktan sonra, geleneksel yöntemlerle işlerin çorbaya dönüştüğü ve içinden çıkılamaz bir hale geldiğini görenler çıkış noktası aramaya başlarlar. Böylece ilk başlarda saçma gelen yöntemler artık yazılımcı için tam anlamıyla can simidi olur. Bu yazımızda da Silverlight MVVM yazılım tasarımını, giriş seviyesindeki bir örnekle incelemeye çalışacağız.
MVVM yazılım tasarımındaki temel amaçlar:
- Yazılımda esnekliğin sağlanması(Loosely Coupled),
- Genişletilebilir bir yazılım oluşturulabilmesi(Open Closed),
- Test edilebilir yazılımın oluşturulabilmesi,
- Kod tekrarlarının önune geçilmesi (Clean Code) şeklinde sıralanabilir.
MVVM sayesinde Silverlight framework elementlerin(xaml tarfının) ve CLR (C#, VB gibi) kodlama tarafının birbirinden yalıtımı da sağlanabilir. Xaml ve Kod tarafında event paslaşmalarını Command Binding mekanizmalarıyla ortadan kaldırmak MVVM tasarımında işleri daha da kolaylaştırmaktadır.
Microsoft Pattern & Practices ürünlerinden olan Prism kütüphanesi sayesinde Desktop uygulamaları ve Silverlight uygulamalarında modülerliği ve yazılımda esnekliği sağlayan bir takım özellikler mevcuttur. Bu yazımızdaki örnek uygulamada command binding diye adlandırılan yapıdan bahsedeceğiz.
ViewModel içerisine tanımlanan bir ICommand nesnesi aracılığı ile View tarafından commanding işlemi gereçekleştirilebilmektedir. Tekrardan view tarafında tanımlanan button v.s gibi bileşenlerin event’lerini yakalayıp, iş operasyonlarını gerçekleştiren süreçleri view tarafına sokmamış oluruz. Yani kısaca herkes kendi yoluna gider.
Şimdi giriş seviyesinde bir örnek uygulama yaparak konuyu incelemeye başlayabiliriz. Örneğimize başlamadan önce Microsoft Pattern & Practices sitesinden Prism kütüphanelerini indirip bunlardan Microsoft.Practices.Prism referans olarak projemize eklemek gerekmektedir.
Örnek Uygulama
Örnek senayyomuz, bir Product tipinin arayüz ayrımının yapılması şeklinde olacaktır.
Model olarak Product adında basit bir temel tip belirliyoruz.
public class Product { public string Name { get; set; } public decimal Price { get; set; } public override string ToString() { return string.Format("Name: {0}, Price: {1}", Name, Price); } }
Bu tipimizi görünüm arayüzünde (xaml tarfına) temsil edecek bir tip oluşturmamız gerekiyor. Bu tip aslında bizim ViewModel dediğimiz yapıyı oluşturacak olan tiptir.
public class ProductViewModel { private readonly Product product; public ICommand SaveCommand { get; set; } public Product Product { get { return product; } } public ProductViewModel() { product = new Product {Name = "Notebook", Price = 1500}; SaveCommand = new DelegateCommand<object>(OnSave); } private void OnSave(object obj) { MessageBox.Show(product.ToString()); } }
Yukarıda görüldüğü gibi ViewModel tipimizin adı ProductViewModel şeklindedir. Bu tip, içerisinde Product tipini barındırıyor ve kaydetme işlemini tetikleyecek olan ICommand tipinde bir nesne barındırıyor. Constructor içerisinde ürün bilgileri ve Command işlemini yapacak olan nesnenin oluşturulma işlemi gerçekleştiriliyor. DelegateCommad tipi, Microsoft.Practices.Prism.Commands
İçerisinde bulunmaktadır. Bizim senaryomuzda herhangi bir kayıt söz konusu olmadığından kaydetme işlemini MessageBox mesajı ile geçiştiriyoruz.
View tarafında da kayıt bilgilerinin alındığı bir form tasarımı oluşturacağız. Ayrıca View tarafında DataContext olarak az önce oluşturduğumuz ViewModel tipini göstereceğiz. View kontrolümüz ProductView.xaml şeklindedir ve içeriği aşağıdaki gibidir. Cs kod tarafında hiç bir işlem yapılmamıştır.
Hazırlık aşaması tamam olduğuna göre artık oluşturduğumuz View, Mainpage.xaml içerisine yerleştirilebilir.
Burada dikkat etmemiz gereken noktalardan biri, button click event’ine hiç kod yazılmaması. Bunun yerinde Command mekanizmasının kullanılmasıdır. Command binding, MVVM tasarım desenini kullanmayı kolaylaştıran yöntemlerden biridir. Eğer button click event kullanılsaydı View tarafında View tarafında yapılmaması gereken bir işlem yapılmış olacaktı.
Sonuç olarak Solution penceremiz şu şekildedir. Klasörleri kendim oluşturdum, yani visual studio tarafından hazır olarak sunulan bir MVVM projesi yok.
Tekrar görüşmek ümidiyle.