Arda Çetinkaya Yazılım ve arada kendim ile ilgili saçmaladıklarım…
Uzun zamandır Mikroservisler(Microservices) ile ilgili bir şeyler karalama niyetindeydim. Bu zamana kısmetmiş… Açıkcası,  mikroservislerin ne olduğunu, zaten internette kolaylıkla bulabileceğiniz kavramlardan bahsederek anlatmak istemiyorum.  O yüzden biraz daha örnekler üzerinden, canlandırabileceğiz şekilde, bir kaç özelliğinden bahsederek anlatmaya çalışacağım… Öncesinde geçen sene yapmış olduğum sunuma da göz atabilirsiniz.

Mikroservis kavramı, ilk konuşulmaya başladığı zaman servis odaklı mimari(SOA) için alternatif bir mimari model olarak yorumlandı. Ancak kesinlikle SOA’ya alternatif bir model ya da yaklaşım değil. Bunun altını özellikle çizmek isterim. Mikroservisleri, SOA mimarisinin karmaşıklığını, pratikleştiren ve yönetimini kolaylaştıran bir kavram olarak yorumlayabiliriz.

micro-service-architecture

Mikroservisler(Microservices), SOA mimarisi ile uygulama geliştirmek için tercih edilebilecek bir yaklaşım, bir mimari stil…

Burada önemli olan kelime “tercih“.  İhtiyaçlar doğrultusunda, getirilerini ve götürülerini ölçüp, biçip tercih edilmeli. Açıkcası mikroservisler sizi alıp, Mars’a götürmüyor; ya da tüm problemlerinizi düzeltmiyor. Getirilerinin yanında, götürüleri ve belli bir olgunluk seviyesinde olmak gibi şartları var.  Bu şartları sağlayabilecek olgunlukta ne kadar olursanız, o kadar faydasını görürsünüz.

Mikroservis mimari stili ile geliştirilen uygulamalar, pratikte bir birinden bağımsız bir kaç servisin beraberce kullanıldığı uygulamalar olarak karşımıza çıkıyor. Mobil, web ya da masa üstü, hatta hatta konsol uygulamaları, bu sayede aynı servisleri kullanarak geliştiriliyor. Dolayısıyla, aynı iş mantığı farklı platformalara kolaylıkla sağlanıyor. Microservices’lerin en önemli noktası; bu servislerin kendi başlarına çalışan, tek bir sorumluluğu olan, bağımsız servisler olmalarıdır. Mesela Amazon’nun web sitesi bir çok servis(microservice) ile geliştirilmiş bir web uygulaması. Aynı servisleri Amazon’nun mobil uygulaması ve B2B uygulamaları da kullanmakta.

Mikroservisler iş mantıklarını ve kurallarını kendi içinde tutmalıdırlar. “Ne yapıldığı” servisler tarafında, “nasıl yapıldığı” ise servisleri kullanan uygulamalar tarafında olmalıdır. Bu sayede iş mantığı tek bir yerde olup, sadece orada gelişecektir.

İş kabiliyetlerine göre ayrıştırılan servisler, tek başlarına çalışabilen servisler olmalıdır. Dolayısıyla platform, sistem, dil ya da framework bağımlılıkları yoktur. Yani bir e-ticaret sitesindeki kategori yönetimini sağlayan servisler .NET ile yazılabilirken, ürün görsellerini sağlayan servis node.js ile geliştirilebilir. Ödeme servisleri Scala ile olurken, istatistiksel verileri sağlayan kısımlar R dili ile yazılabilir. .NET servisleri, Windows sunucularda olurken, node.js *Unix tabanlı bir sistemde bulunabilir. Bu sayede belli bir teknolojiye bağımlılık da ortadan kalkmış oluyor.

continuous integrationBu servislerin bağımsızlık ilkesi, servislerin değişikliğini ve deployment’ını kolaylaştırıyor. Yani görselleri sağlayan servisdeki bir geliştirme, diğer servislerden bağımsız,  başka hiç bir servisi etkilemeden kolaylıkla yapılabilir. Benzer yaklaşım ile servislerin deployment’ları da bir birinden bağımsız ve bir birini etkilemeyecek şekilde gerçekleşebilir. Bu getirinin tabi ki bir şartı var. Oldukça düzgün, oturmuş ve sorunsuz bir Continuous Integration(CI) yönteminizin olması gerekmekte. Yani kodlarınız düzenli bir şekilde, belli aralıklar ile ortak kod deposuna gönderilmesi ve orada hatasız bir şekilde build edilmesi otomatik bir şekilde gerçekleşmeli. Aynı şekilde servisleri versiyonladığınız bir yönteme de sahip olmanız gerekmekte.

