Robert C. Martin'in "Clean Code" kitabından yola çıkan bu prensipler, okunabilir, bakımı kolay ve hatasız kod yazmanın temelini oluşturur. Iyi kod sadece çalışan kod değil; altı ay sonra dönüp baktığınızda ne yaptığını anlayabildiğiniz koddur.
1. Anlamlı İsimler
Kodun en büyük kısmı okunmaktan oluşur. İsimler niyeti açıklamalı:
// PYTHON //
# KÖTÜd = 86400def calc(a, b): return a * b * d# İYİSECONDS_PER_DAY = 86_400def calculate_monthly_cost(daily_rate: float, days: int) -> float: return daily_rate * days * SECONDS_PER_DAY
// TYPESCRIPT //
// KÖTÜ — ne döndürdüğü belirsizfunction get(id: string) { ... }const data = getData();const flag = check();// İYİ — niyeti açıkasync function fetchUserById(userId: string): Promise<User | null> { ... }const activeUsers = await fetchActiveUsers();const isEmailVerified = await checkEmailVerification(userId);
2. Küçük Fonksiyonlar ve Tek Sorumluluk
Her fonksiyon yalnızca bir şey yapmalıdır:
// PHP //
// KÖTÜ — her şeyi yapan bir fonksiyonfunction processOrder(array $data): string { // Validate if (empty($data['email'])) throw new \Exception('Email required'); if ($data['amount'] <= 0) throw new \Exception('Invalid amount'); // Charge $charge = Stripe::charge(['amount' => $data['amount'], ...]); // Save to DB $order = Order::create([...]); // Send email Mail::to($data['email'])->send(new OrderConfirmation($order)); // Update stock foreach ($data['items'] as $item) { Product::decrement('stock', $item['qty']); } return $order->id;}// İYİ — sorumluluklar ayrıştırılmışclass OrderService { public function __construct( private OrderValidator $validator, private PaymentGateway $payment, private OrderRepository $orders, private StockManager $stock, private Mailer $mailer, ) {} public function createOrder(OrderData $data): Order { $this->validator->validate($data); $charge = $this->payment->charge($data->amount, $data->paymentMethod); $order = $this->orders->create($data, $charge->id); $this->stock->decrementForOrder($order); $this->mailer->sendConfirmation($order); return $order; }}
3. DRY — Don't Repeat Yourself
Tekrar eden kod, değişiklik yapıldığında tüm kopyaların güncellenmesini gerektirir:
// TYPESCRIPT //
// KÖTÜ — aynı validasyon üç yerdefunction createUser(email: string, name: string) { if (!email.includes('@')) throw new Error('Invalid email'); if (name.length < 2) throw new Error('Name too short'); // ...}function updateUser(id: string, email: string, name: string) { if (!email.includes('@')) throw new Error('Invalid email'); // Kopya if (name.length < 2) throw new Error('Name too short'); // Kopya // ...}// İYİ — zod veya validation modülü ile merkezi kurallarimport { z } from 'zod';const UserSchema = z.object({ email: z.string().email(), name: z.string().min(2).max(100),});function createUser(data: unknown) { const validated = UserSchema.parse(data); // ...}function updateUser(id: string, data: unknown) { const validated = UserSchema.partial().parse(data); // ...}
4. Yorumlar: Ne Zaman Yazmalı, Ne Zaman Yazmamalı
// PYTHON //
# KÖTÜ — kodun ne yaptığını anlatan yorum (kod zaten söylüyor)# i'yi 1 artıri += 1# Kullanıcıyı veritabanından getiruser = db.query(User).filter(User.id == user_id).first()# İYİ — NEDEN yapıldığını açıklayan yorum# Türk karakterlerini ASCII'ye dönüştür — PostgreSQL full-text search içindef normalize_turkish(text: str) -> str: return text.translate(str.maketrans('çğıöşüÇĞİÖŞÜ', 'cgiosucgiosu'))# BCRYPT rounds=12: 2026 için minimum güvenli değer (NIST SP 800-63B)BCRYPT_ROUNDS = 12
5. Hata Yönetimi
// TYPESCRIPT //
// KÖTÜ — boş catch, sessiz hatatry { await sendEmail(user.email);} catch (e) {}// KÖTÜ — hata kodları döndürmekfunction parseUser(data: unknown): { user?: User; error?: string } { // ...}// İYİ — hataları fırlat, çağıran karar versinasync function sendNotification(userId: string, message: string): Promise<void> { const user = await findUserOrThrow(userId); // NotFoundError fırlatır await emailService.send(user.email, message); // NetworkError fırlatabilir}// İYİ — Result tipi pattern (fonksiyonel yaklaşım)type Result<T, E = Error> = { ok: true; data: T } | { ok: false; error: E };async function safeFetch(url: string): Promise<Result<Response>> { try { return { ok: true, data: await fetch(url) }; } catch (error) { return { ok: false, error: error as Error }; }}
6. SOLID Prensiplerinin Özeti
Prensip
Açıklama
Pratik Kural
S — Single Responsibility
Bir sınıf bir nedenden değişmeli
Sınıf ismi "ve" içermiyorsa iyi
O — Open/Closed
Değişime kapalı, genişlemeye açık
if type == 'X' yerine interface
L — Liskov Substitution
Alt sınıf üst sınıfın yerine geçebilmeli
Override'da davranışı bozmayın
I — Interface Segregation
Kullanılmayan metodlar implement etme
Küçük interface'ler > büyük interface
D — Dependency Inversion
Somut değil soyuta bağlan
Constructor'a interface inject et
Pratik Kontrol Listesi
Kod review öncesi kendinize şu soruları sorun:
▸İsimler niyeti açıkça ifade ediyor mu?
▸Her fonksiyon tek bir şey mi yapıyor?
▸Tekrarlayan kod var mı (3+ kez)?
▸Yorumlar "neden"i açıklıyor mu, "ne"yi değil?
▸Error handling sessiz catch blokları var mı?
▸Test edilebilir mi? (Constructor injection var mı?)
Sonuç
Clean Code bir hedeftir, mükemmeliyetçilik değil. Her satır yazarken "bunu altı ay sonra başka bir geliştirici okuyacak" diye düşünmek, kodun kalitesini zamanla artırır. Küçük, tutarlı iyileştirmeler büyük fark yaratır.