Buse Yigit
9 min readApr 23, 2021

Temiz Kod Nedir?

Temiz kod, yazdığınız kodun anlaşılır, açık ve okunabilirliğinin yüksek olduğu durumlarda kazandığı bir sıfattır. Temiz kod yazmanın asıl amacı başka bir yazılımcının kodunuza baktığında onu kolayca anlayabileceği kadar düzenli ve okunaklı olmasıdır. Yazılan kodlar ne kadar karmaşık ve uzun olursa, yazılımcıların verimliliğini de bir o kadar düşürür.

Karışık program ve projeler genellikle bir takım ürünüdür. Bu takım ne kadar uyumlu ve ve beraber çalışabilirse proje de aynı ölçüde başarıya ulaşır. Projenin başından beri geliştirmeye yardımcı olan takım üyeleri projenin her ayrıntısına hakim olmasına rağmen sonradan ekibe katılan üyeler için bu imkansızdır. Temiz kod sayesinde sonradan katılan üyelerin kodu olabilecek en kolay ve en hızlı şekilde çözümlemesi ve projeye dahil olması amaçlanır. Temiz kodlamanın bir diğer amacı da yazımınızın üzerinden kendi kodunuzu unutabileceğiniz kadar sene geçtikten sonra bile dönüp baktığınızda kodunuzu kolayca hatırlamak ve okuyup anlayabilmektir.

Dağınık yazılmış bir kodu dağınık bir mutfağa benzetmek bu yapının olumsuz yönlerini kavramada bize yardımcı olabilir. Dağınık bir kodda da aynı şekilde istenmeyen yerlerden çıkan istenmeyen elementler mevcuttur. Karışık kod satırlar, satırlar arasında kaybolmuş ve karışık isimli değişkenler, birbirine girmiş dizilmiş döngüler ve benzeri yapılar dağınık ve kötü kodlamanın bir parçası ve temiz kodlamada kesinlikle kaçınılması gereken noktalardan bazılarıdır. Temiz kod yazabilmek için dikkat edilmesi gereken bazı temel hususlara göz atalım.

İsimlendirme:

İsimlendirme temiz kodlamanın en önemli adımlarından biri olarak kabul edilebilir. Programlarda her şeye isim veririz. Bu bir değişken, fonksiyon, sınıf, dosya ve benzeri bir şey olabilir. Bu kadar çok isimlendirme yapılırken belli başlı noktalara dikkat edilmezse kod gereğinden fazla karışık ve okunurluğu az olur. Okuyan kişi değişken isimlerini takip etmekte zorlanır ve bunlara odaklanıp programın amacını kaçırabilir. Hem okuması hem anlaması hem test edilmesi hem de hata gidermesi zor ve zahmetlidir. İsimlendirme bu sebeplerden ötürü apayrı bir sanat olarak görülebilir.

İsimlendirme yapılırken bahsedilen değişkenin veya fonksiyonun amacı göz önünde bulundurulmalıdır. Okuyan kişi okuduğunda değişkenin neyi belirttiğini veya ne amaçla kullanıldığını bağlamdan değil isimden çıkarabilmelidir. Bu sebeple genel isimler yerine özel isimler kullanılması temiz kod açısından daha doğru olacaktır. Örneğin aşağıdaki iki kod bloğundan birincisinde kodun ve değişkenlerin amacı anlaşılmazken ikincide seçilen açıklayıcı ve hedef odaklı isimler kodun ilerleyişi hakkında okuyan yazılımcıya bilgi verir.

1. int not[10]; // Öğrencilerin vize notları

2. //Öğrencilerin vize notları

int BaharVizeNotlari; int GuzVizeNotlari;

Ayrıca isimlendirme yapılırken kısaltmalardan da kaçınılmalıdır. Fazla uzun olmamakla beraber anlaşılır düzeydeki isimlendirme kodun bir kitap gibi akıcı şekilde okunmasına katkı sağlayacaktır. Bu tip kodlar yorum satırlarına da nadiren ihtiyaç duyarlar ve self-documented kod olarak adlandırılırlar. Örneğin hem öğrenci hem de öğretmen değişkenlerinden oluşan bir programda öğrenci değişkeninin ismini “ograd” gibi bir isimle tutmak karışıklık yaratırken, “Ogrenci_Ad” ile tutmak bu kodun anlaşılır olmasında büyük önem taşır.