You had one jobAz önce dediğim iş kabiliyetlerine göre ayrışan bu servisler, bu ayrışmadan dolayı küçük olmalıdır. Tek bir sorumlukları olup, bu sorumlulukları sorunsuz bir şekilde gerçekleştirmelidirler. Bu da basit olmaları anlamına geliyor aslında. İş kabiliyetlerine göre basitlik kavramı değişse de, sonuçta tek bir sorumlulukları olduğu için karmaşıklıkları az olacaktır. Burada önemli olan anahtar kelime “sorunsuz“. Mikroservisler sorunsuz bir şekilde çalışmalıdır. Bu noktada test edilebilir şekilde geliştirilmeleri şartı ortaya çıkıyor. Servislerin sorunsuz olarak çalıştığını, hem birim testler ile hem de otomatikleşmiş testler ile sağlamak gerekli. Aksi takdirde problemi servisler, problemli uygulamalara yol açacaktır. Dolayısıyla test kültürünün takım ya da şirket içinde belli bir olgunluğa erişmiş olması gerekmekte.

Mikroservislerin en önemli özelliklerinden biri, “scale” edilebilir olmaları. Farklı sistemler ve platformlarda çalışabilen farklı servisler olarak geliştirildikleri için, ihtiyaça göre genişletilebilirler. Mesela yoğun “memory” kullanan bir servis ile yoğun I/O işlemi yapan bir servisi farklı şekillerde “scale” edip, kaynak kullanımını optimize etmek oldukça kolay olacaktır. Bu noktada microservices’lerin yönetimi ve monitör edilmesi şartı da karşımıza çıkacaktır. Dolayısıyla devops kültürünün yazılım ekibinde ya da şirkette kabul edilmiş ve oturmuş olması gerekmekte.

dev-ops

Bir çok servisin ortalıkta oluyor olması, bu servislerin monitör edilmesini gerektirecektir. Dolayısıyla öncelikle bu alt yapıyı sağlayan bir platform kurmak ya da araç kullanmak gerekli. Mümkün olabildiğince bu monitör alt yapısı ayrıntılı olmalıdır. Servislerin log’ları, servislere yapılan request sayıları, servis süreleri, servisleri kimlerin çağırdığı gibi kavramları merkezi bir yerden yönetebilmek servislerin operasyon kalitesini arttıracaktır.

Mikroservis mimari stilinin en zor noktası, servislerin büyüklüğü yönetmek. Servisler adet olarak çok fazla büyür ise, sorumlulukları tek bir  servis altında toplanacak şekilde, bir servismiş gibi ele almakta fayda olacaktır. Servislerin içerikleri ve kabiliyetleri ise büyüklük konusunun bir başka noktası. Bu noktada servisin yaptığı işi bilen, sınırları ve ihtiyaçları net bir şekilde tanımlayan kişiler mutlaka olmalıdır. Ya iş birimleri, analistler ya da teknik olarak yetkin kişiler; ve bu kişiler mutlaka tecrübeli olmalıdır. Aksi takdirde servislerin içinde kaybolmak kaçınılmaz olacaktır.

Mikroservislerin temel karakteristik özelliklerini kısaca anlatmaya çalıştım. Anlaşılması ve gerçekleştirilmesi zor olanlara yer vermeye çalıştım. Pratik olarak uygulamak ya da bu mimari stile göre uygulama geliştirmek zor olsa da, imkansız değil. Ama ciddi bir geliştirme kültürü değişikliği şart. Full-stack geliştiriciler, devops’lar ve yazılım prensipleri ile ilgili farkındalık arttıkça, ciddi anlamda tercih edilebilecek ve belki SOA’nın uygulanabilirliğini kolaylaştıracak bir yaklaşım olacaktır. Umarım bazı kavramlar biraz daha netleşmiştir. Bir sonraki yazıya kadar, hatasız build‘ler…

