Image 197
Temiz Kod (Clean Code)

Clean Code Nedir?

Temiz kod okumak, yazılım sektörü ile ilgilenen herkesin keyif aldığı bir durumken, ne yazık ki temiz kod yazmaya verilen dikkat o kadar yüksek değildir.

Bir kodu okurken fonksiyon isimlerinin fonksiyon ile alakasız olması okuyucuya karşı tarafın o an ne hissedip yazdı acaba demesine sebep olabilir ya da bir fonksiyonu yazdığımızda o fonksiyona fazla iş yükü yüklemekte fonksiyonun amacı dışına çıkmak gibi olacaktır. Kısacası bizim amacımız çetrefilli kodlar yazmaktan kaçınmak, kodu basitleştirmek, başka kişilerin de kodu okuyup üzerinde çalışabilecekleri anlaşılırlık düzeyinde bir kod yazmaktır.

Bu yazıda da tam olarak clean code nasıl yazılır bunu konuşacağız ve örneklerle açıklamaya çalışacağız.

Clean Code Yazmak için Nelere Dikkat Edilmeli?

Clean Code Prensipleri:

Doğru ve anlaşılır isim kullanılmalı: Kod yazarken kullanacağımız parametre isimleri olsun, sınıf ve fonksiyon isimleri olsun anlaşılır ve anlamlı olmasına dikkat etmemiz gerekmektedir.

İsimler, kodun ne yaptığını doğru bir şekilde yansıtmalı ve diğer geliştiricilerin kolayca anlayabilmesini sağlamalıdır. Örneğin, iki sayının toplamını hesaplayan bir fonksiyon yazalım:

Kod yazarken, isimlendirme için İngilizce kelimeler kullanmak genel kabuldür bunu biliyoruz. İngilizce, dünya genelinde en yaygın programlama dilidir ve bu nedenle kodumuzun daha geniş bir kitle tarafından anlaşılmasını sağlar. Ayrıca, çoğu programlama kütüphanesi ve ortamında İngilizce isimler kullanılır, bu yüzden tutarlılık açısından önemlidir.

Fonksiyon kendi işini yapmalı ve küçük olmalı: Bir fonksiyon, yalnızca tek bir işlevi yerine getirmelidir. Fonksiyonun amacı net ve spesifik olmalıdır. Böylece, fonksiyonu okuyan veya kullanan başka bir geliştirici, işlevi hızla anlayabilir.

Karmaşık ve uzun fonksiyonlar, kodun anlaşılmasını ve bakımını zorlaştırabilir. Bu nedenle, clean code prensiplerine uygun olarak fonksiyonları küçük ve tek bir işi yapacak şekilde bölerek, kodun okunabilirliğini artırabiliriz. Bir toplama fonksiyonunun aynı zamanda çıkarma işlemi yapması bu prensibe aykırı bir durumdur. Bu prensiple alakalı bir örnek verelim:

Bu örnekte de görüldüğü gibi, AddItem fonksiyonunda birden fazla iş yapıldığını görüyoruz. Fonksiyon, ürün eklemenin yanı sıra toplam fiyatı hesaplayıp ekrana yazdırmaktadır. Bu, fonksiyonun sorumluluklarını karmaşıklaştırır ve fonksiyonun ne yaptığını anlamak ve değişiklik yapmak daha zor hale gelir.

Bu örnekte de görüldüğü gibi, her fonksiyonun belirli bir işi yerine getirdiğini ve küçük olduğunu gösterir. AddItem fonksiyonu, yalnızca ürünleri eklerken kullanılır; CalculateTotalPrice, sepetteki ürünlerin toplam fiyatını hesaplar.

Yorum satırı kullanımına dikkat edilmeli: Clean code prensiplerinde bir diğeri ise yorum satırı konusudur. Kod yazarken gereksiz yorum satırlarından kaçınmamız gerekmektedir. Uzun ve her bir içeriği açıklayan yorum satırları kullanmak kodun temiz olmasını engelleyecektir.