İsimlendirme yapılırken değişkenlere verilen benzer isimler de kısa ve genel isimler kadar sorun yaratır. Bunlar genelde benzer bir değişkene yeni bir isim vermek yerine yanına bir sayı eklemek veya orjinalinin isminden birkaç harf çıkararak oluşturulmuş yeni isimlerdir. Program yazıldıktan sadece birkaç hafta sonra bile bakıldığında bu isimler çoktan birbirlerine karıştırılabilcek düzeyde unutulmuş olur çünkü neredeyse bir diğeri ile aynıdır.

public static void copyChars(char a1[], char a2[]) {

for (int i = 0; i < a1.length, i++) {

a2[i] = a1[i];

}

}

Örneğin yukarıdaki kodda dizi isimlerine özgün birer isim verilmek yerine yanlarına sayı eklenmiş ve hiçbir anlam ifade etmeyen bir söz grubu ile isimlendirilmiş iki dizi elde edilmiştir. Bunun yerine dizinin program içerisindeki kullanım amacına göre isimler konulması gerekmektedir.

İsimlendirme yapılırken dikkat edilmesi gereken bir diğer husus da aranabilir ve bulunabilir isimler seçmektir. İsmin kısa ve öz olması için çaba sarf edilirken haddinden fazla kısa veya aynı sözcüğü içeren isimler kesinlikle kullanılmamalıdır. Bu kullanım hata ayıklama ve çözme süresini oldukça uzatır. Aşağıdaki örnekte görüldüğü ibi ilk örnekten programla ilgili bir bilgi sızmazken ikinci kod bize program hakkında oldukça bilgi verir.

1- for (int j = 0; j < 34; j++) {

t += (g[j]*4)/5;

}

2- int reelGunSayisi = 4;

const int HAFTALIK_CALISMA_GUNU = 5;

int toplam = 0;

for (int j = 0; j < GOREV_SAYISI; j++) {

int reelGorevGunleri = gorevKestirimi[j] * reelGunSayisi;

int reelGorevHaftalari = (reelGunler/HAFTALIK_CALISMA_GUNU);

toplam += reelGorevHaftalari;

}

Koşul Kullanımı:

Bir kodda koşul kullanımı ne kadar sıksa kodu okuma süresi de bir o kadar uzundur. Çünkü her koşulun sağlanma ve sağlamama durumu olduğundan okuyucuyu sürekli geri döndürür ve ikinci bir ihtimalin daha kontrolünü beraberinde getirir. Eğer programlar koşul blokları içermeseydi bu programı okumak bir düz yazıyı okumak kadar zahmetsiz olurdu. Koda eklenen her koşul ve karşılaştırma bloğu kodun karmaşıklığını arttırır ve anlaşılabilirliğini azaltır. Koşul blokları ne kadar büyükse ikinci ihtimali tartışmak için dönülen yok o kadar uzun olacağından kapsamlı ve sık koşul blokları kullanmak temiz kodlama için kaçınılması gereken önemli adımlardan biridir.

Yine koşul veya karşılaştırma satırlarında dikkat edilmesi gereken bir konu da doğal dile ne kadar yakın olduğudur. Örneğin;

1. İf (3=>zar)

Printf(“%d geldi”,zar);

2. İf (ZardaGelenSayi=>3)

Printf(“Zar : %d geldi”, ZardaGelenSayi);

Yukarıdaki iki örnekte görüldüğü gibi ikinci kodu okumak birinci kodu okumaktan daha kolaydır. Aslında ilk kodda da kullanıcının bir zar attığını ve gelen sayı 3 ise yazdırılması gerektiğini anlıyoruz ancak ikinci kodda hem if bloğunun içindeki karşılaştırma sırası konuşma diline daha uygun hem de değişken isimleri açıkça belirtilmiş ve okuyan kişinin tahminine bırakılan bir açıklık yok.

İf-else koşul bloklarında hangi sıra ile yazacağımız da yine kodumuzun okunabilirliğini arttıracak etkenlerden biri olacak. Gerçekleşme ihtimali daha düşük veya tek olan durumları if satırında kullanmak, else satırında kullanmaktansa hem süre hem basitlik açısından bize yarar sağlayacak. Çünkü if satırında beklenen veya istenen durum olması, istenmeyen diğer tüm durumların yanında daha küçük kalacaktır.

Örneğin bu iki koşul bloğunun bir a döngüsü içinde döndüğünü ve b sayısını aradığımızı düşünelim. Bu durumda ilk kodda b sayısını bulduğumuzda if satırları çalışacak ve diğer tüm durumlarda düşünmeden else satırına bırakacağız. Ancak ikinci kodda tüm liste içinde aradığımız b sayısı herhangi bir sırada olabileceğinden sürekli olumsuz durumla baş etmek zorunda kalacağız. Görüldüğü gibi kodun işleyişinde etkisi olmayan bir yazım sırası bile kodun okunur ve anlaşılır olmasında büyük önem taşıyor.

