Architectural Design Patterns in IOS Programming
Tasarım örüntüleri nesne yönelimli programlamada denenmiş en iyi adaptasyonu sağlamak amacıyla ortaya çıkmış, tasarım sistematiği üzerinde izlenecek optimum yolların belirlenmesi işlemidir. Yazılım tasarımı ile ilgili problemi, çözümü ve bu çözümün ne zaman ve nasıl yapılacağının belirlenmesidir.
Temelde nesneler ve sınıflar arasında tipik ilişkileri göstermektedir. Temelini nesne yönelimli programlama mantığı oluşturduğu için programlama dillerinden bağımsız tasarlanır. Bundan dolayı farklı dillerde yazılan tek bir projenin tasarım örüntüsü aynı şekilde tasarlanabilir. Fakat burada dikkat edilmesi gereken önemli konu bir örüntü ile başlanılan proje bu şekilde devam ettirilmelidir.
Peki neden tasarım örüntülerine ihtiyaç duyulmuştur?
Bu sorunun cevabı aslında çok basit, başlanılan bir projenin zamanla yazan kişi tarafından bile okunamaz ve yönetilemez hal aldığı çoğu zaman yazılımcıların tecrübe ettiği bir konudur. Bundan dolayı kodların okunabilirliği, esnekliği ve yönetilebilirliği açısınından bir standardizasyon sağlanması proje boyutlarının büyümesi durumlarında bile büyük fayda sağlamaktadır. Her componente tek sorumluluk verilerek yazılım modüler hale getirilir ve bu yönetilebilirlik kolaylıkla sağlanmış olur.
Hangi örüntü sizin durumunuz için en uygun?
Bunun cevamı aslında yok gibi bir şey. Tasarım örünütüsü belirlenirken her durum için farklı bir örüntü daha iyi oturabilmektedir. Bu açıdan pattern belirlemek, ilk önce kendi case’ inizi daha sonra da tüm patternlerin yapısını iyi bilmeyi gerektirir.
Tasarım örüntüleri kendi içerisinde bir çok dallara ayrılır. Bunlardan bazıları;
- Creational Design Patterns
- Structural Design Patterns
- Behavioral Design Patterns
- Architectural Design Patterns
- Functional Design Patterns vs.
Bu dallardan her biri farklı bir yapı için kurulabilecek örüntü yapılarını belirtmektedir. Örneğin herkesin projesinde en az bir tane kullandığı singleton class yapısı aslında Creational Design Pattern’ e ait bir örüntü yapısıdır. Ya da birbirlerini inherit eden nesnelerle oluşturulan bir yapıda kullanılan Decorator Desing Pattern’i Structural Design Pattern grubuna ait bir örüntüdür. Bu yazıda projenin mimari açıdan kurulumunda kullanılan tasarım örüntüleri anlatılacaktır.
Architectural Design Patterns
Mimari açıdan oluşturulan bu tasarım örüntüleri genelde projenin tümüne ait izlenecek yolları gösteren tasarım örüntüleridir. MVA, MVC, MVVM, MVP, Microservices gibi birçok örneği bulunmaktadır. Yanlız yapısal anlamda mobil programlamaya en çok uyan örüntüler MVP, MVC, MVVM örüntüleridir. Bu yazıda yine bu üç örüntünün karşılaştırılması yapılacak avantaj ve dezavantajlarından bahsedilecektir. Yalnız yukarıda da belirtildiği gibi bir örüntünün ön plana çıkması imkansız olup bu yazılımcının case’ine göre farklılık göstermektedir.
MVC (Model View Controller)
Model View Controller tasarım örüntüsü günümüzde en yaygın kullanılan tasarım örüntüsü denilebilir. Temelde mimari 3 ayrı yapıya ayrılmaktadır. Bunlar servis verilerinin modellendiği, kullanılcak sınıflara ait veri yapılarının belirlendiği kısım olan Model, kullanıcıya gösterilecek arayüzün tasarlandığı View ve bu iki katman arasında köprü görevi gören Controller yapısıdır. İlk kurulan yapıda View ile Model arasında bazen etkileşim olabilse de Apple mühendisleri bunu biraz değiştirerek View ile Model arasındaki haberleşmeyi tamamen ortadan kaldırarak bütün işlemleri controller üzeriden gerçekleştirmeyi hedeflemiştir. Zaten günümüzde de açılan yeni bir Xcode projesi default olarak bu yapıda oluşmaktadır.
Yukarıda da görüldüğü gibi Model ile View herhangi bir şekilde haberleşme yapmayıp, bu işlem sadece Controller üzerinden gerçekleşmektedir. View tarafından alınan kullanıcı action’ları controller’a iletilir. Controller bu işlemle ilgili modelde değiştirilecek bir durum varsa bunu değiştirir ve yine gerekirse view üzerinde güncellemeleri yapar. Görüldüğü üzere bütün trafik controller üzerinden gerçekleştirilmektedir.
MVC tasarım örüntüsü küçük projelerde rahatlıkla kullanılabilecek bir örüntü yapısıdır. Fakat projenin boyutu büyüdükçe Controller yapısı aşırı şişmektedir. Bu da okunabilirliği(readablity) ve yönetilebilirliği(maintainablity) olumsuz yönde aşırı etkilemektedir. Hatta çoğu zaman MVC açılımı hicivli bir şekilde Massive View Controller (Aşırı View Controller) olarak da tanımlanmaktadır. Bu açıdan büyük projelerde yönetilebilirlik açısından MVC kullanımı malesef çok da uygun olmamaktadır.
MVP (Model View Presenter)
MVP aslında Apple’ın evirdiği MVC yapısına çok benzemektedir. Yanlız burada View ile Controller arasında köprü görevi gören katmana Controller değil de Presenter adı verilmiştir. Dolayısıyla Model katmanı ve View katmanındaki değişiklikler Presenter aracılığı ile yapılıp tekrar ilgili katmana gönderilmektedir. Bu bağlamda IOS programlama açısından bakıldığında MVP paterni ile proje geliştirmek çok da mantıklı olmamaktadır. Çünkü default olarak MVC desteklediğinden oradan devam etmek daha mantıklıdır. Fakat MVC örüntüsünde karşılaşılan sıkıntılar burada da olduğundan yine büyük projelerde çok da mantıklı olmamaktadır.
MVVM(Model View ViewModel)
MVVM örüntüsü gelişen teknolojiler ile LOC(line of code) sayısının artmasından dolayı projelerin boyutlarının büyümesi ile ortaya çıkmıştır. İlk olarak Microsoft tarafından ortaya atılmıştır. Aslına baktığınız zaman yine View ve Model arasında ViewModel adı verilen bi katman eklenmiştir. Fakat buradaMVC ve MVP’ ye farkla ViewModel View hakkında herhangi bir bilgiye sahip değildir. yani View ile ViewModel arasında 1-n bir ilişki vardır. IOS programlama açısından bu patternin uygulanabilirliğine bakılacak olursa, bunula ilgili birçok yöntem olup bana en mantıklı gelen ve IOS programlamaya en uygun, yazısına buradan erişebileceğiniz 4 lü MVVM yapısını anlatacağım. Burada yapılması gereken işlem view controller altında transformasyon ve hesaplama işlemlerinin yapılabileceği bir katmanın daha eklenmesi gerektiği ortaya çıkmaktadır. Yani View katmanında yine arayüze ait işlemler, Model katmanında yine veri modelleri olacak fakat, controller katmanında sadece IBOutlet değişkenleri, IBAction methodları gibi zorunlu işlemler yapılacak kalan, dönüşüm ve hesaplama işlemleri ViewModel katmanında yapılacaktır. Resimde de görüldüğü gibi View Controller View Model objesini edinir, callbackler aracılığı ile veri aktarılabilir. Fakat view katmanındaki actionlar ve outletler direkt olarak yine view controllerda handle edilir. Ama yine de action metodlarının içerisi View Model’dan çağrılıp direk button içerisinde işlem yapılmamalıdır 😃.
Bir örnek proje ile patternin entegrasyonu anlatılmak gerekirse, Bir TextField, bir listele Button’ u ve bir Table View ile bir proje oluşturulup, resimde de görüldüğü gibi Text Fieldan girilen değer table view da listelenecek yapı MVVM ile oluşturulacaktır.
Yukarıda da anlatıldığı gibi ViewModel sınıfında Table View metodları, ve data array’i controller da ise sadece lifecyle metodları, outlet ve actionlar bulunmaktadır.
Yukarıda da görüldüğü gibi Table View’i delegate ve data source protokolleri tanımlanmış ve içlerinde gerekli işlemler yapılmıştır. Yine data dizisi de burada tanımlanmıştır.
View Controller’da ise sadece lifecycle metodu viewDidLoad, ViewModel objesi, ve outlet variable’ lar bulunmaktadır. Burada delegate ve dataSource ataması view model’ a yapılmıştır. MVVM kullanılacaksa bu tür işlemlere dikkat edilmelidir. Böylece button’ a basıldığında view modeldaki array’ e textfield’dan alınan değer eklenip tekrar listeleme yapılmıştır.
Görüldüğü üzere basit bir projede bu pattern entegre edilmiş controller’ın yükü neredeyse yarı yarıya azaltılmıştır. Proje boyutunun büyümesi ile bu değerin üstel olarak artacağından emin olabiliriz. Genel olarak kontrollerlarda tek satırlık view model metodları çağırlacak ve bütün dönüşüm işlemleri bu çağrılan metodda yani View Model’da gerçekleştirilecektir.
Yukarıdaki örnekden de anlaşılacağı gibi MVVM küçük projelerde gereksiz dosya fazlalığı sağlamaktadır. Bu yüzden küçük projelerde tercih edilmemelidir.
Sonuç
Bu yazı ile architectural design pattern’leri yüzeysel olarak anlatılmış, avataj ve dezavantajlarından bahsedilmiştir. Sonuç olarak, herhangi bir pattern süper diğerleri çöp demek yerine projeye göre pattern belirlemek gerektiği üzerinde durulmuştur. Fakat şunu kesinlikle unutmamak gerekir, button actionlarında satırlarca kod yazmak yerine herhangi bir pattern belirleyip onun üzerinden SoC (Seperation of Concern) temelinde işlem yapmak hem yazılımcının kendisine, hem de kendinde sonra gelecek kişiye ve en önemlisi yaptığı işe saygısı açısından çok önemlidir. Umarım yazı faydalı olmuştur, iyi kodlamalar.😊