Merhaba ,
Bu yazıda kodlama alışkanlıklarımızı gözden geçirmemize sebep olabilecek bazı detaylardan bahsedeceğim. Yazılımcı olarak bir projeye sıfırdan başlar veya T anında dahil oluruz. Proje büyüdükçe birbirini takip eden iş kuralları da büyür ve iç içe girmeye başlar. Hatta bazı iş kurallarına analizde değil direk kodlamada karşılaşırız. Bahsettiğim bu son durum bütünün farklı sorunları olarak ele alınsa da gelmek istediğim noktada, kod yazarken meslektaşlarımıza ipuçları bırakmanın öneminden açık ve temiz kod yazmanın faydalarından bahsediyor olacağım. Bu yazıdaki örnekleri incelerken refactoring esnasında Temiz Kod ( Clean Code ) prensiplerinden faydalanıp sadeleştirdiğiniz kod bloklarını yorumlarda paylaşabilirsiniz 🙂
Her boş insan bilgisayarın anlayabileceği kodu yazar.Sadece iyi yazılımcılar insanların anlayabileceği kodu yazar.
Martin Fowler
Temiz Kod ( Clean Code ) refactoring ‘e başlamadan genel hatlarıyla üç prensip üzerinde durmalıyız.
- Doğru Araç kullanımı
- Yazılım geliştirdiğimiz IDE, Framework , Paket , güncel teknolojilerden faydalanmak
- Kötü Gürültü sinyallerinin azaltılması
- Aracınızda yolda giderken radyoda çalan şarkıya eşlik ediyorsunuz. Araç dağlık bir bölgeden geçerken radyodan gelen cızırtılı ses’in hissettirdikleri bu madde olmalı 🙂
- Dökümantasyon
- Bilge bir programcı şöyle diyor , Kod level dökümantasyon için comment kullanmaya gerek yok, doğru yazılmış kod yeterli.
Boolean Karşılaştırmalar
Bool değişkenlerin karşılaştırılmasında sadelik ve okunablirlik ön planda olmalıdır.İki ifadeyi de okuyacak olursa , İlk İfadmizde “Eğer done == true” ise ikincide ifademizde “Eğer done” ise şeklinde okuyoruz. O halde en kısa şekilde ifade etmeliyiz.
1 2 3 4 5 |
if(done == true) |
1 2 3 4 5 |
if(done) |
Boolean Değer Atamaları
Clean Code prensibinde ” Increase signal to noise ratio ” bloklarını azaltmamız gerekiyor.
İlk kod bloguna baktığımızda true ve false değerleri göze çarpıyor hemen ardından hasQualifyCampaign değişkeni için iki farklı şart olmalı diye kodu okumaya devam ediyoruz. True ve false değerlerini sinyal olarak ele alırsak hasQualifyCampaign için iki adet sinyal gözden geçiriliyor.
İkinici kod bloğunda durumun böyle olmadığı ve tek sinyal algıladığımızı fark etmişsinizdir. Okunaklı olması da tercih sebeplerini arttırıyor.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
bool hasQualifyCampaign; if(totalWeeklySpend > 500) { hasQualifyCampaign = true; } else { hasQualifyCampaign = false; } |
1 2 3 4 5 |
bool hasQualifyCampaign = totalWeeklySpend > 500; |
Pozitif Ol
Pozitif ifadeleri anlamak, işlemek ve yönetmek negatiflere göre çok daha basit ve işlevseldir.
Aşağıdaki örnekleri inceleyip negatif isimlendirilmiş değişkenler veya negatif bir sonuçtan pozitif çıkarım elde edilmiş değişkenlerde nasıl zorlandığınızı fark edeceksiniz. Pozitif olmak iyidir : )
1 2 3 4 5 |
if(!isNotLogIn) |
1 2 3 4 5 |
if(isLogIn) |
1 2 3 4 5 6 7 8 |
public bool IsValid() { return !exceptions.Any(); } |
1 2 3 4 5 6 7 8 |
public bool IsValid() { return exceptions.Count == 0; } |
Ternary IF
Yine ” Increase signal to noise ratio ” ile karşı karşıyayız. Üstelik dailyMessageLimit değişkeninin kullanım sayısı da dikkatinizi çekmiştir. 9 satır kod ve dönüş değerimiz 3 kez kullanılmış. Kodun sade ve tek satırda işlenmiş halinde çok daha anlaşılır olduğunu görebiliriz.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
int dailyMessageLimit; if(freeMember) { dailyMessageLimit = 10; } else { dailyMessageLimit = 100; } |
1 2 3 4 5 |
int dailyMessageLimit = freeMember ? 10 : 100; |
Strongly type kullan, stringly type değil 🙂
Aslında başlık her şeyi açıklıyor. Başlık haricinde Strongly Type ile;
Reference üzerinden değişken takibiniz kolaylaşır.
Code lens kullanımı kolaylaştırır.
Atamalarda ve eşitliklerde hata yapma olasılığınız yoktur.
Karşılaştırma yaparken Equals OrdinalCase, ToLower gibi önlemleri düşünmek zorıunda kalmazsınız.
1 2 3 4 5 |
if(productType == "HOTEL" |
1 2 3 4 5 |
if(productType == ProductType.Hotel) |
Başı boş ifadelerden kaçının
İlk örneğimizde aklımıza şöyle bir soru geliyor 16 ne ola ki ?
İkinci örneğimizde 16 sayısı net bir şekilde ifade edilmiş.Koşulun amacına yönelik çıkarımlar da yapabilir durumdayız.
1 2 3 4 5 |
if(age > 16) |
1 2 3 4 5 6 |
int maxChildAge = 16; if(age > maxChildAge) |
Karmaşık koşulları sadeleştir ve anlamlandır
İlk örneğimiz “Anlamlandırma” ile ilgili ; belirli bir şarta göre girilen if bloğunda bir güzellik yapılacak.
İşte o güzelliği ne için yaptığımızı anlamak için hem şartı hem de scope içindeki kodları gözden geçirmeliyiz.Daha sade yazılmış örneğini incelediğimizde promosyona hak kazanmış bir kullanıcıdan bahsedildiğini rahatlıkla anlayabiliriz.
1 2 3 4 5 6 7 8 |
if((DateTime.Now.Year - lastVisitDate.Year) <= 2 && childCount > 0) { // yap bir güzellik } |
1 2 3 4 5 6 7 8 |
bool acceptedPromotionGoal = (DateTime.Now.Year - lastVisitDate.Year) <= 2 && childCount > 0; if(acceptedPromotionGoal) { } |
Açıklayıcı ol doğru aracı kullan.Güldürürken düşündürme, Güldür!
İki kod bloğunu incelediğimizde ilk bloğun çok yorucu olduğunu fark etmişsinizdir.
Kod 1
relatedContracts listesi tanımlıyoruz.
Eldeki contracts listesini dönüyoruz
Ödemesi tamamlanmış, Aktif ve geçerli kontratı buluyoruz
relatedContracts’a ekliyoruz.
Listedeki tüm kayıtları döndükten sonra relatedContracts değişkenini return ediyoruz
Kod 2
contracts listesinden Ödemesi tamamlanmış, Aktif ve geçerli olanları geri dön
Ulaşmak istediğimiz hedefi olabildiğinde hızlı ve net bir şekilde anlatmamız ve açıklayıcı olmamız gerekiyor. Güldürürken düşündürmüyoruz 🙂 Diğer bir konu ise doğru araçların kullanılması.
ikinci bloğun yazılabilmesi LinqToObject ile mümkün. O halde doğru araçları kullanmalıyız
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
List<Contract> relatedContracts = new List<Contract>(); foreach(var contract in contracts) { if(contract.IsActive && contract.Status == ContractStatus.Done && contract.RemainingPayment == 0) { relatedContracts.Add(contract); } } return relatedContracts ; |
1 2 3 4 5 6 |
return contracts.Where(c => c.IsActive && c.Status == ContractStatus.Done) .Where(c => c.RemainingPayment == 0); |
Referans
Cory House / Clean Code Principles