Koşul bloklarının asıl sorun oluşturan kısmı ise iç içe birden fazla kez yazılmasıdır. Bunu okumak sıralı bir koşullar listesini okumaktan çok daha zor ve zahmetlidir. Bu sebeple iç içe kullanmak yerine en anlaşılır biçimde ayırmak temiz kodlama açısından bize fayda sağlar.

if (sayi < 0)
printf(“Negatif sayı girdiniz\n”);
else
if (sayi > 0)
printf(“Pozitif bir sayı girdiniz\n”);
else
printf(“Sıfır sayısını girdiniz\n”);

Yukarıdaki örnek oldukça basit bir kod olduğu için iç içe if else blokları kullanılsa bile anlayabiliyoruz. Fakat bu kompleks ve büyük projelerde de böyle olabileceği anlamına gelmez. Bu yüzden şimdi bu kodu nasıl düzeltebileceğimize bir bakalım. Öncelikle kodun amacını anlayalım. Kodun amacı dışarıdan girilen bir “sayi” değişkeninin değerinin poizitif, negatif veya sıfır olduğunu bulmaktır. Bu durumda kod önce sayının 0’dan küçük olup olmadığına bakar. Eğer değilse bu defa ikinci if-else devreye girer ve bu defa pozitif olup olmadığına bakar. O da değilse ekrana sayının sıfır olduğu bilgisini getirir. Şimdi bu kodu daha önce belirttiğimiz önemli noktalara göre düzenleyelim.

if (sayi == 0)
printf(“Sıfır sayısını girdiniz.\n”);
if (sayi > 0)
printf(“Pozitif bir sayı girdiniz\n”);

else
printf(“Negatif bir sayı girdiniz.\n”);

Artık kodumuz iç içe yapılardan oluşmuyor ve az önceki iç içe haline göre takip edilebilirliği daha fazla.

Döngü Kullanımı:

Döngülerde özellikle okuyucu tarafından karmaşık, belirsiz ve endişe verici bir durum olarak görülen döngü do-while döngüsüdür. Do-while döngülerinin şartı while satırında bulunduğundan while satırına gelene kadar yazılmış kod en az bir defa gerçekleştirilir. Fakat şart en sonda belirtildiği için bu ıssız bir gece karanlığında sonunu görmediğiniz bir sokağa sapmak gibidir. Nadiren kullanımı while döngüsünden daha etken bir rol oynasa bile do-while döngüleri her zaman yalnızca while döngüsü şeklinde yazılabildiği için while döngüsünü kullanmak daha açıklayıcı olacaktır. Yine de eğer while döngüsü ile yapacağımız işi for döngüsü ile de yapabiliyorsak daha net sonuçlar için for döngüsünü kullanmak daha doğrudur.

Foksiyonların Kullanımı:

Fonksiyonlar geniş kapsamlı projelerin olmazsa olmazlarıdır. Özellikle de konu okunabilirlik ve açıklık olduğunda karmaşık projeler için eşsiz bir keşiftir. Fonksiyonlar adından da anlaşıldığı üzere kodumuzun en küçük iş birimini içinde bulunduran yapıdır. Tabii daha büyük ve iç içe fonksiyonlar da mevcuttur fakat şimdi fonksiyonların optimum özelliklerine değineceğiz. Fonksiyonlar iş belirtirler. Bu iş şirket yazılımında “CalisanMaasiHesaplama()” veya “KalanIzinSureleriHesaplama()” gibi yapılacak işlerin en temel adımlarını içerirler. Bir fonksiyondan beklenen her şeye yardımcı olması değil sadece tek bir şey yapması ve onu olabilecek en basit ve kısa yani en iyi şekilde yapmasıdır. Bu yüzden fonksiyonları yazarken dikkat edilmesi gereken en önemli husus kısa olmasıdır.

