📌 Hızlı Özet & Temel Çıkarım:
SOLID Prensipleri ve Temiz Kod, yazılımın zaman içinde çürümesini (code rot) önleyen, test edilebilirliği artıran ve yeni özellik ekleme maliyetini düşüren temel tasarım kurallarıdır. Ancak bu kuralların dogmatik bir din gibi uygulanması; 3 satırlık basit bir işlem için onlarca soyutlama sınıfı (over-engineering) yaratarak kodu okunamaz hale getirebilir. Gerçek mühendislik başarısı; prensipleri pragmatik bir dengede tutup sistemin bakımını kolaylaştırmaktır.
1. SOLID Prensipleri Neyi Çözmeyi Amaçlar?
Karmaşıklaşan yazılım projelerinde bir özelliği değiştirdiğinizde bambaşka bir yerin kırılması (fragility) veya kodun başka bir modülde yeniden kullanılamaması (immobility) tipik mimari iflas belirtileridir.
SOLID beş temel ilkeden oluşur:
- S - Single Responsibility Principle (Tek Sorumluluk): Bir sınıfın veya modülün değişmesi için yalnızca tek bir nedeni olmalıdır.
- O - Open/Closed Principle (Açık/Kapalı): Yazılım varlıkları geliştirmeye açık, fakat kaynak kodunu değiştirmeye kapalı olmalıdır.
- L - Liskov Substitution Principle (Liskov Yerine Geçme): Alt sınıflar, üst sınıflarının yerine geçtiğinde programın davranışı bozulmamalıdır.
- I - Interface Segregation Principle (Arayüz Ayrımı): İstemciler kullanmadıkları metotları barındıran şişkin arayüzlere bağımlı olmaya zorlanmamalıdır.
- D - Dependency Inversion Principle (Bağımlılıkların Tersine Çevrilmesi): Üst seviye modüller alt seviye modüllere değil, soyutlamalara (interfaces) bağımlı olmalıdır.
2. Dependency Inversion (DIP) ile Test Edilebilir Mimari
Geleneksel kötü tasarım: Bir servis doğrudan somut bir e-posta veya veritabanı sürücüsünü new ile kendi içinde üretir. Bu durumda o servisi birim testine sokmak imkansızdır.
Pragmatik modern yaklaşım (Python örneği):
from abc import ABC, abstractmethod
# 1. Soyutlama (Arayuz)
class TelemetrySender(ABC):
@abstractmethod
def transmit(self, payload: dict) -> bool:
pass
# 2. Somut Uretim Surucusu (Radio LoRa)
class LoRaTelemetrySender(TelemetrySender):
def transmit(self, payload: dict) -> bool:
# Fiziksel LoRa modulu uzerinden gonderim...
return True
# 3. Test Icin Mock Surucu
class MockTelemetrySender(TelemetrySender):
def __init__(self):
self.sent_packets = []
def transmit(self, payload: dict) -> bool:
self.sent_packets.append(payload)
return True
# 4. Ust Seviye Yonetici Sinif (Soyutlamaya Bagimli)
class AutonomousNavigationCore:
def __init__(self, sender: TelemetrySender):
self.sender = sender
def broadcast_position(self, lat: float, lon: float):
packet = {"lat": lat, "lon": lon, "timestamp": 1726000000}
return self.sender.transmit(packet)
Bu kurgu sayesinde navigasyon çekirdeğini test ederken sahaya çıkıp fiziksel LoRa anteni açmaya gerek kalmaz; MockTelemetrySender verilerek saniyeler içinde 100 farklı test koşulabilir.
3. Aşırı Mühendislik (Over-Engineering) Tuzağı
Her kuralın bir bedeli vardır. Eğer bir projede sadece tek bir ödeme yöntemi olacaksa ve bu durum 5 yıl değişmeyecekse, 10 farklı soyutlama katmanı ve factory deseni yazmak mühendislik değil zaman israfıdır (YAGNI - You Aren’t Gonna Need It).
Prensipler bir kural kitabı değil, kodunuz karmaşıklaşmaya ve test edilememeye başladığında başvurulacak bir refactoring pusulasıdır.
4. İlgili Konular ve İç Bağlantılar
- Yazılım Test Mühendisliği ve Mocking Stratejileri — Arayüzlerin birim testlerinde kullanımı.
- Gerçek Dünyada Tasarım Kalıpları — SOLID ilkelerini hayata geçiren kalıplar.
- Modern C++ ile Yüksek Performanslı Sistem Programlama — Soyutlamaların sıfır ek maliyetle derlenmesi.
5. Sıkça Sorulan Sorular
“Temiz Kod” performans kaybına yol açar mı?
Çoğu web, API ve kurumsal uygulamada fonksiyon bölmelerinin veya arayüzlerin getirdiği nanometrik maliyet tamamen önemsizdir; okunabilirlik ve hata olmaması çok daha değerlidir. Ancak mikrosaniye seviyesinde çalışan robotik kontrol döngülerinde sanal fonksiyon tabloları (vtable lookup) ölçülmeli ve gerekirse statik polimorfizm (C++ CRTP veya Templates) tercih edilmelidir.
Bir fonksiyon maksimum kaç satır olmalıdır?
Kesin bir sayı olmamakla birlikte, bir fonksiyonun tek bir ekrana sığması (yaklaşık 20-30 satır) ve tek bir işi mükemmel yapması endüstriyel kabul gören pratik bir ölçüttür.
6. Boy Scout Kuralı ve Teknik Borcun Ödenmesi
Projelerin zamanla karmaşıklaşıp okunamaz hale gelmesini önlemenin en pratik yolu İzci Kuralı (Boy Scout Rule)’dır: “Bulduğun kamp yerini, bulduğundan daha temiz bırak.”
Yazılım geliştiriciler bir dosyada hata düzeltirken veya yeni bir özellik eklerken:
- Anlamsız isimlendirilmiş tek bir değişken adını düzeltmeli,
- 50 satırı aşmış dev bir fonksiyondan tek bir anlamlı alt fonksiyon çıkarmalı,
- Kullanılmayan ölü bir import’u silmelidir.
Büyük ve riskli refactoring projelerine kalkışmak yerine bu mikro temizlik alışkanlığını tüm ekibe yaymak, kod tabanının yıllar geçse bile taze, okunabilir ve genişletilebilir kalmasını sağlar.
7. Kod Kokuları (Code Smells) ve Otomatik Linter Kuralları
Temiz kod standartlarını ekip genelinde korumanın yolu geliştiricilerin insafına güvenmek değil, CI/CD hattına otomatik statik analiz araçları (Ruff, ESLint, SonarQube) yerleştirmektir.
En sık rastlanan kod kokuları ve çözümleri:
- Uzun Parametre Listesi: Bir fonksiyona 5’ten fazla parametre geçiliyorsa bir DTO (Data Transfer Object) veya konfigürasyon nesnesi tanımlanmalıdır.
- Geçici Alanlar (Temporary Fields): Bir nesnenin yalnızca belirli fonksiyon çağrılarında değer aldığı alanlar ayrı bir yardımcı sınıfa taşınmalıdır.
- Kıskanç Fonksiyon (Feature Envy): Kendi sınıfının verileri yerine sürekli başka bir sınıfın metotlarını çağıran fonksiyonlar, ait olduğu asıl sınıfa taşınmalıdır.
8. Kendi Kendini Belgeleyen Kod (Self-Documenting Code) ve Yorum Satırı Dengesi
Temiz kod felsefesinde en iyi yorum, hiç yazılmaya ihtiyaç duyulmayan yorumdur. Eğer bir fonksiyonun ne yaptığını açıklamak için üzerine 5 satır açıklama yazmanız gerekiyorsa, fonksiyonun adı veya parametreleri kötü tasarlanmış demektir.
Örnek Karşılaştırma:
- Kötü:
// Kullanicinin 18 yasindan buyuk ve aboneligi aktif mi kontrol et->if (u.a > 18 && u.s == 1) - Temiz:
if (user.is_adult() and user.has_active_subscription()):
Yorum satırları “kodun ne yaptığını” (WHAT) değil; mimari kararın arkasındaki “nedenini” (WHY) açıklamak için kullanılmalıdır. Örneğin: “Bu bekleme süresi, STM32 çipinin donanımsal voltaj regülasyonu oturana kadar zorunludur.”