Örnekte de görüldüğü gibi, yorum satırları sadece fonksiyonun ne yaptığını açıklamak için kullanılmıştır. Kod zaten oldukça açıklayıcıdır ve anlaşılır isimlendirme kullanılmıştır.

Bu örnekte ise, fonksiyonun ne yaptığını anlatan gereksiz ve tekrarlayıcı yorum satırları vardır. Fonksiyon zaten açık ve anlaşılır olduğundan, bu kadar fazla yorum satırı kullanmak kodu daha da karmaşık hale getirebilir ve okunabilirliği azalır.

Clean Code prensiplerine göre, kodun anlaşılırlığına katkıda bulunmak için yorum satırları yerine açıklayıcı isimler, iyi yapılandırma ve düzenli kodlama tercih etmemiz gerekmektedir. Fonksiyon ve değişken isimleri, kodun ne yaptığını ve amacını açıklamalıdır. Yalnızca karmaşık algoritmalarda, özel işlemlerde veya önemli notlar için yorum satırları kullanmak daha uygundur.

Tekrarlayan koddan kaçınılmalı (Don’t repeat yourself): Tekrarlayan kod, kodun anlaşılabilirliğini azaltır, bakımını zorlaştırır ve hatalara yol açabilir. Bu nedenle, tekrarlanan kod bloklarını birleştirerek, kodun sadeleşmesini sağlamalıyız.

Kodumuzu inceleyerek, benzer veya aynı kod bloklarını tespit etmemiz gerekmektedir. Bu kod blokları, işlevsel olarak aynı görevi yerine getiriyor olabilir veya benzer mantıksal adımları içerebilir. Bunları tespit ettikten sonra kodları nasıl birleştirebiliriz buna bakmalıyız.

Birleştirme işlemini fonksiyonlardan yardım alarak yapabiliriz. Bununla alakalı örnek verecek olursak:

Yukarıdaki örnekte görüldüğü gibi konsola yazdıracağımız metin iki farklı yerde tekrar ediyor. Bunu da birleştirmek için “Greeting” adında bir fonksiyon oluşturduk ve fonksiyonu dışarıdan çağırarak tekrarlayan kodu önlemiş olduk.

Diğer bir iyileştirme yöntemini de şu şekilde gösterebiliriz:

Gereksiz değişken kullanımından kaçınılmalı: Gereksiz değişken kullanımından kaçınmamız gerekmektedir. Gereksiz değişkenler, kodun karmaşıklığını, hafıza kullanımını artırabilir ve kodun okunabilirliğini azaltabilir. İyi bir kod, yalın ve anlaşılır olmalıdır.

Örnekte de görüldüğü gibi, CalculateSum fonksiyonu iki parametre alır ve bu parametreleri toplayarak doğrudan sonucu döndürür. Herhangi bir gereksiz değişken kullanılmamıştır ve işlem net ve anlaşılır bir şekilde yapılır.

Bu örnekte ise, CalculateSum fonksiyonu gereksiz bir sum değişkeni tanımlar ve bu değişkene a ve b‘yi ekler. Sonuç olarak, bir gereksiz adım eklenir ve kod daha karmaşık hale gelir. Bu örnek için ekstra değişken kullanımı işlemi anlaşılırlığı artırmaz ve okunabilirliği azaltır.

Adlandırma standartlarına dikkat edilmeli:

  • Camel Case (camelCase): Bu standartta kelimenin ilk harfi hep küçük harfle yazılır ve bundan sonra her kelime büyük harfle başlar.
  • Pascal Case (PascalCase): Bu durumda her kelimenin ilk harfi büyük olur.
  • Alt Çizgi Öneki (_underScore): Alt çizgi ( __ ) için, _’dan sonraki sözcük camelCase terminolojisini kullanır.

Sınıfların ve diğer kod öğelerinin adlandırılmasıyla alakalı aşağıda belirtilen şekilde kullanımlar yapılması gerekiyor.

