Neler yeni

Yazılım Forum

Tüm özelliklerimize erişmek için şimdi bize katılın. Kayıt olduktan ve giriş yaptıktan sonra konu oluşturabilecek, mevcut konulara yanıt gönderebilecek, itibar kazanabilecek, özel mesajlaşmaya erişebilecek ve çok daha fazlasını yapabileceksiniz! Bu hizmetlerimiz ise tamamen ücretsiz ve kurallara uyulduğu sürece sınırsızdır, o zaman ne bekliyorsunuz? Hadi, sizde aramıza katılın!

Temiz Kod Yazımı Rehberi: Sürdürülebilir ve Okunabilir Yazılım Geliştirme Sanatı

Giriş: Temiz Kod Neden Bu Kadar Önemli?

Yazılım geliştirme süreci, kod yazmaktan çok daha fazlasını içerir. Mevcut kodu anlamak, değiştirmek, hata ayıklamak ve yeni özellikler eklemek, yazılım geliştiricilerin zamanının büyük bir bölümünü kapsar. İşte tam da bu noktada 'temiz kod' kavramı devreye girer. Temiz kod, sadece bilgisayar tarafından çalıştırılabilen bir dizi talimat değil, aynı zamanda diğer insanlar (ve gelecekteki siz) tarafından kolayca okunabilen, anlaşılabilen ve sürdürülebilen bir sanattır. Bu rehber, temiz kod yazma prensiplerini derinlemesine inceleyerek, yazılım geliştirme pratiklerinizi bir üst seviyeye taşımanıza yardımcı olmayı amaçlamaktadır. Bakım maliyetlerini düşürmek, ekip verimliliğini artırmak ve yazılımın ömrünü uzatmak için temiz kod vazgeçilmezdir. Yazılım projelerinin başarısı ve uzun ömürlülüğü, büyük ölçüde kod kalitesine bağlıdır. Kirli kod, başlangıçta hızlı ilerleme sağlıyormuş gibi görünse de, zamanla teknik borcun birikmesine ve geliştirme hızının düşmesine neden olur. Aksine, temiz kod, ekibin daha hızlı ve daha az hatayla çalışmasını sağlar, yeni gelenlerin projeye adaptasyonunu kolaylaştırır ve gelecekteki genişlemeler için sağlam bir temel oluşturur. Bu, sadece bireysel geliştirici becerisi değil, aynı zamanda tüm ekip için bir kültür meselesidir.

Temiz Kodun Temel Nitelikleri ve Avantajları:

Temiz kod, bir dizi özellikle tanımlanabilir. Bu özellikler, yazılım projenizin uzun vadeli başarısı için kritik öneme sahiptir:
  • Okunabilirlik: Kodun kolayca okunabilir ve anlaşılabilir olması. Sanki iyi yazılmış bir düzyazı gibi akmalı. Bu, kodun mantığını hızlıca kavramayı sağlar.
  • Anlaşılabilirlik: Kodun ne yaptığını, neden yaptığını ve nasıl yaptığını açıkça belirtmesi. Bu, özellikle karmaşık iş mantıklarını içeren bölümlerde hayati öneme sahiptir.
  • Sürdürülebilirlik: Hata ayıklama, yeni özellik ekleme ve mevcut işlevselliği değiştirme kolaylığı. Bu sayede yazılım, değişen gereksinimlere daha kolay adapte olabilir.
  • Test Edilebilirlik: Kodun birim testleri ve entegrasyon testleri ile kolayca doğrulanabilir olması. Test edilebilir kod, aynı zamanda genellikle iyi tasarlanmış koddur.
  • Esneklik: Gelecekteki değişikliklere ve genişlemelere karşı dirençli olması. Modüler yapı ve düşük bağımlılıklar esnekliği artırır.
  • Verimlilik: Geliştirme sürecindeki zaman kaybını minimize etmesi. Azalan hata ayıklama süresi ve kolay entegrasyon ile geliştiricilerin zamanı daha verimli kullanılır.
  • Güvenilirlik: Daha az hata içerme eğilimi ve öngörülebilir davranış. Temiz kod, karmaşıklığı azaltarak hata potansiyelini düşürür.

