images.webp

Selamlar arkadaşlar,
Biliyorsunuz daha önce yazılımla alakalı rehberler açmıştım. Şimdi işin özüne giriyoruz yani temiz kod nasıl yazılır, nasıl okunabilir bunları öğreneceğiz. Yazı uzun olacak okurken sıkılmazsınız umarım. Çayınızı kahvenizi alın başlıyoruz. Konuyu okumadan önce şu rehberlerime göz atmanızı öneririm;

Giriş: Kod Yazmak Aslında Kitap Yazmaktır

images (2).webp

Evet. Robert C. Martin (nam-ı diğer Uncle Bob) abimizin şahane bir sözü var: "Kodun okunma sayısı, yazılma sayısından katbekat fazladır."

Bu basit gerçek aslında yazılım mesleğinin en büyük paradoksunu yüzümüze vuruyor. Biz kodu yazarken genelde "abi çalışsın yeter ya, proda atalım gitsin" kafasında oluyoruz. Ama o kod aylar sonra, belki bir hata çıktığında, belki yeni bir özellik ekleneceğinde karşımıza dikiliyor. İşte o zaman, vaktiyle yaptığımız her kestirme yol bize harcanan saatler olarak geri dönüyor.

Temiz kod dediğimiz şey sadece derleyicinin veya tarayıcının değil, insanların da yani benim, senin, rahatça anlayabileceği, geliştirebileceği koddur. Tıpkı iyi yazılmış bir roman gibi yukarıdan aşağıya su gibi akmalı. Okuyanı "burada ne demek istemiş şair?" diye düşündürmemeli, şaşırtmamalı.


Neden Temiz Kod Yazmak Bu Kadar Zor? (Becerebilen Var mı?)

Leonardo da Vinci reyiz ne demiş: "Basitlik, en üst düzey sofistikeliktir." Yazılım dünyasında bu lafın doğruluğunu her gün test ediyoruz.

Kodu karmaşıklaştırmak dünyanın en kolay işi arkadaşlar. Her yeni istek geldiğinde basarsın if-else, acil durumlarda yapıştırırsın patch, olur biter. Ama o karmaşıklığı alıp sadeleştirmek? İşte o uzmanlık ister.

Temiz kodun önündeki en büyük engel ne biliyor musunuz? Zaman baskısı. Müşteri ensede... Kimse kodun kalitesine bakmaz, yetişti mi? diye sorar. Bu baskı altında yazılımcılar ne yapar? "Teknik Borç" biriktiririz. Aynen banka borcu gibi bu borç faiz işletir. Günün sonunda ya planlı bir şekilde refactoring yaparak ödersin, ya da sistem elinde patlar, iflas edersin.

Bir de şu "Çalışıyorsa dokunma" mantığı var. En tehlikeli kafa budur bana kalırsa. Bu kafa yapısı kodu zamanla çürütür. Kırık Camlar Teorisi'ni duydunuz mu? Bir mahallede kırık bir cam varsa ve tamir edilmezse, kısa sürede millet "burası zaten batık" der, diğer camları da indirmeye başlar. Kod tabanı da aynen böyledir. Bir yer kötü yazılmışsa, gelen diğer geliştiriciler de "aman zaten çöp burası" der, aynı kalitesizlikle devam eder.


Temiz Kodun Temel Taşları: KISS ve DRY

