Yazılım Geliştirme ⏱ 7 dk okuma

Temiz Kod Yazmanın 10 Altın Kuralı

Kod yazmak kolay, okunabilir ve sürdürülebilir kod yazmak ise bambaşka bir sanat. Robert C. Martin'in mirasından ilham alan bu kurallar, ekibinizin ve gelecekteki benliğinizin size teşekkür etmesini sağlayacak.

16 Mart 2026

Robert C. Martin'in 2008'de yayınladığı "Clean Code" kitabı, onlarca yıl sonra hâlâ yazılımcıların el kitabı olmaya devam ediyor. Kitabın açılış satırları her şeyi özetliyor: "Kötü kod yazmak hızlı hissettirir. Ve sonra sizi yavaşlatır." Bakımı güç, anlaşılmaz bir kod tabanının uzun vadeli maliyeti tahmin edilenden çok daha ağır.

Stack Overflow'un yıllık geliştirici anketine göre yazılımcılar çalışma sürelerinin yaklaşık yüzde kırkını başkasının (ya da geçmişteki kendilerinin) yazdığı kodu anlamaya çalışmakla geçiriyor. Bu, kötü kodun doğrudan üretkenlik maliyeti. Dolaylı maliyetleri — hata oranlarındaki artış, yeni özellik geliştirmenin yavaşlaması, ekip moralinin düşmesi — hesaba katarsanız tablo daha da karamsar.

Aşağıdaki 10 kural, soyut prensipler değil; günlük kodlama pratiğine doğrudan uygulanabilir, somut rehberler.

1. Anlamlı ve Niyeti Açıklayan İsimler Kullan

Bir değişken, fonksiyon veya sınıf ismi, okuyucuya "ne olduğunu" ve "neden var olduğunu" anlatmalı. Tek harfli değişkenler, anlamsız kısaltmalar ve bağlamdan koparıldığında hiçbir şey ifade etmeyen isimler, kodun anlaşılabilirliğini doğrudan zedeliyor.

# Kötü
def calc(d, r):
    return d * r * 0.01

# İyi
def calculate_discount_amount(price, discount_rate_percent):
    return price * discount_rate_percent * 0.01

İkinci versiyonu okurken ne yaptığını anlamak için fonksiyon gövdesine bile bakmanız gerekmiyor. İsim kendi açıklamasını yapıyor.

2. Fonksiyonlar Tek Bir İş Yapmalı

Single Responsibility Principle (SRP), nesne yönelimli tasarımın temel taşlarından biri. Fonksiyonlar için de geçerli: bir fonksiyon yalnızca bir şey yapmalı ve onu iyi yapmalı. "Ve" bağlacını kullanmadan fonksiyonun ne yaptığını açıklayamıyorsanız, muhtemelen ikiye bölmeniz gerekiyor.

// Kötü - birden fazla sorumluluk
function processUserData(user) {
    validateUser(user);
    saveToDatabase(user);
    sendWelcomeEmail(user);
    updateAnalytics(user);
}

// İyi - her fonksiyon tek iş yapıyor
function registerUser(user) {
    const validatedUser = validateUser(user);
    const savedUser = saveToDatabase(validatedUser);
    notifyNewRegistration(savedUser);
    return savedUser;
}

20 satır kuralı pratik bir başlangıç noktası: bir fonksiyon 20 satırı aşıyorsa bölmeyi düşünün. Elbette katı bir kural değil, ama iyi bir uyarı sinyali.

3. DRY Prensibi: Kendini Tekrar Etme

"Don't Repeat Yourself" — aynı mantığı farklı yerlerde kopyala-yapıştır yapmak, bakım kaosunun en kısa yolu. Aynı kod parçası üç farklı yerde varsa ve bir hata düzeltmeniz gerektiğinde üç yeri de güncellemeniz gerekir; birini unutursanız tutarsızlık doğar.

# Kötü - aynı doğrulama üç yerde tekrarlanıyor
def create_user(email):
    if not "@" in email:
        raise ValueError("Geçersiz e-posta")
    # ...

def update_user(email):
    if not "@" in email:
        raise ValueError("Geçersiz e-posta")
    # ...

# İyi - tek bir yerde tanımlı
def validate_email(email):
    if not "@" in email:
        raise ValueError("Geçersiz e-posta")

def create_user(email):
    validate_email(email)
    # ...

4. Yorum Yerine Okunabilir Kod Yaz

Yorumlar kötü kodu açıklamak için kullanıldığında güvenilmez olur: kod değişir, yorum unutulur ve artık yalan söyleyen bir belgelendirme oluşur. En iyi yorum, hiç yoruma gerek bırakmayan koddur.

// Kötü
// Kullanıcının 18 yaşından büyük ve premium üye olup olmadığını kontrol et
if (user.age > 18 && user.membership === 'premium') { ... }

// İyi - kod kendini açıklıyor
const isEligibleForPremiumContent = user.age > 18 && user.isPremiumMember();
if (isEligibleForPremiumContent) { ... }

Yorumun gerçekten gerekli olduğu durumlar var: karmaşık bir algoritmanın neden seçildiğini açıklamak, harici API'nin garip bir davranışını belgelemek veya kasıtlı bir geçici çözümü işaretlemek gibi. Ama bu istisnalar, kural değil.

5. Fonksiyon Parametrelerini Az Tut

Martin'e göre ideal parametre sayısı sıfır, bir parametre mükemmel, iki parametre kabul edilebilir, üç parametre sorgulanabilir, dörtten fazlası ciddi bir tasarım sorununa işaret ediyor. Çok fazla parametre, fonksiyonun çok fazla şey yapmaya çalıştığının işareti.

# Kötü
def create_order(user_id, product_id, quantity, price, discount, address, payment_method):
    pass

# İyi - ilgili parametreler nesne altında gruplanıyor
def create_order(user_id, order_details):
    # order_details: { product_id, quantity, price, discount, address, payment_method }
    pass

6. Erken Return Kullan, Derin İç İçe Yapıdan Kaçın

Derin iç içe if blokları (bazıları "arrow code" der) kodu okumayı zorlaştırıyor. Guard clause (koruyucu koşul) kalıbı bu problemi çözüyor: geçersiz durumları fonksiyonun başında tespit edip erken return yapıyorsunuz.

// Kötü - derin iç içe yapı
function processPayment(user, amount) {
    if (user) {
        if (user.isActive) {
            if (amount > 0) {
                if (user.balance >= amount) {
                    // gerçek iş mantığı burada
                }
            }
        }
    }
}

// İyi - erken return ile düz akış
function processPayment(user, amount) {
    if (!user) return;
    if (!user.isActive) return;
    if (amount <= 0) return;
    if (user.balance < amount) return;

    // gerçek iş mantığı burada - temiz ve düz
}

7. Global State'ten Uzak Dur

Global değişkenler, kodun herhangi bir yerinden değiştirilebildiği için hata ayıklamayı son derece güçleştiriyor. Bir fonksiyon, girdi parametrelerinden bağımsız olarak global state'e bağımlıysa test edilmesi de zorlaşıyor. Mümkün olduğunca fonksiyonların yalnızca kendi parametrelerine bağlı, yan etkisiz (pure function) yapıda olmasını hedefleyin.

8. Hataları Susturma, Ele Al

Boş catch blokları, try-except ile hatayı yakalamak ama hiçbir şey yapmamak — bunlar gerçek hataları sessizce yutarak ileride çok daha büyük sorunların tohumunu atıyor.

# Kötü
try:
    result = risky_operation()
except Exception:
    pass  # sssst, kimse duymasın

# İyi
try:
    result = risky_operation()
except SpecificException as e:
    logger.error(f"İşlem başarısız: {e}")
    raise OperationFailedError("Beklenen hata oluştu") from e

9. Testler Yaz: Kodu Değiştirmeyi Kolaylaştırır

Test yazmak kodu yavaşlatmıyor, uzun vadede hızlandırıyor. Testleri olmayan bir kodu değiştirmek, ağ olmadan cambazlık yapmak gibi: her adımda neyin kırıldığını bilemezsiniz. Test Driven Development (TDD) disiplinini benimsemek zor olsa da en azından kritik iş mantığı için unit testler yazmak vazgeçilmez.

def test_calculate_discount_amount():
    assert calculate_discount_amount(100, 20) == 20.0
    assert calculate_discount_amount(200, 10) == 20.0
    assert calculate_discount_amount(0, 50) == 0.0

def test_calculate_discount_amount_raises_on_negative_price():
    with pytest.raises(ValueError):
        calculate_discount_amount(-100, 20)

10. Refactoring: Kodu Temizlemenin Tek Yolu

İzci kuralı: "Kampı geldiğinden daha temiz bırak." Bir kodu her dokunduğunuzda biraz daha iyi hale getirme disiplini, zamanla kümülatif olarak muazzam bir fark yaratıyor. Büyük yeniden yazım projeleri genellikle hayal kırıklığıyla sonuçlanır; küçük, sürekli refactoring ise sürdürülebilir temizliğin yoludur.

Refactoring için en değerli araçlar: IDE'nin otomatik refactoring özellikleri, kapsamlı bir test suite (değişikliklerden emin olmanızı sağlar) ve takımdaki herkesin benimsediği kodlama standartları.

Code Review Kültürü

Bu kuralların tamamını tek başınıza uygulamak zorunda değilsiniz. Code review kültürü, ekibin ortak standardı yükseltmesinin en etkili yolu. Her pull request'te yalnızca hataları değil, okunabilirliği, isimlendirmeyi ve gereksiz karmaşıklığı da sorgulama alışkanlığı edinin. Eleştiri kişiyi değil kodu hedef almalı; bu kültür yerleştiğinde tüm ekip birlikte büyür.

📌 Önemli Noktalar