Private -> _lowerCamelCase
Public -> UpperCamelCase
Protected-> UpperCamelCase
Interface-> IUpperCamelCase
Local Variable-> lowerCamelCase
Parameter-> lowerCamleCase

Süslü parantez kullanımına dikkat edilmeli: Düzgün ve uygun süslü parantez kullanımı sayesinde fonksiyonun içeriği net bir şekilde ayrıştırılır ve kod okunabilirliği artar. Fonksiyonun ne yaptığı ve ne döndürdüğü kolayca anlaşılır. Ayrıca, iç içe geçmiş fonksiyonlar veya koşullar olduğunda, girintileri düzenlemek ve süslü parantezleri düzgün kullanmak, kodun yapısını anlamak için çok önemlidir.

Bu örnekte, süslü parantezlerin kötü kullanımı şu şekillerde ortaya çıkmaktadır:

  • Açılış ve Kapanış Parantezleri Tek Satırda: Açılış süslü parantez ve kapanış süslü parantez aynı satırda yazılmıştır. Bu, kodun bloklarını belirgin bir şekilde ayrıştırmaz ve kodun okunabilirliğini düşürür.
  • Bir Satırda Birden Fazla İfadeint sum = a + b; return sum; şeklindeki ifadeler bir satırda yan yana yazılmıştır. Bu, kodun düzenini ve blokların sınırlarını belirsiz hale getirir.

Diğer Clean Code Prensipleri

1) Basit Tut KISS (Keep It Simple):

KISS prensibi, yazılım geliştirmede kodun mümkün olduğunca basit ve anlaşılır olması gerektiğini ifade eder. Karmaşık ve gereksiz çözümlerden kaçınarak, kodu mümkün olduğunca basit ve açık bir şekilde yazmak önemlidir. Basitlik, kodun okunabilirliğini artırır ve hataları en aza indirir.

2) Anlat, Sorma TDR (Tell, Don’t Ask):

Bir nesnenin veya sınıfın diğer nesnelerle etkileşimde bulunurken onlardan sormak yerine, direkt olarak ne yapması gerektiğini söyleyen bir prensiptir. Yani, bir nesne, başka bir nesneden bilgi almak ve ona göre hareket etmek yerine, ihtiyaç duyduğu bilgileri sağlayan nesneye talimat verir. Bu şekilde, kod daha az bağımlılık içerir ve daha az durum kontrolüyle daha anlaşılır hale gelir.

3) Tek Sorumluluk İlkesi SRP (Single Responsibility Principle):

Bir sınıfın veya modülün sadece bir neden veya sorumluluğu olması gerektiğini ifade eder. Başka bir deyişle, bir sınıfın sadece tek bir işlevi yerine getirmesi ve değişiklikler için sadece bir nedeninin olması gerektiğini vurgular. Bu ilke, kodun anlaşılırlığını, bakımını ve test edilebilirliğini artırarak yazılım projelerinin daha sağlam ve esnek olmasını sağlar.

4) Açık/Kapalı İlkesi OCP (Open/Closed Principle):

Bir yazılım bileşeni (sınıf, modül veya fonksiyon) açılmaya (open) ve değişikliklere kapalı (closed) olmalıdır anlamına gelir. Yani, mevcut kodu değiştirmeden yeni davranışlar eklemek mümkün olmalıdır. Kod, yeni gereksinimleri karşılamak için genişletilebilir olmalı, ancak mevcut işlevselliği bozacak değişikliklere izin vermemelidir.

5) Liskov Yerine Geçme İlkesi LSP (Liskov Substitution Principle):

Bir alt sınıfın, üst sınıfın yerine geçebilir olması gerektiğini ifade eder. Yani, bir sınıfın türetilmiş sınıfı, türeyen sınıfın tüm işlevselliğini korumalı ve hiçbir zaman üst sınıfın beklentilerini bozmamalıdır. Bu ilke, kodun açık ve esnek olmasını sağlayarak, uygulamanın herhangi bir yerinde üst sınıfın türetilmiş sınıfla değiştirilebilmesine olanak tanır.

6) Arayüz Ayırma İlkesi ISP (Interface Segregation Principle):

Bir arayüzün, onu kullanan istemcinin gereksinimlerine uygun olacak şekilde bölünmesi gerektiğini ifade eder. Yani, bir arayüzdeki metodlar, istemci sınıfların ihtiyaçlarına göre küçük, özelleştirilmiş ve bağımsız olmalıdır. Bu ilke, bir sınıfın kullanmadığı veya ihtiyaç duymadığı metodları zorunlu olarak uygulamasını önleyerek, kodun daha temiz ve anlaşılır olmasını sağlar.

7) Bağımlılık Enjeksiyonu (Dependency Injection):

Bir sınıfın diğer sınıflara olan bağımlılıklarını azaltmak ve daha esnek bir yapı oluşturmak için kullanılan bir tasarım desenidir. Bu desen, bir sınıfın ihtiyaç duyduğu bağımlılıkları (başka sınıfları, servisleri, veritabanı bağlantılarını vb.) doğrudan kendisinin oluşturmak yerine dışarıdan enjekte etmesini sağlar.

Kodun Kötü Kokması (CODE SMELLS)

Yazılım geliştirme sürecinde, kodun bakımı, genişletilmesi ve anlaşılması önemli bir rol oynar. Ancak, bazı durumlarda kod, düşük kaliteli, karmaşık ve zor anlaşılır hale gelebilir. Bu tür kodlara “Code Smells” veya “Kod Kokuları” denir. Kod kokuları, yazılım geliştirme sürecindeki düzensizlikler ve kötü uygulamaları işaret eder.

Kötü yazılım tasarımı veya düzensizlikleri olduğunda Code smells meydana gelmiştir diyebiliriz. Bu, kodun karmaşık olması, tekrar eden yapıların kullanılması, gereksiz karmaşıklık ve anlaşılabilirliğin düşük olması gibi sorunlardır. Yukarıda clean code yazmak için gerekli maddeler yazarken de bunlardan bahsettik. Kod kokuları, yazılımın kalitesini düşürür ve bakım maliyetini artırır, yeni özellikler eklemeyi veya hataları düzeltmeyi zorlaştırır.

Ayrıca kod kokuları, genellikle kodun kalitesini ve bakımını olumsuz etkileyen ancak doğrudan performans ölçümleriyle ilişkilendirilmeyen sorunlardır. Kod kokuları, kodun anlaşılabilirliğini, genişletilebilirliğini ve bakımını zorlaştırır, bu nedenle dolaylı olarak performansı etkileyebilirler. Ancak kod kokularının doğrudan bir performans ölçüsü olmadığını belirtmek önemlidir. İşte kod kokuları ve performans arasındaki ilişkiyi açıklayan bazı örnekler:

  1. Düşük Anlaşılabilirlik: Kodun karmaşıklığı ve okunabilirliği düşük olduğunda, yeni eklemeler veya hataların düzeltilmesi zorlaşır. Bu, geliştiricilerin daha fazla zaman harcamalarına ve hataların daha uzun süre tespit edilmesine neden olabilir. Bu durum, performansın dolaylı olarak etkilenmesine yol açabilir.
  2. Tekrar Eden Kod Blokları: Tekrar eden kod blokları, kodun bakımını zorlaştırır ve kodun genişletilmesini karmaşık hale getirir. Aynı işlevselliği farklı yerlerde tekrar tekrar yazmak, kodun daha büyük ve daha karmaşık olmasına yol açar. Bu durum, performansı etkileyebilir, çünkü gereksiz kod karmaşıklığına neden olur.
  3. Gereksiz Karmaşıklık: Kodun gereksiz karmaşıklığı, kodun daha yavaş çalışmasına veya kaynakların daha fazla kullanılmasına neden olabilir. Örneğin, gereksiz döngüler veya veri yapısı dönüşümleri, performans kaybına yol açabilir. Ancak bu durum doğrudan bir performans ölçüsü değildir, çünkü etkileri spesifik bir senaryoya ve uygulamaya bağlı olacaktır.
  4.  Kod Kopyalama (Code Duplications): Kod kopyalama, bir hata düzeltildiğinde veya yeni bir özellik eklenmeye çalışıldığında birden fazla yerde güncellemeler yapılmasını gerektirir. Bu, hataların ve uyumsuzlukların ortaya çıkmasına yol açabilir, bu da performans sorunlarına neden olabilir.

