Single Responsibility (SRP) Prensibi

single responsibility prensibi

Her modül, sınıf veya fonksiyon yalnızca tek bir işlevi yerine getirmeli ve tek bir amacı olmalıdır. Amaçla ilişkili olduğu sürece sınıf içerisinde bir çok üye olabilir ve sorumluluk bir sınıf tarafından kapsüllenmelidir. Single responsibility prensibi uygulanarak kodumuz daha atomik ve temiz olmakla birlikte daha az kırılgan (Fragility) olmaktadır.

A class should have only one reason to change. (Bir sınıfın değişmesi için tek bir nedeni olmalıdır.)

Robert C. Martin

Şimdi bu prensibi bir örnekle pekiştirelim. Buna göre kullanıcı kayıt ve giriş işlemlerini yöneten bir uygulamaya ihtiyacımız olduğunu düşünelim. Uygulamamız aynı zamanda giriş ve kayıt işlemleri sonrasında kullanıcıya bilgilendirme amaçlı e-posta gönderecek ve olası bir hata durumunda loglama da yapacaktır. Hemen işe koyulup aşağıdaki kodu yazdığımızı düşünelim.

public interface IUserService
{
    bool SignIn(string userName, string password);
    bool SignUp(string userName, string password, string email);
    void LogError(string error);
    bool SendEmail(string emailContent);
}

Kodumuzu incelediğimizde e-posta gönderme ve loglama işlemlerinin kullanıcı ile bir ilişkisi olmadığını görüyoruz. Ayrıca uygulama içerisinde kullanıcı arayüzünü çağıramadığımız ya da çağırmanın mantık dışı olduğu senaryolarda uygulamanın başka bir yerinde e-posta gönderme ve loglama yapmak istediğimizde aynı kodu tekrar yazmamız gerekecek ve DRY prensibini ihlal etmiş olacağız; bununla birlikte aynı işi yapan iki fonksiyon olduğunu düşünün ve birinde modifikasyon yapıp diğerini unuttuğumuzu…

Single responsibility prensibi uygulayarak kodumuzu uygun hale getirelim.

public interface IUserService
{
    bool SignIn(string userName, string password);
    bool SignUp(string userName, string password, string email);
}
public interface ILoggerService
{
    void LogError(string error);
}
public interface IEmailService
{
    bool SendEmail(string emailContent);
}

Artık tüm arayüzlerimiz tek bir amaca hizmet ederek kendi işlerini gerçekleştirecek sınıflar tarafından implemente edilmeye hazır. Bu sayede ortaya yönetimi ve tekrar kullanılabilirliğini (Reusability) artmış bir yapı çıkmıştır.

Clean Code ile ilgili ufak bir not

Bu konuya burada değinmeden bitirmek istemiyorum. Yukarıda oluşturduğumuz 3 arayüze tekrar göz atalım; hala ufak bir sıkıntı var. Arayüzleri implemente ettiğimizi; kullanıcı giriş ve kayıt işlemleri ve de bir hata yakalandığında e-posta gönderdiğimizi düşünelim.

IEmailService.SendMail fonksiyonuna başlık alanı eklemek istiyoruz. Bu işlemi yaptığımızda bu fonksiyonu nerelerden kaç kere çağırıyorsak hepsini teker teker düzeltmemiz gerekecek. Bu da bir hayli ve yorucu bir iş, özellikle kurumsal büyük projelerde. Kaldı ki bu maliyeti göz önüne alsak bile 50 parametresi olan bir fonksiyon düşünün ve gözlerimizin kanamaya başladığını…

Hemen kodumuzu parametrik açıdan değişikliklere açık ve daha okunabilir hale getirelim.

public class SignIn
{
    public string UserName { get; set; }
    public string Password { get; set; }
}
public class SignUp
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
}
public class Log
{
    public string Error { get; set; }
}
public class Email
{
    public string Title { get; set; }
    public string Content { get; set; }
}

Artık modellerimizi oluşturduğumuza göre arayüzlerimizi de değiştirebiliriz.

public interface IUserService
{
    bool SignIn(SignIn signIn);
    bool SignUp(SignUp signUp);
}
public interface ILoggerService
{
    void LogError(Log log);
}
public interface IEmailService
{
    bool SendEmail(Email email);
}

You may also like...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir