| « Bu siteye erişim mahkeme kararıyla engellenmiştir | ÜRÜN GELİŞTİRME UZMANI » |
kod kalitesi üzerine
Bir yazılımın kalitesini ölçerken hafıza kullanımı, performans, stabil kalma, hata adedi, yazılımcı "din"i inançlarına uygunluk vs gibi ölçekler kullanırsınız peki karşınızda duran kod dosyası için kaliteyi nasıl ölçersiniz?
Bakalım;
- Satır adedi?
- Hız?
- Okunabilirlik?
- Notlar (Comments)?
- Hata kontrolleri ?
Siz bu listeye istediğiniz kadar aklınıza gelenleri ekleyebilirsiniz ve hepsi pasta'nın bir dilim'ini paylaşır. Bazılarından ödün verip diğerini yükseltebilirsiniz ancak hangi dilimlerin daha çok yer kaplayacağı asıl sorundur.
Satır Adedi
Bazı yazılımcılar (-ki buna kendimi tutamayıp bende dahil oluyorum) ürettikleri yazılımın satır adedi ile övünürler. Aslında satır adedinin yüksek olması her zaman (ama her zaman) kötüdür. Satır adedinin artması yazılımın karmaşıklaşması, bakımının zorlaşması, hatalı/kötü/bilmeden bir "reuse" yada varsa object oriented kullanımının işaretidir.
Aynı işi yapan 2 yazılım için satır adedi daha düşük olan'ın yönetimi her zaman için daha kolaydır. Herhangi bir hata olması durumunda neden'i bulmanız her zaman daha kısa sürecektir. Bu yüzden mümkün olduğu kadar satır adedini az tutmak gerekli.
Satır adedi daha çok projenin boyutu ile ilgili bir ölçektir. Fazlası her zaman kötüdür.
Gerekmediği sürece yeni bir satır eklememek ilerideki saçlarınızın yerinde ve koyu renkte kalmasına yardımcı olur.
Hız
Hızlı çalışan bir yazılım her zaman için tercih edilir ancak bu konuda 2 kez düşünmek gerekli.
Okunabilirliği yüksek ama yavaş çalışan bir kodu, bakınca kimsenin hiç bir şey anlamadığı ama hızlı çalışan bir kod'a çoğu zaman tercih etmeniz gerekir.
Neden?
Eğer tek başına bir yazılım geliştiriyorsanız bu çoğu zaman sizin için bir sorun yaratmaz ama bir ekip ile çalışıyorsanız ekip'deki herkesin sizin becerilerinize sahip olması gibi bir imkanınız olmayacaktır.
Yazılımın içinde bu hızlı çalışan ama dokunulamayan kısımları bıraktığınız her parça dönüp dolaşıp size gelecektir.
Yıllar önce yazdığım (-ki şu an ne iş yaptığını bilsem de nasıl yaptığı konusunda en ufak bir fikrim olmayan) bir kod örneği vereyim;
Code:
void putpixel16(int x,int y,unsigned char * segment) | |
{ | |
register unsigned char * vidmem; | |
register unsigned short int packed; | |
| |
vidmem = (unsigned char * ) (segment + ( y * SCREEN_WIDTH + x ) * SCREEN_BYTEPERPIXEL); | |
| |
_asm { mov eax,vidmem } | |
_asm { mov edi,eax } | |
_asm { mov al,ColR } | |
_asm { and al,0f8h } | |
_asm { mov bl,ColG } | |
_asm { and bl,11100000b } | |
_asm { shr bl,5 } | |
_asm { or al,bl } | |
_asm { stosb } | |
_asm { mov bl,ColG } | |
_asm { and bl,1ch } | |
_asm { shl bl,3 } | |
_asm { mov al,ColB } | |
_asm { shr al,3 } | |
_asm { or al,bl } | |
_asm { stosb } | |
} |
ve aynı kodun daha anlaşılabilir hali;
Code:
void putpixel16(dword x,dword y,unsigned char * segment) | |
{ | |
register unsigned short int *vidmem; | |
register unsigned short int packed; | |
| |
vidmem = (unsigned short int * ) (segment + ( y * SCREEN_WIDTH + x ) * SCREEN_BYTEPERPIXEL ); | |
| |
packed = (ColR << 11) | (ColG << 6) | ColB; | |
| |
* vidmem = packed; | |
} |
Bu örnekle putpixel'i (ölümcül doğası itibariyle) c ile yazın demiyorum, sadece örnektir
Eğer ölümcül değil ise her zaman okunabilir olanı tercih etmek, sabahları işe gittiğinizde yüzlerce sorun yerine internetten haber sitelerini gezmenize yardımcı olacaktır.
Okunabilirlik
Bir kod parçasınının okunabilirliği üzerine yüzlerce şey anlatabilirsiniz ancak en iyisi örnek;
Code:
for (int i = 1; i < num; ++i) { meetsCriteria[i] = true; } | |
for (int i = 2; i < num / 2; ++i) { | |
int j = i + i; | |
while (j <= num) { meetsCriteria[j] = false; j += i; } | |
} | |
for (int i = 0; i < num; ++i) { | |
if (meetsCriteria[i]) { Console.WriteLine(i + " meets criteria"); } | |
} |
Bu örnekde tek bakışta işlemlerin nasıl ilerlerdiğini anlamak zor. İşleyişi çözmek için kod üzerinden fazladan 3-5 sn daha geçirmeniz gerekli, bunun yerine aşağıdaki gibi bir düzen daha iyi olacaktır. Okurken gözlerin kamaştığı bir düzen yerine;
Code:
for (int i = 1; i < num; ++i) | |
{ | |
meetsCriteria[i] = true; | |
} | |
| |
for (int i = 2; i < num / 2; ++i) | |
{ | |
int j = i + i; | |
| |
while (j <= num) | |
{ | |
meetsCriteria[j] = false; | |
| |
j += i; | |
} | |
} | |
| |
for (int i = 0; i < num; ++i) | |
{ | |
if (meetsCriteria[i]) | |
{ | |
Console.WriteLine(i + " meets criteria"); | |
} | |
} |
tercih etmeniz her zaman için başkaları ve bir zaman sonra sizin için sağlıklı olandır.
Buna göre her "statement" olarak geçecek bloğu "{" , "}" arasına alabilirsiniz.
Mantıksal olarak ayrı iş yapılan yerlerde boş bir satır bırakabilirsiniz.
Akışı göstermek için indent verebilirsiniz. Ident'ler için her editör/programcı farklı boşluk seviyesi (2,4,8..) kullandığı için editörü Tab karakteri yerine boşluk koymak üzere ayarlarsanız başka birisi baktığında da aynı düzeni görür.
Notlar
Kod içinde yazılan notlar için kötü örneklerde bazen hiç not olmaz yada yazan kişi her satırın ne olduğuna dair kendince açıklamalar yapar. Bu konuda iyileştirme yapmak istiyorsanız her zaman için yazdığınız kodun ne yaptığı yerinde neden bu şekilde olduğuna dair notlar düşün.
Bu mantıkla baktığınızda her satırda açıklama yapmak yada not yazma zahmetini en aza indirmiş olursunuz.
Hata kontrolleri
Bu konu yeni öğrenen yazılımcılar için belkide en çok hata yapılan konu. Bu yüzden biraz daha detay vermeye çalışıyorum. .Net için konuşuyorsak "hata" olarak konuşulan başlık "exception" olarak geçer. .Net dünyasında kontrolü yapılmamış her exception için Windows'un mavi ekranları olarak algılanabilir ve Windows tabanlı uygulamalar için;