İki prensibimiz var:
  1. KISS (Keep It Simple Stupid): Yani "Basit tut şapşal". Gereksiz atraksiyonlara girme. Bir problemi çözmenin en basit yolu, genelde en doğru yoldur.​
  2. DRY (Don't Repeat Yourself): Yani "Kendini tekrar etme". Aynı kod bloğunu kopyala-yapıştır yapıyorsan dur. Onu bir fonksiyon haline getirmenin vakti gelmiştir.​


İsimlendirme: Kodun Sözlüğü

Bana sorarsanız isimlendirme temiz kodun yarısıdır. Bir değişkenin veya fonksiyonun adı, onun ne halt yediğini anlatmalı.
Bakın şu örneğe:
Kod:
# Kötü İsimlendirme (Bunu yapanı döverler)
d = 5
x = get_data()
temp = calculate()

# Temiz İsimlendirme (Oh be dünya var mış)
gun_sayisi = 5
musteri_listesi = get_active_customers()
toplam_fiyat = calculate_order_total()
Bir de "Sihirli Sayılar" (Magic Numbers) olayı var. Kodun en büyük düşmanı. Kodun ortasında bir anda "5" diye bir rakam var. Ne bu 5? Elma mı, armut mu? Aranabilir de değil.
Kod:
# Kötü Kullanım
if len(users) > 5:
    raise Exception("Limit aşıldı")

# Temiz Kullanım
MAX_USER_LIMIT = 5
if len(users) > MAX_USER_LIMIT:
    raise Exception("Kullanıcı limiti aşıldı")
Tutarlılık da çok önemli. Bir yerde veriyi çekerken get dediysen, başka yerde fetch deme. Okuyanın kafası yanar. Tüm projede aynı terimleri kullanın ki millet kodu daha hızlı öğrensin.


Fonksiyonlar: Tek İş, İyi İş

Bir fonksiyon sadece tek bir işi yapmalı babacım onu da iyi yapmalı. Söylemesi kolay ama en çok ihlal ettiğimiz kural bu.
Alın size çorba gibi bir fonksiyon:
Kod:
# Kötü Fonksiyon: Her işe burnunu sokuyor
def process_order(order):
    # Validasyon (Doğrulama)
    if not order.items:
        raise ValueError("Sepet boş")
    if not order.customer.address:
        raise ValueError("Adres yok")
    
    # Fiyat hesaplama
    total = 0
    for item in order.items:
        total += item.price * item.quantity
        if item.discount:
            total -= item.discount
            
    # Veritabanına kaydet
    db = MySQLConnection()
    db.connect()
    db.execute("INSERT INTO orders...")
    
    # Email gönder
    smtp = SMTPClient()
    smtp.send(order.customer.email, "Siparişiniz alındı")
    
    # Fatura yazdır
    printer = Printer()
    printer.print(order.invoice)
    
    return total
Gördüğünüz gibi fonksiyon beş farklı iş yapıyor: Validasyon, hesaplama, veritabanı, mail ve yazdırma. Bunu parçalamak lazım:
Kod:
# Temiz Fonksiyonlar: Herkes kendi işine bakıyor
def validate_order(order):
    if not order.items:
        raise ValueError("Sepet boş")
    if not order.customer.address:
        raise ValueError("Adres yok")

def calculate_order_total(order):
    total = 0
    for item in order.items:
        total += item.price * item.quantity
        total -= item.discount or 0
    return total

def save_order(order, repository):
    repository.save(order)

def notify_customer(order, notification_service):
    notification_service.send_order_confirmation(order)

def process_order(order, repository, notification_service):
    # Ana fonksiyon sadece orkestra şefi gibi diğerlerini yönetiyor
    validate_order(order)
    order.total = calculate_order_total(order)
    save_order(order, repository)
    notify_customer(order, notification_service)
    return order
Bir de parametre sayısı mevzusu var. İdeal parametre sayısı sıfırdır. Sonra bir, hadi bilemedin iki. Üç ve fazlası tehlike çanlarıdır. Öyle durumda parametreleri bir nesneye (object) çevirin.
Kod:
# Kötü: Destan gibi parametre
def create_user(name, surname, email, phone, address, city, country, postal_code):
    pass

# Temiz: Parametreler nesne oldu
class UserInfo:
    def __init__(self, name, surname, email, phone, address):
        self.name = name
        self.surname = surname
        self.email = email
        self.phone = phone
        self.address = address

def create_user(user_info):
    pass

Yorum Satırları: Başarısızlığın İtirafı

Başlık sert geldi dimi? Ama gerçek bu. Eğer yazdığın kodu açıklamak için yorum yazmaya ihtiyaç duyuyorsan, kodun yeterince açık değildir hacı. Yorum yazacağına git kodu düzelt.
Kod:
# Kötü: Yorum ile durumu kurtarmaya çalışmak
# Kullanıcının 18 yaşından büyük olup olmadığını kontrol et
if u.a >= 18:
    pass

# Temiz: Kod kendini anlatıyor
def is_adult(user):
    LEGAL_AGE = 18
    return user.age >= LEGAL_AGE

if is_adult(user):
    pass
Yorumlar sadece "Neden?" sorusuna cevap vermeli. İş mantığı, yasal zorunluluk vs. varsa yazılır.
Kod:
# İyi Yorum: Sebebini açıklıyor
# KVKK gereği kullanıcı verileri 6 ay sonra anonimleştirilmeli
ANONYMIZATION_PERIOD_DAYS = 180

SOLID Prensipleri

SOLID, Nesne Yönelimli Programlama'nın 5 şartıdır. Yazılımın bakımını kolaylaştırır, genişletilebilir yapar.

S - Single Responsibility Principle (Tek Sorumluluk Prensibi)
Bir sınıfın değişmesi için SADECE tek bir sebebi olmalı. Sınıfınız İsviçre Çakısı gibi her işi yapıyorsa orada durun.
Kod:
# HATALI KOD: Order sınıfı her şeyi yapıyor
class Order:
    def __init__(self, items):
        self.items = items
        self.total = 0
    
    def calculate_total(self):
        for item in self.items:
            self.total += item.price * item.quantity
        return self.total
    
    def save_to_database(self): # Veritabanı işi?
        connection = MySQLConnection()
        connection.connect()
        connection.execute(f"INSERT INTO orders VALUES ({self.total})")
        connection.close()
    
    def print_invoice(self): # Yazıcı işi?
        printer = Printer()
        printer.initialize()
        printer.print(f"Toplam: {self.total}")
    
    def send_confirmation_email(self): # Mail işi?
        smtp = SMTPClient("smtp.mail.com")
        smtp.send("Siparişiniz alındı")
Bu sınıfın değişmesi için 4 sebep var: Hesaplama değişirse, DB değişirse, yazıcı değişirse, mail sistemi değişirse... Hepsini ayıralım:
Kod:
# TEMİZ KOD: Her sınıfın tek sorumluluğu var
class Order:
    def __init__(self, items):
        self.items = items
        self.total = 0

class OrderCalculator: # Sadece hesap yapar
    def calculate_total(self, order):
        total = 0
        for item in order.items:
            total += item.price * item.quantity
        order.total = total
        return total

class OrderRepository: # Sadece veritabanı işleri
    def __init__(self, database_connection):
        self.connection = database_connection
    
    def save(self, order):
        self.connection.execute(
            "INSERT INTO orders (total) VALUES (?)", [order.total]
        )

class OrderPrinter: # Sadece yazdırma
    def __init__(self, printer):
        self.printer = printer
    
    def print_invoice(self, order):
        self.printer.print(f"Toplam: {order.total}")

class OrderNotifier: # Sadece bildirim
    def __init__(self, email_service):
        self.email_service = email_service
    
    def send_confirmation(self, order, customer_email):
        self.email_service.send(
            to=customer_email,
            subject="Sipariş Onayı",
            body=f"Siparişiniz alındı. Toplam: {order.total}"
        )
Artık veritabanı mı değişti? Sadece OrderRepository ile uğraşırsın, diğerleri etkilenmez.
O - Open/Closed Principle (Açık/Kapalı Prensibi)
Yazılım gelişime açık, değişime kapalı olmalı. Yani yeni özellik eklerken çalışan kodu bozmamalısın.
En yaygın hata indirim sistemlerinde yapılıyor. Yeni indirim gelince if-else eklemek bu prensibi deler.
Kod:
# HATALI KOD: Her yeni indirimde burayı mıncıklamak lazım
class DiscountCalculator:
    def calculate(self, customer_type, amount):
        if customer_type == "ogrenci":
            return amount * 0.20
        elif customer_type == "emekli":
            return amount * 0.15
        elif customer_type == "ogretmen":
            return amount * 0.10
        elif customer_type == "doktor": # Yeni eklendi!
            return amount * 0.12
        elif customer_type == "asker": # Bu da yeni!
            return amount * 0.18
        else:
            return 0
Her indirimde burayı açıp kod eklemek hata riskini artırır. Çözüm soyutlama kullanmak:
Kod:
# TEMİZ KOD: Yeni indirim için sadece yeni sınıf ekle
from abc import ABC, abstractmethod

class DiscountStrategy(ABC):
    @abstractmethod
    def calculate(self, amount):
        pass

class StudentDiscount(DiscountStrategy):
    def calculate(self, amount):
        return amount * 0.20

class RetiredDiscount(DiscountStrategy):
    def calculate(self, amount):
        return amount * 0.15

# ... Diğer sınıflar ...

class DiscountCalculator:
    def __init__(self, strategy: DiscountStrategy):
        self.strategy = strategy
    
    def calculate(self, amount):
        return self.strategy.calculate(amount)

# Kullanım
student_calculator = DiscountCalculator(StudentDiscount())
discount = student_calculator.calculate(100) # 20 döner

# Yeni indirim türü eklemek için ana koda dokunmadan:
class MilitaryDiscount(DiscountStrategy):
    def calculate(self, amount):
        return amount * 0.18
Kod değişime kapalı (Calculator'a dokunmadık), gelişime açık (Yeni MilitaryDiscount ekledik).
L - Liskov Substitution Principle (Liskov'un Yerine Geçme Prensibi)
Alt sınıflar, üst sınıfların yerine geçebilmeli. Program sapıtmamalı. Barbara Liskov ablamızın prensibi.
Kuş örneği klasiktir.
Kod:
# HATALI KOD: Tavuk uçamaz ama Bird sınıfından türüyor
class Bird:
    def __init__(self, name):
        self.name = name
    def fly(self):
        return f"{self.name} uçuyor!"
    def eat(self):
        return f"{self.name} yemek yiyor."

class Eagle(Bird):
    def fly(self):
        return f"{self.name} yükseklerde süzülüyor!"

class Chicken(Bird):
    def fly(self):
        # Tavuk uçamaz! Ne yapacağız?
        raise Exception("Tavuklar uçamaz!")

# Kullanım
def make_bird_fly(bird: Bird):
    print(bird.fly())

eagle = Eagle("Kartal")
chicken = Chicken("Tavuk")
make_bird_fly(eagle) # Çalışır
make_bird_fly(chicken) # PATLADI! Liskov ihlali!
Chicken sınıfı Bird'ün yerine geçemiyor çünkü fly metodu patlıyor. Çözüm yetenekleri ayırmak:
Kod:
# TEMİZ KOD: Yetenekler arayüzlere bölündü
from abc import ABC, abstractmethod

class Bird(ABC):
    # Temel özellikler
    def __init__(self, name):
        self.name = name
    @abstractmethod
    def eat(self): pass

class Flyable(ABC): # Uçabilme yeteneği
    @abstractmethod
    def fly(self): pass

class Swimmable(ABC): # Yüzebilme yeteneği
    @abstractmethod
    def swim(self): pass

class Eagle(Bird, Flyable):
    def eat(self): return "Et yiyor"
    def fly(self): return "Uçuyor"

class Chicken(Bird):
    def eat(self): return "Yem yiyor"
    # Tavuk uçamaz, Flyable değil!

class Duck(Bird, Flyable, Swimmable):
    def eat(self): return "Ekmek yiyor"
    def fly(self): return "Uçuyor"
    def swim(self): return "Yüzüyor"

# Kullanım
def make_it_fly(flyable: Flyable):
    print(flyable.fly())

eagle = Eagle("Kartal")
# make_it_fly(chicken) # Derleme hatası verir, kod patlamaz.
I - Interface Segregation Principle (Arayüz Ayrımı Prensibi)
Müşterileri kullanmadıkları metotlara zorlamayın. Şişman interfaceler yerine küçük, odaklı interfaceler yapın.
Kod:
# HATALI KOD: Tek ve şişman bir arayüz
from abc import ABC, abstractmethod

class IOrderService(ABC):
    @abstractmethod
    def calculate_total(self): pass
    @abstractmethod
    def process_online_payment(self): pass
    @abstractmethod
    def process_in_store_payment(self): pass # Mağaza ödemesi

class OnlineOrder(IOrderService):
    def calculate_total(self): return 100
    def process_online_payment(self): pass
    def process_in_store_payment(self):
        # Online siparişte mağaza ödemesi olmaz!
        raise NotImplementedError("Gereksiz metod!")
Burada OnlineOrder sınıfı, kullanmadığı process_in_store_payment metodunu implemente etmek zorunda kalıyor. Çözüm parçalamak:
Kod:
# TEMİZ KOD: Odaklı arayüzler
class ICalculatable(ABC):
    @abstractmethod
    def calculate_total(self): pass

class IOnlinePayable(ABC):
    @abstractmethod
    def process_online_payment(self): pass

class IInStorePayable(ABC):
    @abstractmethod
    def process_in_store_payment(self): pass

class OnlineOrder(ICalculatable, IOnlinePayable):
    # Sadece ihtiyacı olanları alır
    def calculate_total(self): return 100
    def process_online_payment(self): print("Online ödeme")

class InStoreOrder(ICalculatable, IInStorePayable):
    # Sadece ihtiyacı olanları alır
    def calculate_total(self): return 100
    def process_in_store_payment(self): print("Nakit ödeme")
D - Dependency Inversion Principle (Bağımlılığın Tersine Çevrilmesi)
Yüksek seviyeli modüller (iş mantığı), düşük seviyeli modüllere (veritabanı vs.) doğrudan bağımlı olmamalı. İkisi de soyutlamaya (interface) bağımlı olmalı.
Kod:
# HATALI KOD: Doğrudan bağımlılık
class MySQLDatabase:
    def connect(self): print("MySQL bağlandı")
    def execute(self, query): print(f"Sorgu: {query}")

class OrderManager:
    def __init__(self):
        # Doğrudan MySQL'e bağımlı!
        self.database = MySQLDatabase()
    
    def save_order(self, order):
        self.database.connect()
        self.database.execute(...)
Yarın MSSQL'e geçmek istersen OrderManager sınıfını değiştirmek zorundasın.
Kod:
# TEMİZ KOD: Soyutlamaya bağımlılık
from abc import ABC, abstractmethod

class IDatabase(ABC): # Soyutlama
    @abstractmethod
    def connect(self): pass
    @abstractmethod
    def execute(self, query): pass

class MySQLDatabase(IDatabase): # Somut sınıf
    def connect(self): print("MySQL")
    def execute(self, query): print("Sorgu")

class PostgreSQLDatabase(IDatabase): # Somut sınıf
    def connect(self): print("Postgre")
    def execute(self, query): print("Sorgu")

class OrderManager:
    def __init__(self, database: IDatabase):
        # Hangi DB geldiği umurumda değil, IDatabase olsun yeter
        self.database = database
    
    def save_order(self, order):
        self.database.connect()
        self.database.execute(...)

# Kullanım - Dependency Injection
mysql_db = MySQLDatabase()
manager = OrderManager(mysql_db) # MySQL ile çalışır

postgres_db = PostgreSQLDatabase()
manager = OrderManager(postgres_db) # Kod değişmeden Postgre ile çalışır
Bu sayede test yazarken sahte (mock) veritabanı da verebilirsiniz.


Süreç ve Kültür: Temiz Kod Bir Varış Noktası Değil

Arkadaşlar temiz kod bir kere yazıp bitirilen bir iş değil, sürekli bir süreçtir. Bu süreci ayakta tutan 3 şey var:
  1. Refactoring (Yeniden Düzenleme): Kodu yazdın bitti mi? Hayır. Davranışını değiştirmeden yapısını iyileştireceksin. "Çalışan koda dokunma" dersen kaybedersin. Geri dönüp "Bunu nasıl sadeleştiririm?" diye kafa yorman lazım.​
  2. Code Review (Kod İnceleme): Başkasının anlamadığı kod kirli koddur, net. Kod sadece yazan değil, ekip arkadaşları tarafından da okunmalı. Hem bilgi paylaşılır hem standartlar korunur.​
  3. Pair Programming (Eşli Programlama): İki geliştirici tek bilgisayar. Biri yazar, diğeri anlık denetler. Bilgi paylaşımını zirveye çıkarır.​
Son olarak ego yönetimi. Bazı arkadaşlar yazdığı koda duygusal bağlanıyor. Ama eleştiriye açık olmak, "daha iyisi" önerildiğinde egoyu kenara bırakmak profesyonelliktir.


Sonuç

Temiz kod yazmak yetenek değil, disiplindir. SOLID prensipleri bu işin kurallarıdır.
Single Responsibility ile odaklan, Open/Closed ile koru, Liskov ile mirası düzgün kullan, Interface Segregation ile böl, Dependency Inversion ile esnek ol.

Bunları bilmek yetmez, uygulamak lazım. Sürekli pratik, code review ve refactoring şart. Temiz kod lüks değil, yazılımın sağlığı için zorunluluktur.
Umarım faydalı olmuştur dostlar. Elimde birçok kaynak kitap var telif hakkı sorun olur diye paylaşamıyorum. Yöneticilerden dönüş alırsak konuya eklerim. İyi sosyaller herkese!
 
Teşekkürler hocam.
Harika bir konu. Elinize sağlık. Bu temiz kod yazma sanatı Rust'ta da, Go'da da hatta programlama dili olmayan HTML'de de geçerli.
Eyvallah hocam.
Dil veya teknoloji sadece araç, mantık her yerde aynı. HTML'de bile o meşhur div çorbasını engellemek, semantik yazmak için yine düzen şart. Disiplin her yerde lazım :)
İsimlendirme işlerini daha düzgün yapacağım artık. Yoksa döverler onu fark ettim. Elinize sağlık Hocam.
o x, y, temp yazanları ıslak odunla kovalıyorlar dikkat :D
Bende 4-5 aydır belirli bir düzene geçmeye çalışıyorum işte...

Eki Görüntüle 216184

Hiç yorum satırını kullanmayanlara yorumlarınız nedir?
Düzenli ve estetik duruyor, evet. Lakin profesyonel şekilde bakarsak bakımı zor, gereksiz kalabalık ve fazla kişisel bir kod bloğu bu.

Hiç yorum yazmayanlar tembeldir, evet. Ama her satıra yorum yazıp kodu dekorasyona boğanlar da takıntılıdır ve kodu hantallaştırır. İkisinin arası lazım hocam.
 
Eki Görüntüle 216168

Bir de parametre sayısı mevzusu var. İdeal parametre sayısı sıfırdır. Sonra bir, hadi bilemedin iki. Üç ve fazlası tehlike çanlarıdır. Öyle durumda parametreleri bir nesneye (object) çevirin.
Kod:
# Kötü: Destan gibi parametre
def create_user(name, surname, email, phone, address, city, country, postal_code):
    pass

# Temiz: Parametreler nesne oldu
class UserInfo:
    def __init__(self, name, surname, email, phone, address):
        self.name = name
        self.surname = surname
        self.email = email
        self.phone = phone
        self.address = address

def create_user(user_info):
    pass
Parametre konusuna bir ekleme yapmak istiyorum. Az miktarda parametre ile fonksiyon çağrısı yaptığımızda işletim sistemleri (aslında işlemci) bu çağrılar için kullanılan parametreleri stack'e göndermek yerine doğrudan register üzerinden fonksiyona aktarabilir. Bu özellik sayesinde parametredeki değer belleğe uğramadan doğrudan CPU üzerinden aktarılıp veri yolunun yavaşlığından gelen (her ne kadar modern sistemler oldukça hızlı olsa da) etkilenmez.

Linux sistemlerde bu register sayısı 6'dır. Parametre sırasına göre sırasıyla şu registerlar kullanılır: rdi, rsi, rdx, rcx, r8, r9. Teorik olarak 48 baytlık veri registerlar üzerinden aktarılabilir.
Windows sistemlerde ise bu register sayısı 4'tür. sırasıyla rcx, rdx, r8, r9 registerları kullanılır. Burada ise 32 bayt aktarılabilir.
Kaynak:
Linux için
Windows için
Dipnot: Bu registerlar 64-bit registerlardır, 32 bit sistemlerde fastcall yöntemi ile 2 register kullanılabilir (ECX, EDX).
 
Hiç yorum satırını kullanmayanlara yorumlarınız nedir?
Kendini aciklayan bi kodda yorum satiri bulunmaz. Yorum satirlarindan olabildigince kacinirsin. Contract reasoning tasimadigi muddetce veya bilinen edge caseleri aciklamiyorsa, yorum satiri yazilmaz.

Not: Buna function documentation dahil degil. Bir fonksiyon icin aciklamalar da her dail yazilmak zorunda degil ama eger fonksiyon ismi yaptigi isi anlatmak icin yeterli degilse, fonksiyonlar dokumente edilmelidir. Ancak asiri bariz isimlere sahip fonksiyonlarda da dokumantasyon yazmak code smell olarak gecer.

Bir veya birden fazla side effect'e sahip olan bi fonksiyon (ornegin hooklar aracaligiyla event triggerlanmasina sebep oluyordur), dokumentasyon gerektirir. Normalde daha iyisi, bu side effectlerin disariya alinmasidir ama orchestrator fonksiyonlar icin bu tarz durumlar neredeyse kacinilmaz oldugu icin dokumente edilmesinde yarar var.

Ancak substring, slice, starts_with, ends_with benzeri methodlarda eger bilinen ve kullanicilarin dikkatli olmasi gereken bir edge case yoksa, aciklamalar gereksizdir.

Ek olarak yorum satirlari yalan soyleyebilir. Kodun ne yaptigini acikladiginiz bi satir, eski halini acikliyor olabilir. Bu durumda yeni haliyle guncellemezseniz, eski halini anlatacak ve o yorumu okuyan herkese yalan soylemis olacak.