Çok uzun zamandır merak ettiğim Brugge’e sonunda gitme fırsatı elde ettim. Gidenler genelde Brüksel merkezli, günü birlik(ya da max. 2 gün) Brugge ve Ghent şeklinde bir program yapıyor. En azından benim rastladığım, duyduğum hep bu şekildeydi. Kendileri yapmasa da, turlar falan bu şekilde sanırım. Kafamızı dinleyelim yeter, güzel zaman geçirelim, her yeri görmesek de olur kafasında, rahat bir tatil istediğimiz için, biz böyle yapmadık ve dolu dolu 4 gün Brugge’ün keyfini çıkardık.

Brugge’e, Brüksel üzerinden gitmek çok kolay. Brüksel hava alanından şehir merkezine, oradan da Brugge’e trenle 1 saatte gidebiliyorsunuz. Oldukça keyifli bir yolculuk, bunun da altını özellikle çizmek isterim.

Brugge

Brugge, oldukça küçük bir kent. Her tarafını yürüyerek dolaşabilirsiniz. Her yer bir birine oldukça yakın. Dolayısıyla kent merkezine, tren istasyonundan yürüyerek gitmek mümkün. Yok ben yürüyemem derseniz, hemen tren istasyonunun çıkışında otobüsler var…Yok ben otobüse de binmem derseniz de, taksiyle yaklaşık 15-20 euro civarı bir ücrete gitmek istediğiniz yere gidebilirsiniz.

BruggeBrugge, oldukça sevimli bir orta çağ kenti. Avrupa’nın büyük kesimini yıkan II. Dünya Savaşı’nı yara almadan atlatmış. Dolayısıyla hala bir “orta çağ” kenti. Açıkçası sadece mimarisinden dolayı değil…Sakinliği ve kendi halinde olması, filmlerde gördüğümüz o kuzeydeki kaleler içindeki kendine has yaşam tarzları Brugge’de de var. Mimarisi ile ruhu da korunmuş kentin… Yürüyerek her yere gidebildiğiniz için, önce mutlaka yürüyün…Bol bol yürüyün…Girebildiğiniz tüm sokaklara girin. Tüm binalara bakın, affetmeyin hiç. Daha sonra zamanınız olursa bir de bisiklet kiralayın diyor herkes ama biz kiralamadık. Açıkçası bisiklet ile keyifli bir şekilde dolaşmak, insan kalabalığında biraz zor olabilir. Tabanway rulessss….

BruggeBrugge’ün en büyük olayı, sanırım “bira”…Sonra çikolata, sonra dantel…Patates ve waffle bunların yanında biraz daha geride kalsa da, onları da her köşe başında bulabilirsiniz. Ama dediğim gibi “bira” en ağırlığı olan şey. Bir rivayet göre 16000 çeşit bira varmış…Siz düşünün artık. Gitmeden önce hiçbir yerde okumadığım ve görünce şaşırdığım, bir “çay” gerçeği de var. Açıkcası hiç bilmiyordum, ama çay da Brugge’de hatırı sayılır bir saygınlığa ve çeşitliliğe sahip. Çay dükkanlarına girip, kokuları ile kafa bulabilirsiniz…

2 günde çok rahat, keyifle gezilebilecek yerleri tamamlayabilirsiniz. Eğer zamanınız bolsa o yüzden sıkıştırmanın anlamı yok. Bilimum gezi sitesinde zaten gitmeniz gereken yerler ve yapmanız gerekenler hakkında bir çok şey bulabilirsiniz. O yüzden tek tek yazmayacağım ben de. Ama özellikle bir kaç yerden bahsetmek isterim.

Brugge’de ne yapalım…

BruggeMinnewaterpark ve Beguinage mahallesi…Burası kentin güneyinde, tren istasyonuna oldukça yakın bir bölge. Kuğuların yoğun olduğu, bol yeşilikli ve güzel bir manzarası olan, dinlendirici bir yer…Alın biranızı, oturun banka… Burayı sevmemin bir diğer sebebi, Brugge’e gitmişken gidilmezse olmazı, De Halve Maan‘ın buraya çok yakın olması. De Halve Maan, Brugge’de hala kentin içinde bira imalatı yapan, Brugge’deki en eski bira evi…Bir ara gazetelere de çıkmıştı. Birayı taşımak maliyetli oluyor diye, şehrin altından borular ile birayı diğer şehirlere ve Brüksel’e taşıyan yer…Neyse…Kendi birasını nasıl ürettiğini anlatan 1 saatlik bir turu ile içerisini gezmeniz mümkün. Biranın nasıl yapıldığını, hangi aşamalardan geçtiğini oldukça güzel ve keyifli bir şekilde anlatıyorlar. Turun sonunda da güzel bir bira ile yorgunluğunuzu atıyorsunuz.

BiraaaaBira ile devam edelim…Bir diğer güzel bira noktası, 2be Beerwall… Buranın yeri ve manzarası şahane…Kanalın dibinde, tam köşede…Oldukça geniş bir bira menüsüde var. Mix menü şeklinde 5 adet farklı bira alarak, bira tadımı yapmanız mümkün. Aslında Brugge’deki bir çok bira evinde bu şekilde menüler alarak farklı biraları deneme şansınız olabiliyor. Çok mantıklı ve güzel bir hareket…

Müze konusunda çok zengin bir yer değil Brugge. Ama açıkcası oldukça orijinal bir müzeye sahip, Historium… Orta çağ ortamını hissettiren, bir hikaye içinde gezdiğiniz interaktif bir müze…Brugge’ün orta çağ dönemindeki yaşantısını interaktif bir hikaye ile anlatıyor. Oldukça ilginç bir deneyimdi…Tavsiye ederim. Ve tabi ki kanal turu…Açıkcası turu yaptığınız araçlar biraz sıkışık ve kalabalık oluyor. O yüzden binerken biraz hayal kırıklığına bürünebilirsiniz. Ama tur başladıktan sonra oldukça keyifli oluyor. Yapmakta fayda var… Grote Mark ve Burg meydanı, Belfry saat kulesi, çikolata müzesi, patates müzesi falan bunlar zaten bir şekilde karşınıza çıkacak yerler. Zamanınız varsa, ayrıntılı olarak buralarıda gezebilirsiniz tabi.

Eee peki Brüksel…

Dediğim gibi tam tersi bir programla günü birlik Brüksel gezisini tercih ettik. Ve açıkcası iyi ki böyle yapmışız. Brüksel, oldukça standart ve boş bir şehir. Açıkcası pek sevmedim. Çok hazırlık yapmadan, spontene bir şekilde gitmiş olmamızdandır belki ama pek bizi cezbeden bir şey bulamadık şehirde. “Belgian Comic Strip Museum” özellikle görmek istediğim bir yer olduğu için biraz onun sayesinde, biraz da Delirium isimli bira evi sayesinde kendini kurtardı diyebilirim Brüksel. Belçika’ya gitmek gibi bir plan içindeyseniz ama, Brugge ve Ghent varken, Brüksel’i hiç düşünmeyin bile…

Evet Ghent…

GhentBrüksel dönüşü, akşama doğru Ghent yolumuzun üstü olunca bir akşamı orada geçirmeye karar verdik. Nasıl Brüksel’i beğenmediysem, tam tersi şeklinde de Ghent’i çok beğendim. Çok gezme fırsatım olamadı ama gördüğüm kadarıyla Brugge’ün devamı diyebilirim. Akşam saatleri ile havanın kararmasıyla, çok daha güzel bir hal aldı. Keyifli bir akşam yemeği ve sonrasında küçük bir tur ile ağzımız açık bir şekilde Ghent’den ayrıldık. Bir daha gidersem oralara, kesinlikle daha fazla zaman ayıracağım…Ahaaa da yazdım buraya…

Ghent

Neyse…Fazla da “spoiler” vermenin anlamı yok aslında. Çok uzun zamandır gitmek istediğim için, beklentimin yüksek olduğu bir yerdi Brugge. Kesinlikle beklentimi karşıladığını söyleyebilirim. Çok güzel ve özel bir tatildi. Şiddetle tavsiye ediyorum… Bir sonraki durakta görüşmek üzere, şimdilik benden bu kadar (:

 

 

Bir önceki yazımda .NET Core ve .NET Framework’ün arasındaki farkı ve .NET Core’un ortaya çıkışındaki amaçtan bahsetmeye çalışmıştım. Bu sefer biraz daha ayrıntılara girip, .NET Core ve hatta ASP.NET 5 ile haşır neşir olmaya başlayanların büyük bir ihtimal karşılaştığı dnvm, dnu ve dnx kavramlarından bahsetmeye çalışacağım.

net2015Yeni nesil .NET uygulamalarının çalışmaları için gerekli olan bu araçların hala gelişmekte olduğunu özellikle belirtmek isterim. Önceki isimleri ile; KLR,KVM,KRE olarak ilk başta çıktığında, tam oturmamış ve problemleri olan bu araçlar, artık biraz daha stabil ve yeni nesil .NET uygulamalarının temelini oluşturuyor. Açıkcası tamamen olgunlaştıklarında, bazı kavramların tamamen soyutlanacağını ve kolaylaşacağını düşünüyorum.

DNX

DNX, yeni nesil .NET uygulamalarının çalışmasını sağlayan “runtime” bileşeni diyebiliriz. Common Language Runtime’ı yükleyen ve onun çalışmasını sağlayan temel bileşen. Kendi içinde çalışma şekli olarak iki farklı yöntemi var. Bir tanesi .NET Core için, CoreCLR’ın çalışması için, diğeri de normal .NET Framework’ün yani .NET CLR’ın çalışması için. DNX bu iki ayrımı kendi içinte yönetip, bizden bu ayrımı soyutluyor. Kısacası yeni nesil .NET uygulamalarının kalbi.

dnx

DNVM

Yeni nesil .NET uygulamaları önceden duyurulduğu gibi artık daha yalın ve bağımsız. System.IO ve System.Console bileşenleri artık kendi versiyonları ile ayrı ayrı uygulamalarınızda çalışabiliyor. Yani System.IO’nun 1.0.0 versiyonu ile System.Console’un 2.0.0 versiyonunu, kendi uygulamamız içinde, bu ayrımı yaparak kullanabileceğiz. Bu durum, DNX içindeki bileşenlerin versiyonlarının yönetilmesi gerekliliğini ortaya çıkarıyor. .NET Version Manager(dnvm) da bu yönetimi sağlayan temel araç.

dnvmİstediğimiz DNX’i DNVM ile yükleyip, gerektiğini güncellemek bu araç ile yapabileceğimiz bir şey.

DNU

Yeni nesil .NET uygulamaları, hem geliştirme yöntemleri hem de proje şablonları açısından oldukça yalınlaşıyor. project.json isimli proje tanım dosyaları ile uygulamanızın runtime(DNX)’da nasıl çalışacağını json formatında belirtebiliyorsunuz. DNU bu aşamada bu proje dosyalarının DNX tarafından yorumlanmasını sağlıyor. Proje dosyanızda belirtilen, referansların getirilmesi, projenizin “build” edilmesini hatta projenizin nuget paketine dönüştürülmesini bu araç sağlıyor.

Bütün bu araçlar, open-source olarak GitHub’da mevcut tabii ki. Gelişme süreçlerini oradan çok yakın bir şekilde takip edip, gelişme süreçlerine dahil de olabilirsiniz.

 

Microsoft yaklaşık bir yıldır, .NET Framework’n OS X ve *Unix işletim sistemlerinde de çalışması için yoğun bir çalışma içerisinde. Takip edenler biliyordur zaten… Bu ve benzeri çalışmaları “Open Source” olarak paylaşmaya da başlayınca oldukça hızlı bir şekilde çıktılarını görmeye başladık. Build 2015 ile beraber de bunları yakın zaman da üretim ortamlarında da kullanabileceğimizi gördük.

Build 2015’in en heyecan verici gelişmelerinden biri, Microsoft’un OS X ve *Unix işletim sistemlerine vereceği desteğin geçici bir heves olmadığının altını çiziliyor olması. Gerçi CoreCLR ile bunu belirtmiş olsa da, geliştiriciler için, Visual Studio gibi, o ortamlarda da geliştirmeyi kolaylaştıracak araçlar olmadan buna inanmak çok kolay deildi. SublimeText gibi benzeri editörlerde, CoreCLR ve ASP.NET 5 alt yapılarını kullanarak, .NET uygulamaları geliştirebiliyorduk ama biraz “advanced” bir kullancı olmamız gerekiyordu.

Build 2015’de duyurulan Visual Studio Code, bu işletim sistemlerinde CoreCLR ve ASP.NET 5 uygulamaları geliştirmek için sunulan bir “text-editor”. Burada önemli nokta bir “IDE”, yani tam bir geliştirme ortamı olmaması. Yani kısaca Visual Studio Code bir IDE değil, bir text-editor. Electron alt yapısı kullanılarak geliştirilmesi bunun asıl sebebi. Github’un geliştirdiği Atom Text editörünün de temelinde bulunan Electron(a.k.a Atom Shell) node,js, HTML, CSS, javascript gibi alt yaplar ile cross-platform uygulamalar geliştirmenizi sağlıyor. Visual Studio Code’da bu alt yapı üzerinde geliştirilmiş bir uygulama.

Visual Studio Code’un dnvm ve dnx ile beraber gelmiyor ne yazık ki. Onları kendiniz kurmamız gerekiyor. Bunun için Visual Studio Code dokumantasyon sayfasına bakmanızı şiddetle öneririm. Açıkcası ilk duyurulduğu zaman bunların da kurulumu uygulama ile beraber oluyor diye düşünmüştüm. Şu an için bütün bunların Preview seviyesinde olduğunu düşünürsek aslında normal. İlerleyen versiyonlarda büyük ihtimal dnvm, dnx falan Visual Studio Code ile entegre gelecektir diye düşünüyorum.

Hızlı hızlı bir göz atalım…

Öncelikle text-editor olduğu için, sadece .NET uygulamalar değil, her türlü text tabanlı kodu da yazmanı mümkün.

Visual Studio CodeCoreCLR ve ASP.NET 5 ile hayatımıza giren klasör bazlı proje şablonları Visual Studio Code’daki proje kavramının temelini oluşturuyor. project.json ile projemizin tüm içeriğini ve özelliklerini Visual Studio Code ile kolaylıkla düzenleyebiliyoruz. Direk bu adımdan başlayan IntelliSense, alışık olmayanlara karmaşık gelebilecek bu yapıyı oldukça kolaylaştırıyor.

Visual Studio CodeOluşturduğumuz *.cs dosyları için de ayn ekilde IntelliSense tabi ki mümkün. IntelliSense ile beraber, temel code-snippet’lar da mevcut. cw yazınca Console.WriteLine() oluşması falan gibi.

Visual Studio CodeYazdığımız kodların oluşturduğu hata ve uyarları da yine oldukça kolay bir şekilde görebiliyoruz. Text-editor’un sol alt köşesinde belirdiği gibi onlara tıkladığımızda da ilgili hatalar olduka kolay bir şekilde karşımıza çıkıyor.

Visual Studio Code

Visual Studio Code ile Debug yapmak da mümkün. Sol taraftaki en altta bulunan böcük ikonuna bastığımızda Debug ile ilgili ön yüze ulaşabiliyor ve Debug’ı çalıştırabiliyorsunuz. Ama ne yazık ki OS X ve *Unix olan versiyonda şu an için CoreCLR ve ASP.NET 5 uygulamalarını Debug edemiyoruz. Şu an sadece mono ve node uygulamalarını Debug yapabiliyorsunuz. Haa evet, bu arada node uygulamalarını debug edebiliyoruz. :) CoreCLR ve ASP.NET 5 uygulamalarını Windows versiyonunda ise Debug edebiliyoruz.