yada ASP.Net için

İyi yazılmış bir .Net uygulaması için asla ama asla bu tip ekranları görmemeniz gereklidir. Bunun anlamı hata kontrolleri yeterince yapılan bir uygulamada exception oluşması gereklidir. Exception'ın Türkçe anlamıda zaten "kural dışı durum" olarak geçer.
.Net dünyasında exceptionlar tepeden baktığınız durumda 2 kategoriye ayrılır. Çalıştırma (Execution) hataları yada bug'dan kaynaklanan hatalar.
Örneğin NullReference, InvalidOperation, ArgumentNull gibi hatalar uygulama genellikle bir bug olduğunu gösterir. Bu tür hataları azaltmak için yapabileceğiniz en iyi çözüm parametre alan methodlarda gerekli kontrolleri yapmaktır. Örneğin;
Code:
void Save(Order order) | |
{ | |
Database.SaveObject(order.Customer); | |
Database.SaveObject(order.Order); | |
} |
Gibi bir method içerisinde parametre olarak gönderilen Order tipi objenin null olup olmadığı kontrolü yapılmıyor. Uygulama içerisindeki bir hata yüzünden null parametre gönderildiğinde size bu NullReference exception olarak gözükecektir. Bunun yerine;
Code:
void Save(Order order) | |
{ | |
if (order == null) | |
throw new ArgumentNullException("order"); | |
| |
Database.SaveObject(order.Customer); | |
Database.SaveObject(order.Order); | |
} |
şeklindeki bir kontrol olası hataları daha erken bulmanızı sağlar.
Execution hatalarına örnek olarakda FileNotFound, SerializationException gibi hatalar olabilir. Bu tür hatalarda genellikle yeterince kontrol yapılmadan işlem yapıldığında ortaya çıkar. Örneğin dosyanın varlığını kontrol etmeden dosyayı açmak gibi. Yapılması gereken dosyanın var olup olmadığını kontrol ederek kullanıcının anlayacağı bir mesaj vermek en doğrusudur.
Execution hatalarında elbetteki olası tüm kontrolleri yapmanız mümkün değil ancak sık olabilecek hataları önceden kontrol etmeniz yeterlidir. Bunun dışındaki hatalar için standart exception dialoglarını kendinize özgü hata ekranları ile değiştirmeniz her zaman için iyi bir fikirdir. Böylece handle etmediğiniz bir hata olduğunda uygulamanın size mail atabilmesi, hata log'larına kayıt gibi fantastik imkanlarınız olabilir.
Standart exception dialoglarını değiştirmek için AppDomain.CurrentDomain.UnhandledException event'ini kullanabilirsiniz. Handle edilmeyen herhangi bir exception oluştuğunda bu event tetiklenir. Örnek olarak buradaki adresde bazı bilgiler bulabilirsiniz.