Category Archives: software engineering
Hiding vs Overriding
Geçen gün ofiste, aramızda yaptığımız teknik bir konuşmada Method Hiding ile Method Overriding arasında ne fark olduğu gündeme geldi. Zaman geçmiş herhalde pek hatırlayan olmadı. Ama içimizden de şöyle geçiyor; “bi farkı var ki Microsoft koymuş bunları” diye.
Şöyle bir onbeş dakikalık araştırma sonucunda hatırlayıverdik. Efendim şöyle:
Bilindiği gibi polymorphism diye birşey var oop de. Yani nesnelere “… gibi davranma” özelliği verebilme. Klasik oop örnekleri ile örneklemek istersek:
İki tane sınıfımız olsun, biri diğerinden türesin;
class Animal { public virtual void Walk() { Console.WriteLine("Animal is walking."); } } class Cat : Animal { public override void Walk() { Console.WriteLine("Cat is walking."); } }
Ve şimdi bu sınıflarımızı kullanalım:
static void Main(string[] args) { Animal animal = new Cat(); animal.Walk(); }
Alacağımız çıktı şöyle olacak tahmin ettiğiniz gibi:
Cat is walking.
Şimdi override edeceğimize methodu hide edelim bakalım dünyada neler değişiyor:
class Cat : Animal { public new void Walk() { Console.WriteLine("Cat is walking."); } }
Şimdiki çıktımız ise şöyle oluyor:
Animal is walking.
Soru : Neden?
Şöyle özetleyebiliriz; methodu override ettiğimiz zaman framework Animal tipinde (Cat tipinde değil) bir nesnenin Walk methodunu çağırırken, içindeki bir tablodan (tablo olduğunu düşünelim basitçe) bu method, bu nesnenin sınıfı tarafından override edilmiş mi diye bakar. Eğer override edilmiş ise Animal sınıfının Walk methodu yerine o methodu çalıştırır.
Eğer override edilmeyip hide edilmişse, o zaman o tabloda bu kayıt bulunmaz ve Animal sınıfının Walk methodunu çağırır. Sizin nesneniz aslında Cat sınıfının bir nesnesidir ancak Walk methodu Animal sınıfının Walk methodu oluverir.
Soru : Peki niye böyle birşey yapalım? Yani niye methodu hide edelim?
Bu sorunun cevabına geçmeden statik tip ve dinamik tip ayrımını bilmek gerekiyor. Şuradan bir göz atabilirsiniz.
OOP kurallarına ters bir durum olduğu malum. Ancak diyelim ki şöyle elzem bir durum söz konusu:
Benim nesnemin statik tipi Cat olacaksa Cat sınıfına yazılan Walk methodu, yok eğer statik tipi Animal olacaksa yani Cat nesnesi Animal gibi davranacaksa Animal sınıfındaki Walk methodu çalıştırılsın.
İşte böyle bir isteğimiz olursa -ki benim şimdiye kadar olmadı- method hiding burada yardımınıza yetişir.
VS Test Method Snippet
Test driven geliştirme yapmak, eğlenceli olduğu kadar uzun süren bi işlemdir malumunuz. Bu konu ile ilgili bir yazım olacaktı.
Önce test yazacaksınız, sonra testi geçirecek kodu yazacaksınız. Başka bir test yazıp asıl işi yapacak kodu yazmaya zorlarsınız kedinizi. Sonra duplicationları gidermek için refactor edersiniz. Bunları yaparken naming convention a dikkat edersiniz.
Derken ne oldu? Hepi topu 3 ile 5 i toplayıp 8 döndüren bir method yazdınız daha. Bu methodu yazabilmek için en az 4 test yazmış olmamız lazım. Yani sadece basit bir method için 4 test yazıyoruz ki, büyükçe bir projede bu sayı nerelere çıkar varın siz düşünün.
TDD yazıyorsak en çok yazılan şey doğal olarak testtir. Farkettim ki bizim Visual Studio içinde bu durumla ilgili bir snippet yok. Ben her test için şunu kendim yazmak zorundayım:
[Test] public void TestMethodTest() { Assert.Fail("Not implemented yet!"); }
Halbuki bir code snippet olsa ve biz 1-2 tuş ile bunu şak diye yazmış sayılsak diye düşünerek bir snippet yazdım. İtiraf etmeliyim ki “prop” snippettını referans alarak yazdım.
İndirmek isterseniz buyrun.
Bu dosyayı “My Documents\Visual Studio 2008\Code Snippets\Visual C#\[İstediğiniz bir folder]\” altına atabilirisiz.
Basit Tasarım
Yaklaşık 9 ay kadar önce Yenibiris.com’dan 3 arkadaş TDD eğitimi almıştık. Eğitimi artık bu alanda guru sayılan J.B.Rainsberger’den (Joe) aldık. Kendisi Kanada’lı bir yazılım geliştirme danışmanı. Yani şirketlerin yazılım geliştirme ekibine “O şöyle bir sorun yaratır, şu patterni kullan”, “Daha önce falanca yerde böyle birşey olmuştu, şöyle çözdük” gibi ahkamlar kesen bir insan.
Meslek, ilk bakışta “ukalalık”, “kendini beğenmişlik”, vs gibi düşünülse de böyle olmadığı açık. Ama bu düşünce yüzünden böyle bir meslek Türkiye’de yok. Zaten sektörün hali ortada. Bu konuyu geçelim. Gelelim konu başlığımıza.
Efendim eğitimin başlamasını müteakip Joe bize ilk şu listeyi yazdı:
Simple Design
- Passes tests
- Minimize duplication
- Maximize clarity
- Reduces size
- One thing at a time
Bu 5 madde uygulanırsa sonuç : Modüler tasarım.
Maddelere gelirsek:
- Passes test : TDD de testlerin geçmesi zaten işin temeli. Tasarımın %85 ini oluşturur ve Joe’ya göre (katılmamak elde değil) zamanla otonomik bir hale dönüşüyor. Yani, nasıl yürürken hangi ayağımızı ne zaman öne atacağımızı düşünmeden hareket edip kendi haline bırakıyorsak, zamanla yazılan testlerin geçmesini sağlamak ta aynı şekilde kendi haline bırakılır.
- Minimize duplication : Daha önce yazdığım Bu kod kokuyor isimli makalede bahsi geçmişti. Aynı kod projenizde birden çok kez geçiyorsa ki bu zaman zaman olur. Bunları refactor edip minimize etmeliyiz.
- Maximize clarity : Kodumuzda anlamsız değişkenler, açıklayıcı olmayan class ya da method isimleri bulunmamalı. Asla ve asla kodumuza comment yazmamalıyız. Comment yazılmış kod, açıklayıcı değildir. Kodumuzu öyle bir yazmalıyız ki commente ihtiyaç duymadan kod kendini anlatabilmeli.
- Reduce size : Bu madde 5 i içindeki en önemsiz. Ama aklımızın bir köşesinde bulunmalı. Ne kadar çok kod yazarsak maintenance yapılacak o kadar çok satır olacak demektir. Kodumuzu mümkün olduğunca kısa tutmakta fayda. Tabi bunu yaparken dozu iyi ayarlamalı, şokunu çıkarmamalıyız.
- One thing at a time : İşte bu 5 maddenin en zoru. Aslında olay şu. Her seferinde tek bir şey yapmalıyız. İhtiyacımız oldukça kod yazmalıyız. Aksi takdirde YAGNI olacaktır.
Tecrübeli fakat TDD kullanmayan yazılımcıların bu 5 maddede en çok sonuncusunda zorlandığını öğrendik Joe’dan (Eğitimdeki örneklemelerde bizzat ben) . Sebebi de yıllarca kompleks yapılar tasarlamışlar, Presentation Layer a bi textbox koymak için; bir yandan BL yazarken, diğer yandan DAL yazarak projeler geliştirmişler. Şimdi adama diyorsun ki “dur bakalım. önce falanca classın bilmemne fonksiyonunu yaz. Database ile ilgimiz yok!!!”
E doğal olarak, eğer gelişimden hoşlanmayan bir insansa, “uğraşamam ben bununla” diyerek kestirip atabiliyor.
TDD development aşaması uzun ve keyifli, maintenance ve bugfixing aşaması ise hemen hemen hiç yok diyebileceğim kadar kısa ve zahmetsiz oluyor. Bunu ekip olarak, son yazdığımız servisleri TDD ile yazarak yaşadık.
TDD yi seviyoruz.
Bu Kod Kokuyor
Bazen kendi yazdığımız ya da başkasının yazdığı kodu incelerken “bu işte bir terslik var” dediğimiz olur. En azından benim olur. O terslik nedir, o sırada bilmem ama vardır. Bunu hissederim.
İşte buna “Code Smell” diyoruz. Yani kokan kod.
Örnek 1:
return AllItems.Where(a => a.ArticleTypeID = 1);
İşte böyle bir kod gördüğümde ben biraz işkilleniyorum. Orada kendi kendine durmakta olan “1” beni rahatsız ediyor. Acaba o “1” ne anlama gelmekte? “1” yerine “2” dersem ne olur? Oraya yazılacak sayının bir üst limiti var mıdır acaba? Ve eğer düzeltilmezse her bu kodu gördüğümde zincirleme olarak bu sorular aklıma tekrar tekrar gelecektir. Kısacası bu kod “kokmaktadır”.
Kodu kokutan maddeleri şöyle sıralayabiliriz:
- Çoğaltılmış (duplicate) kod : Eğer birebir aynı şeyi yapan kod, projenizde birden çok defa geçiyorsa, kodunuz kokmaya başlamıştır.
- Çoğaltılmış Fonksiyon : Birbirlerine çok benzeyen, hatta aynı işi yapan birden fazla fonksiyonlarınız olabilir. Overload etmeyi denemelisiniz.
- Fazla uzun fonksyion : Code Complete der ki; “Eğer bir method 35 satırdan uzun sürüyorsa, methodu parçalara ayırmayı düşünmelisiniz”. Fazla uzun fonksiyonlar kodu kokutmak için birebirdir.
- Fazla uzun class : Yine Code Complete buyurmuştur ki; “Eğer bir class, 350 satırdan uzunsa, classı parçalamayı düşünmelisiniz.”
- Başka sınıfın işini yapmaya çalışan sınıf : Eğer yazdığınız bir class, başka bir class ın methodlarını çok sık kullanmaya başladıysa, belkide iki classı birlikte düşünmelisiniz.
- Başka sınıfın işine karışan sınıf : Eğer yazılmış bir class başka bir classın işine karışmaya başlamışsa. Kendisini ilgilendirmeyen işler yapmaya kalkıyorsa, kodunuz kokuyor dikkat!!!
- Türediği sınıftan gelen mirasları reddeden sınıf : Meşhur Canlı –> Hayvan örneğinde Hayvan, Canlı’dan gelen “NefesAl” methodunu override ediyor ve en sonunda “base.NefesAl();” demiyorsa dikkat etmek gerek. Canlı’nın ne yaptığını bilmeden bunu yapmamakta fayda var.
- Tembel Sınıf : Malumunuz çok az kullanılan sınıf. Az kullanıldığı için ya hiç sorun çıkarmaz, ya da çıkardığında sorunun nereden geldiğinin anlaşılması zor olabilir.
- Gereksiz kompleks yapı : Alt tarafı bir formdaki verileri database e kayıt edecek bir yapı için bşn satır kod, onlarca sınıf, vs yazarak pireyi deve yapmışsanız kodunuz kokuyordur.
Yukarıdaki liste Wikipedia’dan alınmıştır.
Bu örnekler çoğaltılabilir. Peki tek satırlık örneğimizde (Örnek 1) burnuma gelen kokunun sebebi nedir sizce? Elbette ki “1” in ne olduğunu anlamamam. Buradaki “1” e Magic Number diyoruz. Kodlarımızın içerisinde Magic Number bulunması kokuya sebep olur. Peki bu kokudan nasıl kurtuluruz. Hemen imdadımıza sabitlerimiz yani Constant larımız yetişiyor.
Örneğimizi şöyle değiştirirsek:
Örnek 2:
const int STANDART_ARTICLE_TYPEID = 1; return AllItems.Where(a => a.ArticleTypeID = STANDART_ARTICLE_TYPEID);
Böylece, bileceğim ki benim kodumun sonucunda her zaman “Standart Makale” tipindeki makaleler döner. Her bu kodu gördüğümde de bundan böyle “1” in ne olduğunu hatırlamak zorunda kalmayacağım.