1. Adlandırma Sanatı: Anlamlı İsimler Vermek

Kodda kullandığınız değişken, fonksiyon, sınıf ve dosya isimleri, kodunuzun anlaşılabilirliğinin temelini oluşturur. Anlamlı isimler, kodun amacını ve işlevini açıkça ifade etmelidir. Tek harfli veya kısaltılmış isimlerden kaçının. Örneğin, 'a' yerine 'miktar' veya 'müşteriSayısı' kullanmak çok daha açıklayıcıdır. Fonksiyon isimleri genellikle bir fiil veya fiil öbeği olmalı (örn. `kullaniciGetir()`, `urunKaydet()`), değişken isimleri ise bir isim veya isim öbeği olmalı (örn. `siparisMiktari`, `musteriListesi`). Bir ismin uzunluğu, anlaşılırlığını olumsuz etkilemez; asıl önemli olan, ismin neyi temsil ettiğini net bir şekilde belirtmesidir. Uzun vadede bu pratik, kodu okuyan herkesin zihinsel yükünü azaltır.

Kod:
// Kötü Örnek: Anlaşılması zor, açıklayıcı olmayan isimler
int d = 10; // 'd' ne anlama geliyor?
String s = "Merhaba"; // 's' selamlaşma mesajı mı, durum mu?
void calc(int x) { ... } // 'calc' neyi hesaplıyor, hangi parametreyle?

// İyi Örnek: Amacını ve içeriğini açıkça belirten isimler
int gecikmeSuresiGunOlarak = 10; // Gün cinsinden gecikme süresi
String hosGeldinMesaji = "Merhaba Dünya"; // Karşılama mesajı
void toplamBorcMiktariniHesapla(int musteriID) { ... } // Müşteri bazında toplam borç

2. Fonksiyonlar ve Metotlar: Küçük, Odaklanmış ve Tek İşlevli

Fonksiyonlar, temiz kodun en önemli yapı taşlarından biridir. İyi bir fonksiyon, tek bir görevi yerine getirmeli ve bunu iyi yapmalıdır. Bu prensip 'Tek Sorumluluk Prensibi' (Single Responsibility Principle - SRP) olarak da bilinir. Fonksiyonlarınız kısa olmalı (tercihen 20 satırdan az) ve yalnızca birkaç argüman almalıdır. Karmaşık koşullu ifadelerden veya iç içe döngülerden kaçınarak fonksiyonunuzun anlaşılabilirliğini artırın. Her fonksiyonun bir adı olmalı ve bu ad, fonksiyonun yaptığı işi tam olarak yansıtmalıdır. Bu, fonksiyonu çağırırken ne bekleneceği konusunda net bir fikir verir. Fonksiyonlarınızı küçük tutmak, test yazmayı kolaylaştırır ve hata ayıklama sürecini hızlandırır.

Kod:
// Kötü Örnek: Birden fazla iş yapan ve karmaşık olan bir fonksiyon
function kullaniciIslemleri(kullaniciVerisi, islemTipi) {
  if (islemTipi === 'dogrula') {
    // Kullanıcı verisi doğrulama mantığı
    if (!kullaniciVerisi.isim || !kullaniciVerisi.sifre) return false;
    console.log('Kullanıcı doğrulandı.');
    return true;
  } else if (islemTipi === 'kaydet') {
    // Kullanıcıyı veritabanına kaydetme mantığı
    try {
      db.kaydet('kullanicilar', kullaniciVerisi);
      console.log('Kullanıcı kaydedildi.');
      return true;
    } catch (e) {
      console.error('Kaydetme hatası:', e);
      return false;
    }
  } else if (islemTipi === 'epostaGonder') {
    // Kullanıcıya hoş geldin e-postası gönderme mantığı
    if (!kullaniciVerisi.email) return false;
    epostaServisi.gonder(kullaniciVerisi.email, 'Hoş Geldiniz');
    console.log('E-posta gönderildi.');
    return true;
  }
  return false;
}