Fonksiyonlar bir programın yapı taşlarıdır. Birleşip bir bütün oluşturmaları beklenir ve istenirken en baştan karmaşık ve uzun olurlarsa iç içe girdiklerinden içinden çıkılamaz bir hal alacaklardır. Ayrıca fonksiyonların da tıpkı değişkenler gibi isimlendirmesi çok önemlidir. Kısaltmalar ve fonksiyonun tam amacını anlatmayan isimler kod ilerlediğinde karmaşıklığa ve unutkanlığa yol açacaktır. Fonksiyonun ismi fonksiyonun ne yaptığını tam olarak anlatmalı ve fonksiyon, isminde belirtilen işi tam olarak yapabiliyor olmalıdır. Bu isimlendirme kodun geleceği için oldukça önemli olduğundan yapmış olmak için yapılmamalı, aksine üzerine oturup düşünülmelidir. Fonksiyonlarınız kendini yeterince iyi anlatırsa sizin onu tekrar anlatmak için kullanmanız gereken yorum satırlarından da sizi kurtarmış olacaktır.

Yorum Satırları:

Yazılımda asıl amacımız temiz, düzenli ve kendini okutabilen kodlar yazmaktır ki anlaşılırlığı yazan kişi veya kişilerle sınırlı kalmasın. Yorum satırlarının da amacı aslında okuyan kişiye kodun açıklamasını yapmaktır. Fakat bu cümleden çıkarılabilecek tek yargı kodunuz kendi kendini anlatamadığı için sizin onu anlatma gereksinimi duyduğunuzdur. İyi yerleştirilmiş gerekli bir yorum kodunuz için çok yararlı olabilir ancak asıl amaç bu yorumlara bile ihtiyaç bırakmayacak kadar açık ve anlaşılır kodlar yazmaktır. Unutmayalım ki kötü kodları yorum satırları ile açıklamaktansa yenisini ve keni kendini anlatan bir kod yazmak her zaman için daha iyidir.

İnceleme

Şimdi buraya kadar yazdıklarımızı iş üzerinde görmek için birkaç kod inceleyelim ve temiz kodlama açısından yanlış bulduğumuz noktaları belirleyelim.

Örnek :

Bu kodu incelemeye yazımızdaki adımların sonuncusu olan yorum satırlarından başlayalım. Yapılan işlemin anlaşıldığı 6. Ve 8. Satırlardaki yorumlar oldukça gereksizdir çünkü while döngüsü içinde dönen sayının sayaç olduğunu ve döngünün sonunda arttırıldığını zaten görebiliyoruz.

Şimdi bunlar dışındaki yorum satırlarını gidermek için neler yapabileceğimize bir bakalım. Bunu yapmak için kodun amacını anlamış olmamız gerekiyor. Kodumuzdaki while döngüsünün içine bakarsak bunun bir faktöriyel alma programı olduğunu rahatça söyleyebiliriz. Sayaç 1’den başlıyor ve kendisine faktöriyeli alınacak sayıya gelene kadar olan tüm sayılar sırayla çarpılıyor ve geçici bir değişkene atanıyor. Burada anlatırken dahi göze çarpan önemli hatalardan biri tabi ki isimlendirme hataları. Bu kodun daha anlaşılır olması ve tek tek işlemlere bakmadan okuyucuya kendini anlatabilmesi için “okunanSayi” değişkeni yerine “FaktoriyeliIstenenSayi”, “digerSayi” yerine ise “GeciciDegiskenSayi” ifadelerini kullanmak daha doğru olur.

İsimlendirme dışındaki bir diğer yanlış ise döngü kullanımındaki dikkatsizlik. Bu kodu yazarken rahatlıkla while döngüsü yerine aşağıdaki gibi bir for döngüsü kullanabiliriz ve bu hem sonradan okuyan birine hem de sizin geri dönüp test etmeniz için size kolaylık sağlar.

Doğru kullanım:

for(j=1;j<=FaktoriyeliIstenenSayi;j++)

{

GeciciDegiskenSayi= GeciciDegiskenSayi*j;

}

Son olarak kodu temize çekme işi asla sonraya bırakılmamalıdır çünkü asla geri dönülüp yapılmaz.

“Sonra asla demektir (Later equals never).”- LeBlanc

Kaynakça:

· https://medium.com/@busrauzun/clean-code-kitabindan-notlar-1-temiz-kod-derken-44e6f7a27eb0

· https://medium.com/@orhunbegendi/koda-yorum-yazmak-mi-yoksa-yazmamak-mi-d6b9d402aa44

· https://www.geeksforgeeks.org/7-tips-to-write-clean-and-better-code-in-2020/

· https://enos.itcollege.ee/~jpoial/oop/naited/Clean%20Code.pdf

· https://www.pomelosoft.com/blog/temiz-kod-nedir

· http://cagataykiziltan.net/tr/clean-code/

· https://www.erenakpinar.com/temiz-kod-nedir-nasil-yazilir/

https://www.karel.com.tr/blog/temiz-kod-icin-15-oneri