Visual Studio Code
Uygulamaları çalıştırmak için dnx komutlarından faydalanıyoruz. Bunun için Command Pallette(F1) yardımıyla istediğimiz komutları çalıştırabiliriz. Atom editörüne aşina olanlar ya da SublimeText kullananlar kolaylıkla adapte olacaktır.

Visual Studio CodeVisual Studio Code’da aynı zamanda GitHub desteği de var, sanırım artık GitHub desteği olmayan geliştirme yapabilecek araç yok :) GitHub ile çalışanlar için olduka cezbedici sanırım.

Visual Studio Code’u hemen https://code.visualstudio.com/ adresinden indirebilir ve deneyebilirsiniz. Merak uyandıran bu kısa giriş yazısı ile umarım ilginizi çekmeyi başarmışımdır. Dediğim gibi şimdilik Preview aşamasında olduğu için bir çok eksiği var ama kesinlikle denemeye değer.

Son olarak aşağıdaki kısa videoya da bir göz atın derim.

Kim kurgulayıp, yaptıysa ayağa kalkıp, önümü ilikleyip öyle alkışladım. Keyifli bir video olmuş…

Yakın zamanda Devnot‘a yazdığım TDD (Test-Driven Development) Yapmak Gerçekten Zor Mu? yazısının devamı niteliğinde biraz daha kod örnekleri ile bu sormuş olduğum sorunun cevabını vermeye çalışacağım. Basit bir senaryo üzerinden, yine basit bir kod yazarak; hani kod yazmadan, nasıl testi yazılır problemi var ya, bunu anlamaya bir yandan da anlatmaya çalışacağım…

