SRP (Single Responsibility Principle) — SOLID'in ilk ilkesidir ve şunu belirtir: her sınıf veya modülün değişmek için tam olarak bir nedeni olmalıdır. Bu ilke Robert Martin tarafından Clean Architecture (2017) kitabında formüle edilmiş ve modüler tasarımın temeli haline gelmiştir. Bu kitaba göre, SRP uygulamak bileşenlerin bağlılığını doğrudan azaltır ve işlevsellik değişikliğinde zincirleme değişiklikleri ortadan kaldırır.
Anahtar noktalar
SRP (Single Responsibility Principle) tek sorumluluk ilkesidir ve şunu belirtir: her sınıf veya modülün değişmek için tam olarak bir nedeni olmalıdır. Bu, bir sınıfın tam olarak bir işlem yapması gerektiği anlamına gelmez. Bir aktöre karşı tek bir sorumlulukta birleşmiş ilgili eylemler grubunu ifade eder.
Robert Martin SRP'yi aktörler açısından yeniden tanımladı: bir sınıf yalnızca bir paydaş veya bir grup insanın talebi üzerine değişmelidir. İki farklı aktör aynı sınıfta değişiklik talep ediyorsa, sorumluluk yanlış bölünmüştür.
Örneğin, hem maaş hesaplama (muhasebe bölümü talebi) hem de rapor oluşturma (yönetim talebi) yapan bir Employee sınıfı SRP'yi ihlal eder. Hesaplama kurallarındaki bir değişiklik rapor oluşturmayı etkileyebilir ve bunun tersi de geçerlidir.
Bir modülün değişmek için bir ve yalnızca bir nedeni olmalıdır. Değişim nedeni bir aktör tarafından belirlenir — gereksinimi başlatan kişi veya sistem. Farklı aktörlerden gelen gereksinimler tek bir modülte değişikliğe yol açıyorsa, modül SRP'yi ihlal ediyordur.
Aktör kavramı, SRP'yi soyut bir öneri değil, pratik bir mimari analiz aracı haline getirir. Bir sistemi tasarlarken şu soruyu sormak yeterlidir: “Bu kodu kim değiştirmemi isteyecek?” — yanıt birden fazla paydaş içeriyorsa, sorumluluk bölünmelidir.
Tek sorumluluk, aynı nedenle değişen metotları gruplayarak uygulanır. Bir sınıf, her durum için bir “İsviçre çakısı” değil, ilgili mantığın bir “toplama noktası” haline gelir. Bu, kodu anlamayı basitleştirir: geliştirici sınıfı görür ve amacını hemen anlar.
SRP'nin mekanizması tek değişim ekseni kuralına dayanır. Bir işlevsellik bağımsız nedenlerle değişebiliyorsa, ayrı sınıflara çıkarılmalıdır. Bu sınıflar arasındaki bağlantılar composition veya delegasyon yoluyla kurulur.
SRP ihlali, “God Object”lerde kendini gösterir — farklı verilerle çalışan düzinelerce metodu olan sınıflar. Böyle bir sınıfı test etmek zordur — bir metodu test etmek, diğerlerinin tümü için ortamın kurulmasını gerektirir. Bir sorumluluğu değiştirmek diğerini bozabilir ve kodu kırılgan hale getirebilir.
Pratikte SRP, geliştiricilerin “Bu kod nerede?” sorusunu yanıtlamasına yardımcı olur. Her sorumluluk kendi sınıfında ayrılmışsa, doğru dosyayı bulmak saniyeler alır. MVVM mimarisine sahip bir Android projesinde, UserViewModel yalnızca kullanıcı ekranı durumundan, UserRepository ise veri alımından sorumludur. Önbellek mantığını arayan bir geliştirici ViewModel'e değil, UserCacheRepository'ye gider. Böyle bir kod organizasyonu yeni ekip üyelerinin uyum sürecini hızlandırır ve yeniden düzenleme sırasındaki hata sayısını azaltır.
Mobil geliştirme, kod modülerliğine özel talepler getirir. Bir Android Fragment veya iOS ViewController genellikle bir mantık “mıknatısı” haline gelir: dokunma işleme, API çağrıları, yanıt ayrıştırma, UI güncelleme — hepsi tek bir sınıfta. SRP bu sorumlulukların ayrılmasını gerektirir.
Android mimarisinde SRP, Google'ın Jetpack önerilerine yerleştirilmiştir: ViewModel ekran durumundan, Repository verilerden, UseCase iş mantığından sorumludur. iOS geliştirmede MVVM ve Coordinator pattern'leri aynı mantığı izler.
Mobil projelerde SRP'yi takip etmek ölçülebilir faydalar sağlar: sınıf boyutunda %40-60 azalma, kod incelemelerinde daha az zaman ve yeni işlevsellik eklerken daha az regresyon hatası. Yalıtılmış modüller birim testlerle kapsanması ve diğer ekranlarda yeniden kullanılması daha kolaydır.
SRP'ye uyan sınıfların birim testleri daha az mock nesne ve daha az yapılandırma gerektirir. Bir sınıfın tek bir sorumluluğu varsa, bağımlılıkları sınırlıdır. Test, birden fazla ilgisiz senaryonun kombinasyonunu değil, tek bir davranışı doğrular.
Google Testing Blog (2023) raporuna göre, tek sorumluluğa sahip sınıflar, toplayıcı sınıflara kıyasla %35 daha yüksek test kapsamı gösterir. Geliştiriciler küçük, anlaşılması kolay modüller için daha isteyerek test yazar.
SRP'yi ihlal eden tipik bir Android sınıfına bakalım — veri yükler, yanıtı ayrıştırır ve UI'yi günceller. Yeniden düzenlemeden sonra, her sorumluluk kendi bileşeninde ayrılır.
// SRP ihlali: tek bir sınıf her şeyi yapar
class BadUserProfileActivity {
fun loadUser(userId: Int) {
// HTTP isteği
// JSON ayrıştırma
// UI güncelleme
// Veritabanına kaydetme
}
}
// SRP uygulandıktan sonra
class UserRepository {
fun getUser(userId: Int): User
}
class UserViewModel {
private val repo: UserRepository
fun loadUser(userId: Int) { }
}
class UserProfileFragment {
fun render(user: User) { }
}
iOS Swift'te ağ katmanı ve görüntülemenin ayrılmasıyla benzer bir örnek:
// SRP ihlali: ViewController verileri ve UI'yı yönetir
class BadProfileViewController: UIViewController {
func viewDidLoad() {
// URLSession isteği
// JSON kod çözme
// Label güncelleme
}
}
// SRP uygulandıktan sonra
protocol UserServiceProtocol {
func fetchUser(id: Int) async throws -> User
}
class ProfileViewModel {
private let service: UserServiceProtocol
func loadProfile(id: Int) { }
}
class ProfileViewController: UIViewController {
func display(user: User) { }
}
SRP yeniden düzenlemesi mimariyi karmaşıklaştırmaz — sorumluluğu yeniden dağıtır. Tekrarları ortadan kaldırarak kod miktarı azalabilir bile. Her yeni sınıfın net bir amacı vardır ve bağımsız olarak geliştirilebilir.
Composition, kalıtımın gereksiz bağlılıklar yarattığı yerlerde SRP'yi korumaya yardımcı olur. Düzinelerce metoda sahip bir süper sınıf yerine, alt sınıf kurucu aracılığıyla bir dizi uzmanlaşmış nesne alır. Her nesne kendi işlevselliğinden sorumludur.
Android geliştirmede, Decorator pattern'i orijinal sınıfı değiştirmeden sorumluluk eklemeye izin verir. iOS'ta, ağ katmanındaki bir Middleware zinciri, günlükleme, önbellekleme ve kimlik doğrulamayı ayrı modüllere ayırır.
En yaygın ihlal bir “God Class”dır: veritabanını yöneten, bildirimler gönderen, raporlar oluşturan ve kullanıcı girdisini işleyen bir sınıf. Böyle bir sınıf projenin darboğazı haline gelir: herhangi bir değişiklik tam regresyon testi gerektirir.
Mobil geliştirmede, Activity, Fragment veya ViewController'da iş mantığı ve UI mantığının karıştırılması SRP ihlaline yol açar. Bir onClickListener aynı anda verileri doğruluyor, bir API çağırıyor ve düğmelerin görünürlüğünü güncelliyorsa — bu, tek sorumluluk ilkesinin doğrudan ihlalidir.
SRP ihlalinin sonuçları şunları içerir: paralel geliştirmede zorluk (tek dosyada çakışmalar), zor birim testi, yüksek değişiklik maliyeti ve düşük kod okunabilirliği. Sistematik SRP ihlalleri olan projeler, yeni işlevsellik eklemek için 2-3 kat daha fazla zaman gerektirir.
SRP ihlalleri dolaylı işaretlerle tanınabilir: sınıf 200 satırı aşar, farklı uygulama katmanlarından (UI + network + database) modüller içe aktarır, farklı konularda 5'ten fazla genel metoda sahiptir. Bağlılık metriği istatistiksel bir göstergedir: bir sınıf içindeki metotların düşük bağlılığı SRP ihlaline işaret eder.
SRP ihlallerini tespit etmek için statik analiz araçlarını kullanın: Android için TooManyFunctions kuralıyla Detekt, iOS için file_length kuralıyla SwiftLint. Bu araçlar, boyut ve karmaşıklık eşiklerini aşan sınıfları vurgular.
SRP'yi ihlal eden sınıfların yeniden düzenlenmesi Extract Class veya Extract Delegate ile yapılır: ilgili metotlardan oluşan bir grup ayrı bir sınıfa çıkarılır ve orijinal sınıf çağrıları onlara devreder. Bu yeniden düzenlemelerin kademeli olarak uygulanması, bir “God Class”ı her biri tek bir sorumluluğa sahip, gevşek bağlı modüller kümesine dönüştürür. Bu yaklaşım, geliştirmeyi durdurmadan mimariyi iyileştirmeye olanak tanır — yeniden düzenleme yinelemeli olarak, her seferinde bir modül yapılır.
Sıkça sorulan sorular
Hayır. SRP metot sayısıyla değil, değişim nedenlerinin sayısıyla ilgilidir. Bir sınıf, tümü tek bir aktöre karşı tek bir sorumluluğa hizmet ediyorsa düzinelerce metoda sahip olabilir. Tek bir metot, kodun aşırı parçalanmasına yol açan diğer uç noktadır.
Aynı ilkedir. Single Responsibility Principle hem “tek sorumluluk” hem de “tek yükümlülük” olarak çevrilir. “Sorumluluk” terimi özü daha iyi yansıtır: teknik bir işlevden değil, bir aktöre karşı sorumluluktan bahseder.
Repository, SRP'nin veri katmanına uygulanmasının doğrudan bir sonucudur. Veri erişim mantığını ViewModel veya UseCase'e yaymak yerine, Repository tek bir sorumluluk üstlenir: kaynak soyutlamasıyla veri sağlamak. Bu, mobil mimaride SRP'nin klasik bir uygulamasıdır.
Evet, SRP bağımlılıkları yasaklamaz. Tek sorumluluğa sahip bir sınıf, composition aracılığıyla işin bir kısmını diğer sınıflara devredebilir. Önemli olan, bu devredilen görevlerin aynı sorumluluğun parçası olması, bağımsız bir değişim nedeni olmamasıdır.
Şu soruyu sorun: “Hangi aktörler bu sınıfta değişiklik talep edebilir?” Yanıt birden fazla aktör içeriyorsa, SRP ihlal edilmiştir. Ek olarak: sınıfın amacını “ve” bağlacı olmadan tek bir cümleyle tanımlamaya çalışın. Yapamıyorsanız, sınıf çok fazla şey yapıyordur.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun