Blog Yazısı

← Tüm Blog Yazılarına Dön
Yazılım Mimarisi & Clean Code • 6 Kasım 2026 • 7 dk okuma

SOLID Prensipleri Nedir? Gerçek Hayat Örnekleriyle Temiz Kod (Clean Code) Rehberi

Yazılım dünyasında spagetti kodlardan kurtulmanın, bakım yapılabilir ve ölçeklenebilir sistemler inşa etmenin altın anahtarı: SOLID prensipleri. S, O, L, I ve D ilkelerinin ne anlama geldiğini, gerçek hayat benzetmeleri ve pratik kod yaklaşımlarıyla inceliyoruz.

Yazılım geliştirmeye ilk başladığımız yıllarda tek bir hedefimiz vardır: Yazdığımız kodun bir şekilde çalışması. Ancak projeler büyüdükçe, yeni özellikler eklendikçe veya aylar sonra kendi yazdığımız koda geri döndüğümüzde acı bir gerçekle karşılaşırız: Spagetti kod. Bir yeri düzeltirken alakasız üç yerin bozulduğu, tek bir satır eklemek için yüzlerce satırın elden geçirilmesi gerektiği o kabus dolu anlar... İşte tam bu noktada, nesne yönelimli programlamanın (OOP) kurucu babalarından Robert C. Martin (namıdiğer Uncle Bob) tarafından sistematik hale getirilen 'SOLID Prensipleri' devreye giriyor.

SOLID; iyi tasarlanmış, esnek, test edilebilir ve gelecekteki değişikliklere kolayca uyum sağlayabilen yazılımlar üretmek için kılavuzluk eden 5 temel tasarım ilkesinin baş harflerinden oluşur. Şimdi bu prensipleri teorik tanımlara boğulmadan, günlük hayattan pratik benzetmelerle tek tek inceleyelim:

1. S - Single Responsibility Principle (Tek Sorumluluk Prensibi):
Bir sınıfın, fonksiyonun veya modülün değişmek için yalnızca ve yalnızca TEK BİR nedeni olmalıdır. Yani bir sınıf sadece bir tek işi mükemmel şekilde yapmalıdır. Günlük hayattan düşünelim: Bir restoranda aşçı hem siparişi alıp, hem yemeği pişirip, hem masalara servis yapıp, hem de kasada fiş kesmeye çalışırsa ne olur? Bir noktada siparişler karışır ve mutfak çöker. Yazılımda da aynıdır. Örneğin bir 'KullaniciYonetimi' sınıfı; hem kullanıcının şifresini doğrulamamalı, hem veritabanına sorgu atmamalı, hem de hoş geldin e-postası göndermemelidir. E-posta gönderimi ayrı bir 'EpostaServisi' sınıfına, veritabanı kayıtları ise 'KullaniciDeposu' (Repository) sınıfına devredilmelidir.

2. O - Open/Closed Principle (Açık/Kapalı Prensibi):
Yazılım varlıkları (sınıflar, modüller, fonksiyonlar) genişletilmeye AÇIK (Open for extension), fakat değiştirilmeye KAPALI (Closed for modification) olmalıdır. Yani sisteme yeni bir özellik eklemek istediğinizde, daha önce test edilmiş ve tıkır tıkır çalışan eski kodları açıp kurcalamak zorunda kalmamalısınız. Örneğin bir e-ticaret sistemine yeni bir ödeme yöntemi (Havale, Kredi Kartı, Kripto) eklerken; ana ödeme fonksiyonunun içine 'if (odemeTipi == Kripto)' diye yeni şartlar eklemek bu prensibi ihlal eder. Bunun yerine 'OdemeYontemi' adında bir arayüz (Interface) tanımlayıp, her ödeme metodunu bu arayüzden türetirseniz; var olan tek bir satır koda bile dokunmadan sisteme 10 yeni ödeme yöntemi entegre edebilirsiniz.

3. L - Liskov Substitution Principle (Liskov İkame Prensibi):
Barbara Liskov tarafından ortaya atılan bu prensip der ki: Alt sınıflar, türedikleri üst sınıfların yerine hiçbir beklenmeyen davranış sergilemeden geçebilmelidir. Ünlü 'Penguen ve Kuş' örneğini ele alalım: Eğer bir 'Kus' üst sınıfı oluşturup içine 'uc()' fonksiyonu koyarsanız ve ardından 'Penguen' sınıfını bu Kuş sınıfından türetirseniz sorun yaşarsınız. Çünkü penguen bir kuştur ama uçamaz! Penguen nesnesi üzerinden 'uc()' fonksiyonunu çağırdığınızda hata fırlatmak zorunda kalırsınız. Çözüm; uçabilen kuşlar için ayrı, uçamayan kuşlar için ayrı soyutlamalar yapmaktır. Bir kod parçası bir üst sınıfı bekliyorsa, onun herhangi bir alt sınıfı verildiğinde hiçbir şey aksamadan çalışabilmelidir.

4. I - Interface Segregation Principle (Arayüz Ayrımı Prensibi):
İstemciler (client sınıflar), asla kullanmadıkları arayüz metotlarına bağımlı olmaya zorlanmamalıdır. Yani devasa, her işi yapan 'şişman (fat)' arayüzler tasarlamayın. Örneğin bir 'Calisan' arayüzü tanımlayıp içine 'kodYaz()', 'tasarimYap()', 'finansRaporuHazirla()' metotlarını doldurursanız; bu arayüzü uygulayan bir Yazılımcı sınıfına boşu boşuna 'finansRaporuHazirla()' metodunu implement ettirmek zorunda kalırsınız. Bunun yerine 'KodYazabilir', 'TasarimYapabilir' gibi küçük, amaca yönelik, odaklanmış arayüzler tasarlamak çok daha temiz bir mimari sunar.

5. D - Dependency Inversion Principle (Bağımlılıkların Tersine Çevrilmesi):
Yüksek seviyeli iş mantığı modülleri, düşük seviyeli modüllere (veritabanı, dosya sistemi, dış servisler) doğrudan bağımlı olmamalıdır; her iki taraf da SOYUTLAMALARA (arayüzlere) bağımlı olmalıdır. Örneğin bir bildirim yöneticiniz doğrudan 'TwilioSmsGonderici' sınıfına somut olarak bağımlıysa, yarın SMS sağlayıcınızı değiştirmek istediğinizde tüm bildirim sistemini baştan yazmanız gerekir. Oysa bildirim yöneticisini 'IBildirimGonderici' isimli bir arayüze bağlarsanız; ister Twilio, ister Telegram botu, ister WhatsApp API olsun, dışarıdan istediğiniz servisi enjekte edebilirsiniz (Dependency Injection).

Özetle SOLID; ezberlenmesi gereken kuru bir kural seti değil, bir yazılımcının düşünme biçimidir. Elbette her 20 satırlık basit script için beş katmanlı mimariler kurmak aşırı mühendisliktir (over-engineering). Ancak ekiple geliştirilen, büyümesi hedeflenen ve geleceğe yatırım yapan projelerde SOLID prensiplerine uymak, projenizi spagetti bir enkazdan yaşayan güçlü bir mühendislik harikasına dönüştürür.

← Diğer Yazılar Fikirlerini Paylaş →