Performans ölçümleri, kodun çalışma süresi, bellek kullanımı veya işlemci kullanımı gibi daha spesifik metrikleri içerir. Kod kokuları, kodun kalitesini ve bakımını etkilediği için, kötü tasarım veya düzensizliklerin doğrudan bir performans etkisi olmadığı, ancak performans sorunlarını dolaylı olarak etkileyebileceği unutulmamalıdır. Dolayısıyla kod kalitesini artırmak ve kod kokularını gidermek, genellikle uzun vadede performansın iyileştirilmesine katkı sağlar, ancak bu iyileşme doğrudan bir ölçüm olmaz. Performans sorunlarını tespit etmek ve optimize etmek için spesifik performans analiz araçlarına veya profillemeye ihtiyaç vardır.

Nasıl Kod Kokuları Düzeltilebilir?

Kod kokularını düzeltmek için, düzenli bir şekilde refaktoring yapmak ve Clean Code prensiplerine dikkat etmek önemlidir. İşte kod kokularını düzeltmek için bazı stratejiler:

  1. Clean Code Prensiplerini Uygulamak: Clean Code prensiplerini (KISS, DRY, SOLID, vb.) uygulamak, kod kalitesini artırır ve kod kokularını azaltır.
  2. Refaktoring Uygulamak: Kod kokularını düzeltmek için düzenli olarak refaktoring yapmak önemlidir. Kodu anlaşılır, modüler ve bakımı kolay bir hale getirecek şekilde yeniden yapılandırmak gerekir.
  3. Kod İncelemeleri Yapmak: Takım üyeleri arasında kod incelemeleri yapmak, kod kokularını tespit etmeye yardımcı olur. Birlikte kodu gözden geçirerek iyileştirmeler yapmak önemlidir.
  4. Tasarım Desenlerini Kullanmak: Tasarım desenleri, kodun daha modüler ve esnek olmasını sağlar. Gereksiz tekrarları ve karmaşıklığı önler.

Kod kokuları, yazılım geliştirme sürecinde kaçınılmaz olabilir. Ancak, düzenli refaktoring ve Clean Code prensiplerine dikkat ederek, kod kalitesini artırabilir ve kod kokularını azaltabiliriz.

Sonuç olarak, Clean Code, yazılım geliştirmede temiz, anlaşılır ve bakımı kolay kod yazmanın önemini vurgulayan önemli bir kavramdır. Bu yazılım prensipleri, kod tabanınızı daha sürdürülebilir ve esnek hale getirerek uzun süreli başarıya ulaşmamıza yardımcı olur.

Temiz kod yazma süreci, başlangıçta ekstra çaba gerektirebilir, ancak zamanla büyük faydalar sağlar. Okunabilir, basit ve mantıklı kodlar, geliştiricilerin daha hızlı anlamasını ve hataların daha kolay tespit edilmesini sağlar.

Unutmayalım ki yazılım dünyası hızla değişiyor ve yeni teknolojilerle karşı karşıya kalıyoruz. Ancak Clean Code prensipleri, geçerliliğini koruyan temel kavramlardır ve her yazılım projesinde uygulanması gereken önemli bir yaklaşımdır.

Kaynaklar

Senanur Yılmaz
Aralık 18 , 2023
Diğer Blog İçerikleri