// İyi Örnek: Fonksiyonları ayırarak tek sorumluluk ilkesine uyma
function kullaniciVerisiniDogrula(kullaniciVerisi) {
  // Doğrulama mantığı...
  return kullaniciVerisi.isim && kullaniciVerisi.sifre;
}

function kullaniciyiVeritabaninaKaydet(kullaniciVerisi) {
  // Kaydetme mantığı...
  try {
    db.kaydet('kullanicilar', kullaniciVerisi);
    return true;
  } catch (e) {
    console.error('Kaydetme hatası:', e);
    return false;
  }
}

function kullaniciyaHosGeldinEpostasiGonder(kullaniciVerisi) {
  // E-posta gönderme mantığı...
  if (!kullaniciVerisi.email) return false;
  epostaServisi.gonder(kullaniciVerisi.email, 'Hoş Geldiniz');
  return true;
}

// İş akışını bir araya getiren daha yüksek seviye bir fonksiyon
function yeniKullaniciKaydi(kullaniciVerisi) {
  if (!kullaniciVerisiniDogrula(kullaniciVerisi)) {
    console.error('Kullanıcı verisi geçersiz.');
    return false;
  }
  if (!kullaniciyiVeritabaninaKaydet(kullaniciVerisi)) {
    console.error('Kullanıcı kaydı başarısız.');
    return false;
  }
  if (!kullaniciyaHosGeldinEpostasiGonder(kullaniciVerisi)) {
    console.warn('Hoş geldin e-postası gönderilemedi.');
  }
  return true;
}

3. Yorumlar: Kodun Anlattığı Yerde Suskun Kalmak

Yorumlar, iyi niyetli olsalar da, yanlış veya eskimiş olma potansiyelleri nedeniyle kod tabanına ek yük getirebilir.
"İyi kod, en iyi belgelemedir." - Robert C. Martin (Uncle Bob)
prensibi gereği, kodunuzun kendisi açıklayıcı olmalıdır. Yorumlar, ancak kodun neden böyle yazıldığını (niyet), karmaşık bir algoritmanın mantığını veya bir dış bağımlılığın özel durumlarını açıklamak için kullanılmalıdır. Ne yaptığı açık olan kodu yorumlamak fazlalıktır. Örneğin, 'i++ // i'yi bir artır' gibi yorumlar gereksizdir. Bunun yerine, kodunuzu öyle yazın ki, yorumlara ihtiyaç duymadan anlaşılır olsun. Yorumlar, 'neden' sorusuna yanıt vermelidir, 'ne' değil. Örneğin, belirli bir iş kuralının veya bir API kısıtlamasının neden bu şekilde ele alındığını açıklamak için kullanılabilirler.

4. Biçimlendirme ve Okunabilirlik: Görsel Tutarlılık

Tutarlı bir kod biçimlendirme stili, kodunuzun okunabilirliğini önemli ölçüde artırır. Girintileme, boşluk kullanımı, satır uzunluğu ve dosya yapısı gibi konularda bir standarda uyun. Ekibinizle birlikte bir stil rehberi belirleyin ve linters gibi araçlar kullanarak bu rehbere uyumu otomatikleştirin. Örneğin, https://google.github.io/styleguide/ veya https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/ gibi genel kabul görmüş stil rehberlerini inceleyebilir ve kendi projenize uyarlayabilirsiniz. Tutarlı biçimlendirme, kodun görsel olarak düzenli ve kolay taranabilir olmasını sağlar, bu da hataların daha kolay tespit edilmesine ve kod incelemelerinin daha verimli olmasına yardımcı olur.

5. Hata Yönetimi: Hatayı Gizlemeyin, Kontrol Edin

Uygulamanızda ortaya çıkabilecek hataları zarif bir şekilde yönetmek, temiz kodun önemli bir parçasıdır. Hataları yutmak veya görmezden gelmek yerine, onları açıkça ele alın. İstisna mekanizmalarını doğru kullanarak hata durumlarını net bir şekilde belirtin ve ilgili yerlerde yakalayın. Hata mesajlarınız kullanıcılar ve geliştiriciler için anlamlı olmalıdır. Hata durumlarını oluştukları yerde yönetmek veya ilgili katmana iletmek, sistemin bütünlüğünü korur ve hata ayıklamayı kolaylaştırır. Özellikle dış sistemlerle (veritabanları, ağ servisleri vb.) etkileşimlerde hata yönetimini ciddiye almak kritik öneme sahiptir.