Belli bir miktarda paranın aylık faiz miktarını hesaplamamız gerekiyor. Ana para 10.000’den büyük olursa faiz oranı maksimum % 3, 10.000’den küçük olursa da maksimum %1.5 olacak şekilde hesaplanmalıdır. Sadece aylık zaman dilimine göre hesaplanmalı ve bu zaman 1 yılı geçmemeli.

Ekonomiye can katacak bu çok basit müşteri talebi ya da analiz çakması ihtiyacımız; işte artık nasıl yorumlarsanız, uygulamamızın ilk hali aslında. Böyle uzun uzadıya tasarım yapabileceğimiz bir örnek olmasa da kabaca nasıl yaparız bunu düşünelim önce.

Öncelike bir tane FinancialManager diye bir sınıfımız olsun mesela. Bu ana paramızı emanet ettiğimiz sınıf…SetCapital metotu ile ana paramızı belirtelim. Bu sınıf üzerinden faiz oranını tanımlayabilelim, SetInterestRate mesela. İstersek değiştirebilelim. Aynı şekilde SetPeriod ile aylık zamanı da belirtip, değiştirelim. Bütün bu tanımlamalara, FinancialManager sınıfının özelliklerinden ulaşabilelim. Ana para(Capital), faiz oranı(InterestRate), aylık zaman(Period) falan…Bütün bu özellikler belirtildiği zamanda CalculateInterest ile faiz miktarını hesaplayabilelim.

Sınıf, metot, özellik falan…Biraz daha koda yaklaştık. Teknik olarak biraz daha anlaşılır oldu sanki. Bu aşamadan sonra kodu yazmak biraz daha kolay, hatta direkt yazalım…Test etmeye ne gerek var?

Dııttt yanlış….

Teknik olarak, ne yapacağımızı oluştursak da, kodu yazarken hata yapma oranımız çok yüksek. Çünkü parametrelerimiz değişken, dikkat etmemiz gereken ve sağlamamız gereken belli şartlar var falan filan… Bu hatalar kod gelişmeye başladıkça karşımıza zaten çıkacak. Baştan farkında olup, kod geliştikçe ortadan kalkacak şekilde düşünürsek ama, daha sağlıklı bir kodumuz olacaktır. O yüzden hadi test yazalım…

Bu örneği Visual Studio’nun test proje şablonunu kullanarak yapacağım. Farklı proje şablonları ya da test framework’leri de kullanabilirsiniz tabi. Birim testi için bir sürü framework var. Farklılıkları olsa da hepsinin ortak noktası daha çok. O yüzden araçtan çok, konsepte odaklanmak bu aşamada daha doğru olacaktır.

TestÖncelikle bir tane Unit Test, bir tane de Class Library şablonundan iki proje oluşturalım. FinanceApp olsun bir tanesi, bunun test projesi de FinanceApp.Test olsun. FinanceApp’in içerisinde de hiç bir sınıf falan olmasın…Silelim, şablonla gelen Class1’i…Gerek yok.

Bizim şimdilik işimiz FinanceApp.Test projesi… O yüzden UnitTest.cs dosyasını açalım. Fark etmiş olduğunuz gibi içinde boş bir tane test metodu olan, test sınıfımız bu dosyanın içinde.

namespace FinanceApp.Test
{
    [TestClass]
    public class UnitTest
    {
        [TestMethod]
        public void TestMethod1()
        {


        }
    }
}

İlk testimizi de, bu TestMethod1’in ismini Test_SetCapital şeklinde değiştirerek içine yazalım…

namespace FinanceApp.Test
{
    [TestClass]
    public class UnitTest
    {
        [TestMethod]
        public void Test_SetCapital()
        {
            FinancialManager manager = new FinancialManager();
            manager.SetCapital(100.0);

            double expected = 100.0;
            double actual = manager.Capital;

            Assert.AreEqual(expected, actual);

        }
    }
}

Yukarıda özetlediğim gibi, basitçe test kodunu yazmaya çalıştım. FinancialManager diye bir sınıf olduğunu farz edip, bundan bir nesne yarattım. SetCapital() metodu ile de ana paramı tanımladım. Daha sonra expected ve actual değerlerini, karşılaştırıyorum. Bu iki değer bir biri ile aynı olursa testimiz başarılı sonuçlanmış demektir.

