BEST PRACTICES8m READ10 Nisan 2026

Clean Code Prensipleri: Türkçe Rehber

Temiz kod yazmanın temel prensipleri ve pratik örnekler.

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 = 86400
def calc(a, b):
    return a * b * d
 
# İYİ
SECONDS_PER_DAY = 86_400
 
def calculate_monthly_cost(daily_rate: float, days: int) -> float:
    return daily_rate * days * SECONDS_PER_DAY
// TYPESCRIPT //
// KÖTÜ — ne döndürdüğü belirsiz
function get(id: string) { ... }
const data = getData();
const flag = check();
 
// İYİ — niyeti açık
async 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 fonksiyon
function 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 üç yerde
function 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 kurallar
import { 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ır
i += 1
 
# Kullanıcıyı veritabanından getir
user = 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çin
def 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 hata
try {
  await sendEmail(user.email);
} catch (e) {}
 
// KÖTÜ — hata kodları döndürmek
function parseUser(data: unknown): { user?: User; error?: string } {
  // ...
}
 
// İYİ — hataları fırlat, çağıran karar versin
async 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

PrensipAçıklamaPratik Kural
S — Single ResponsibilityBir sınıf bir nedenden değişmeliSınıf ismi "ve" içermiyorsa iyi
O — Open/ClosedDeğişime kapalı, genişlemeye açıkif type == 'X' yerine interface
L — Liskov SubstitutionAlt sınıf üst sınıfın yerine geçebilmeliOverride'da davranışı bozmayın
I — Interface SegregationKullanılmayan metodlar implement etmeKüçük interface'ler > büyük interface
D — Dependency InversionSomut değil soyuta bağlanConstructor'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.