Kod:
try {
  // Dış servis çağrısı veya hassas dosya işlemi
  veriKaynagi.veriyiOku(dosyaAdi);
} catch (FileNotFoundException e) {
  // Dosya bulunamadı hatası özel işleme
  log.error("Belirtilen dosya bulunamadı: " + dosyaAdi, e);
  throw new UygulamaOzelIstisnasi("Okunacak dosya mevcut değil.", e);
} catch (IOException e) {
  // Genel G/Ç hatası
  log.error("Dosya okuma sırasında bir G/Ç hatası oluştu: " + e.getMessage(), e);
  throw new UygulamaOzelIstisnasi("Dosya işlemi sırasında beklenmeyen bir hata oluştu.", e);
} finally {
  // Kaynakları kapatma veya temizleme
  if (veriKaynagi != null) {
    veriKaynagi.kapat();
  }
}

6. Test Edilebilirlik: Temiz Kodun Aynası

Temiz kod, doğal olarak test edilebilir koddur. Eğer kodunuzu test etmek zorsa, bu genellikle kötü tasarımın bir işaretidir. Tek sorumluluğu olan küçük fonksiyonlar, bağımlılıkları enjekte edilmiş sınıflar ve net arayüzler, birim testlerini yazmayı kolaylaştırır. Testlerinizi yazmak, hem kodunuzun doğruluğunu sağlar hem de gelecekteki değişikliklerin mevcut işlevselliği bozmadığını garanti eder. Test piramidi yaklaşımı, farklı test türlerinin (birim, entegrasyon, UI) dengeli bir şekilde kullanılmasını önerir. Test güdümlü geliştirme (TDD) gibi yaklaşımlar, temiz ve test edilebilir kod yazmayı teşvik eder. İyi yazılmış testler, aynı zamanda kodun nasıl kullanılması gerektiğine dair yaşayan bir belge niteliği taşır.

800px-Test_Pyramid.svg.png

Resim: Martin Fowler'ın Test Piramidi Konsepti (Görsel temsil amaçlıdır, gerçek bağlantıdan farklılık gösterebilir). Piramit, tabanda hızlı çalışan birim testleri, ortada daha yavaş entegrasyon testleri ve en tepede en yavaş UI testleri ile test türleri arasındaki dengeyi gösterir.

7. DRY, KISS, YAGNI İlkeleri

Bu üç ilke, yazılım tasarımında karmaşıklığı azaltma ve verimliliği artırma konusunda temel rehberlerdir:

Don't Repeat Yourself (DRY - Kendini Tekrar Etme): Kod tabanınızda aynı mantığı birden fazla yerde bulundurmaktan kaçının. Tekrarlanan kodu fonksiyonlara veya sınıflara soyutlayarak, değişiklikleri tek bir yerden yapabilir ve tutarlılığı sağlayabilirsiniz. Bu, bakım maliyetlerini düşürür ve hataların yayılmasını engeller.

Keep It Simple, Stupid (KISS - Basit Tut Salak): En basit çözümü tercih edin. Gereksiz karmaşıklık eklemekten kaçının. Genellikle, en basit çözüm en iyisidir ve anlaşılması, bakımı daha kolaydır. Aşırı mühendislikten kaçının ve bir problemi çözmek için en sade yolu bulun.

You Aren't Gonna Need It (YAGNI - Buna İhtiyacın Olmayacak): Şu anda ihtiyacınız olmayan özellikleri veya altyapıyı eklemekten kaçının. 'Belki ileride işe yarar' düşüncesiyle eklenen kod, genellikle hiç kullanılmaz ve sadece kod tabanını karmaşıklaştırır, bakımını zorlaştırır. Odak noktanızı mevcut gereksinimleri karşılamaya odaklayın.