Test_1

 

Devam

MEF(Managed Extensibility Framework) ile ilgili geçenlerde küçük bir soru ile karşılaştım. Burada da bahsetmek isterim. Ama önce MEF nedir, ne değildir hatırlamak isteyenlere önceki yazılara bir göz atmalarını tavsiye ederim…

  1. MEF ile esneklik kazanıyoruz…
  2. MEF’de “Part”lara kendi “metadata” bilgilerimizi nasıl ekleriz acaba?
  3. MEF’i basit bir WPF uygulaması ile daha iyi anlıyoruz…
  4. Managed Extensibility Framework(MEF)’de ki kataloglar…
  5. Asp.Net MVC Framework’de MEF ile Controller eklentileri…

Neyse gelelim, soruya… MEF alt yapısını kullanarak, uygulamalarızı genişletirken, “Part”ları [Export] özelliğini kullanarak belirtiyoruz. MEF’in olmazsa olmaz, en önemli özelliği aslında. Bununla ilgili olarak,  “Her geliştirilen “Part” bu şekilde [Export] özelliğine sahip olmalı mı,tek bir ortak yapı ile olmaz mı?” manasında bir soruydu gelen. Hemen bakalım…

MEF alt yapısı ile uygulamalarımızı genişletmek için kullandığımız parçaları mutlaka tanımlamamız lazım. MEF’deki kataloglar ve konteynırlar bu tanımlamalara göre oluşturduğumuz parçaları yaratıyor ve ayağa kalkmasını sağlıyor. Bildiğiniz üzere de [Export] bunu sağlayan özellik. Ama her parçaya bunu yazmak pek tercih edilen bir yöntem olmayabilir. Bu da aslında temel olarak iki sebepten olabilir. Bir tanesi MEF alt yapısını dışarısı ile paylaşmak istememek, bir diğeri de tüm koduna müdahele edemediğimiz uygulamaları genişletme ihtiyacı…

Öncelikle normalde nasıl yaptımızı hatırlayalım. Aşağıdaki kod örneği sanırım bunun için yeterli olacaktır.


    public interface IPlugin
    {
        void Execute();
    }

    [Export(typeof(IPlugin))]
    public class PluginA : IPlugin
    {

        public void Execute()
        {
            throw new NotImplementedException();
        }
    }

    [Export(typeof(IPlugin))]
    public class PluginB : IPlugin
    {

        public void Execute()
        {
            throw new NotImplementedException();
        }
    }

Burada her IPlugin arayüzünden geliştirilen, “Part”a, [Export] özelliğini yazmak yerine, BasePlugin şeklinde bir temel sınıf olup, “Part”ların o sınıftan türemesi istenebilir. Böylece “PlugX” şeklinde geliştirilen her sınıf, hem belli standart özellikleri sağlıyor olur, hem de [Export] özelliği o sınıf tarafından yönetilebilir. Ayrıca tüm koduna müdahele edemediğimiz, ama belli bir sınıftan türeyen sınıfların, MEF Part’ları olarak yorumlanmasını da istersek, bu belli sınıfa sadece bir özellik ekleyerek, yazılımcıdan “Part” kavramını soyutlayabiliriz.

MEF’de bunun için [InheritedExport] özelliği sunuyor.  Sadece bir sınıf ya da arayüze [InheritedExport] özelliği eklemek, bunlardan türetilen tüm sınıfların “Part” olarak yorumlanmasını sağlayacaktır. Bu sayede Export özelliği tek bir yerden yönetmek mümkün olacaktır.


    [InheritedExport(typeof(IPlugin))]
    public abstract class BasePlugin : IPlugin
    {

        public void Execute()
        {
            Process();
        }

        public abstract void Process();
    }

    public class PluginA : BasePlugin
    {

        public override void Process()
        {
            throw new NotImplementedException();
        }
    }

    public class PluginB : BasePlugin
    {

        public override void Process()
        {
            throw new NotImplementedException();
        }
    }

Bu basit ama bir o kadar da anlamlı özellik, kodun kirlenmesinin de önüne geçiyor diye düşünüyorum. MEF ile çalışmayı düşünen ya da çalışanlar için umarım faydalı olur.