8. SOLID İlkeleri (Kısa Bir Bakış)

Nesne Yönelimli Tasarımda temiz kod için yol gösterici olan SOLID ilkeleri şunlardır:
  • Single-responsibility Principle (Tek Sorumluluk Prensibi): Bir sınıfın veya modülün yalnızca bir sorumluluğu olmalıdır.
  • Open-closed Principle (Açık-Kapalı Prensibi): Yazılım varlıkları (sınıflar, modüller, fonksiyonlar vb.) geliştirmeye açık, ancak değiştirmeye kapalı olmalıdır.
  • Liskov Substitution Principle (Liskov Yerine Koyma Prensibi): Bir süper sınıfta kullanılan nesneler, alt sınıfların nesneleriyle değiştirilebilmelidir.
  • Interface Segregation Principle (Arayüz Ayırma Prensibi): İstemciler, kullanmadıkları arayüzlere bağımlı olmamalıdır.
  • Dependency Inversion Principle (Bağımlılıkların Tersine Çevrilmesi Prensibi): Yüksek seviyeli modüller, düşük seviyeli modüllere bağlı olmamalıdır. Her ikisi de soyutlamalara bağlı olmalıdır. Soyutlamalar detaylara bağlı olmamalı, detaylar soyutlamalara bağlı olmalıdır.
Bu ilkeler, özellikle büyük ve karmaşık sistemlerde, esnek, sürdürülebilir ve bakımı kolay bir kod tabanı oluşturmaya yardımcı olur. Her bir ilke kendi içinde ayrı bir rehber konusu olsa da, genel bir temiz kod yaklaşımının ayrılmaz bir parçasıdırlar. Bu prensipleri anlamak ve uygulamak, yazılım mimarisi kararlarınızda size yol gösterecektir.

9. Kod Kokuları ve Refaktoring: Sürekli İyileştirme

'Kod kokusu' (code smell), kodun kendisi hatalı olmasa da, kötü tasarım veya uygulama göstergesi olan yüzey işaretleridir. Uzun fonksiyonlar, büyük sınıflar, tekrarlanan kod, çok sayıda parametre ve karmaşık koşullu ifadeler yaygın kod kokularıdır. Refaktoring, yazılımın dışarıdan görünen davranışını değiştirmeden iç yapısını iyileştirme sürecidir. Düzenli refaktoring, kod tabanınızın temiz ve yönetilebilir kalmasını sağlar. Küçük adımlarla, sürekli olarak refaktoring yapmak, büyük ölçekli yeniden yazma ihtiyacını azaltır. Kod incelemeleri (code reviews) ve otomatik analiz araçları, kod kokularını erken aşamada tespit etmeye yardımcı olabilir. Refaktoring, sürekli bir süreç olmalı ve teknik borcun birikmesini engellemelidir.

Kod:
// Kod Kokusu Örneği: Çoklu if/else ile karmaşık koşullu mantık ve indirim oranı mantığının karıştırılması
function siparisFiyatiHesapla(urunKodu, miktar, musteriTipi) {
  let birimFiyat;
  if (urunKodu === 'ELMA') {
    birimFiyat = 5;
  } else if (urunKodu === 'ARMUT') {
    birimFiyat = 7;
  } else if (urunKodu === 'MUZ') {
    birimFiyat = 3;
  } else {
    birimFiyat = 0;
  }

  let toplamFiyat = birimFiyat * miktar;

  if (musteriTipi === 'GOLD') {
    toplamFiyat *= 0.8; // %20 indirim
  } else if (musteriTipi === 'SILVER') {
    toplamFiyat *= 0.9; // %10 indirim
  }
  // Diğer müşteri tipleri için indirim yok

  return toplamFiyat;
}

// Refaktoring Sonrası (Örnek: Fonksiyonları ayırarak daha okunabilir ve yönetilebilir bir yapı)
function urunBirimFiyatiniGetir(urunKodu) {
  switch (urunKodu) {
    case 'ELMA': return 5;
    case 'ARMUT': return 7;
    case 'MUZ': return 3;
    default: return 0;
  }
}

function musteriIndirimOraniniUygula(toplamFiyat, musteriTipi) {
  switch (musteriTipi) {
    case 'GOLD': return toplamFiyat * 0.8;
    case 'SILVER': return toplamFiyat * 0.9;
    default: return toplamFiyat;
  }
}

function siparisFiyatiHesaplaRefactored(urunKodu, miktar, musteriTipi) {
  const birimFiyat = urunBirimFiyatiniGetir(urunKodu);
  let toplamFiyat = birimFiyat * miktar;
  toplamFiyat = musteriIndirimOraniniUygula(toplamFiyat, musteriTipi);
  return toplamFiyat;
}

Sonuç: Temiz Kod Bir Yolculuktur

Temiz kod yazmak, tek seferlik bir hedef değil, sürekli bir öğrenme ve iyileştirme yolculuğudur. Bu rehberde bahsedilen prensipleri günlük kodlama alışkanlıklarınızın bir parçası haline getirmek, hem kendi kişisel gelişiminizi hızlandıracak hem de çalıştığınız projelerin kalitesini artıracaktır. Unutmayın, yazdığınız kodun asıl hedef kitlesi bilgisayarlar değil, diğer insanlardır. Bu nedenle, kodunuzu sadece çalışır hale getirmekle kalmayın, aynı zamanda okunabilir, anlaşılabilir ve sürdürülebilir olmasına da özen gösterin. İyi yazılmış, temiz bir kod tabanı, bir yazılım projesinin uzun ömürlü ve başarılı olmasının anahtarıdır. Bu pratikleri benimseyerek, daha verimli, daha az hata içeren ve bakımı daha kolay yazılımlar geliştirebilirsiniz. Her yeni satır kodda, bu prensipleri aklınızda tutarak yazılım sanatında ustalaşın. Bol şans!

https://tr.wikipedia.org/wiki/Temiz_kod adresinden daha fazla bilgi edinebilirsiniz.

Bu rehber, yazılım geliştirme topluluğunun genel kabul görmüş en iyi pratiklerini özetlemeyi amaçlamaktadır. Temiz kod prensipleri hakkında daha fazla bilgi ve derinlemesine inceleme için Robert C. Martin'in 'Clean Code' kitabını okumanız şiddetle tavsiye edilir. Temiz kod, sadece teknik bir konu değil, aynı zamanda ekip içi iletişimi ve iş birliğini güçlendiren bir felsefedir. Bu prensipleri benimsemek, yazılım mühendisliği kariyerinizde önemli bir fark yaratacaktır.
 
shape1
shape2
shape3
shape4
shape5
shape6
Üst

Bu web sitenin performansı Hazal Host tarafından sağlanmaktadır.

YazilimForum.com.tr internet sitesi, 5651 sayılı Kanun’un 2. maddesinin 1. fıkrasının (m) bendi ve aynı Kanun’un 5. maddesi kapsamında Yer Sağlayıcı konumundadır. Sitede yer alan içerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır.

YazilimForum.com.tr, kullanıcılar tarafından paylaşılan içeriklerin doğruluğunu, güncelliğini veya hukuka uygunluğunu garanti etmez ve içeriklerin kontrolü veya araştırılması ile yükümlü değildir. Kullanıcılar, paylaştıkları içeriklerden tamamen kendileri sorumludur.

Hukuka aykırı içerikleri fark ettiğinizde lütfen bize bildirin: lydexcoding@gmail.com

Sitemiz, kullanıcıların paylaştığı içerik ve bilgileri 6698 sayılı KVKK kapsamında işlemektedir. Kullanıcılar, kişisel verileriyle ilgili haklarını KVKK Politikası sayfasından inceleyebilir.

Sitede yer alan reklamlar veya üçüncü taraf bağlantılar için YazilimForum.com.tr herhangi bir sorumluluk kabul etmez.

Sitemizi kullanarak Forum Kuralları’nı kabul etmiş sayılırsınız.

DMCA.com Protection Status Copyrighted.com Registered & Protected