Interface Segregation Principle Nedir?

Öncelikle bu prensibin dayandığı anafikri genel çerçevede açıklamaya çalışıp ,ardından bir örnek üzerinden giderek yazımıza devam edelim. Elimizde ortak özellikler barındıran birçok sınıf olduğunu düşünelim. Genelde böyle durumlarda bu sınıfları ortak olan tek bir interface'i uygulayarak oluştururuz. Bu elbette ilk etapta mantıklı ve işimizi gören bir yaklaşımdır. Fakat bizim geliştirdiğimiz uygulama tabiki genişletilebilir bir yapıya sahip olacak ve ilerde uygulamamıza bu sınıflara benzer yeni sınıflar ekleme ihtiyacı duyacağız. Bunu yaparken tabiki ilk yapacağımız şey, bu yeni sınıflarıda aynı interface' i uygulayarak yaratmak olacaktır. Fakat yeni sınıfımızın yapısı gereği, bu interface içinde bulunan bazı üyeleri kullanması doğru ve mantıklı değildir. İşte bizim sorunumuz da tam bu noktada ortaya çıkıyor. Sınıfların, interface içinde kullanmayacağı kesin olarak belli üyeler varsa ve bunlar sınıfın yapısına aykırı bir durum sergiliyorsa, sınıfın bu interface'i uygulaması doğru değildir. Çözüm ilk etapta yeni bir interface yaratıp, yeni sınıfa onu uygulamak gibi görünsede bu durumda pek sağlıklı değildir. Çünkü ilerde bu tarz sınıfların sayısının arttığı bir durumda, sınıf hiyerarşisi içinden çıkılamayacak kadar karışık bir hal almaya başlar.Bunuda kimse istemez herhalde.Peki ozaman ne yapacağız? Çözüm o kadar da zor değil aslında.Tek yapmamız gereken şey ,interfaceleri oluştururken barındırdığı üyeleri ortak olacak şekilde parçalayıp, bu üyeleri farklı interface'ler altında toplayıp,ayrı ayrı interface'ler oluşturmak o kadar.Bu genel açıklamadan sonra şimdi somut bir örnek ile ne demek istediğimizi çok daha net bir şekilde örnekleyelim. Kullanacağım örnek genelde bu prensibin anlatılırken kullanıldığı bir senaryoya sahip . Bende bu örneğin, sorunu ve çözümünü çok güzel açıkladığını düşündüğüm için aynen kullanacağım. Örneğimizde işçilerin ortak özelliklerini barındıran IWorker adında bir interface mevcut. Bu interface içinde işçilerin çalışma yeteneğini gösteren Workadında bir method ve yemek yeme yeteneğini gösteren Eat adında bir method var .Bunun dışında bu interface'i uygulayan normal bir çalışan olan Worker ve daha çok çalışan SuperWorker adında 2 tane işçi sınıfı var .Bütün işçi tipleride bu interface'i uygulayarak yaratılıyor .Yani biz yeni bir işçi sınıfı tanımlamak istersek bunuda IWorkerinterface'ini uygulayarak yaparız. Böylece bizim bütün işçilerimiz hem çalışıp hemde yemek yiyebilme yeteneklerine sahip olmuş oluyor.Son olarak birde Manager adında, işçilerin ne yapmasını gerektiğini söyleyen bir sınıf mevcut.

public interface IWorker
{
    void Work();
    void Eat();
}
public class Worker : IWorker
{
    public void Work()
    {
        Console.WriteLine("Az is yapar");
    }
    public void Eat()
    {
        Console.WriteLine("Az yemek yer");
    }
}
public class SuperWorker : IWorker
{
    public void Work()
    {
        Console.WriteLine("Cok is yapar");
    }
    public void Eat()
    {
        Console.WriteLine("Cok yemek yer");
        }
}
public class Manager
{
    IWorker worker;
    public void SetWorker(IWorker w)
    {
        worker = w;
    }
    public void Manage()
    {
        worker.Work();
    }
}

Buraya kadar herşey çok güzel ve sorunsuz görünüyor. Şimdi size herşeyin açıklanmasına neden olacak soruyu sormak istiyorum. Uygulamayı geliştirdiğiniz fabrika, insan işçilerin yanına bir de robot işçiler almaya karar verdi ! Robot olmasına rağmen sonuçta o da bir işçidir. Bu durumda robot sınıfının mutlaka IWorker interface' ini uygulaması gerekiyor. Fakat robotlar yemek yemez. Biz bu örnekte sadece yemek yeme olayı üzerinden gittik. Fakat bu kompleks bir sınıf olsaydı, robot yapısına aykırı bir çok olay olacaktı.Örneğin maaş gibi veya izin kullanma hakkı gibi.Bu örnekler çoğaltılabilir. Hal böyleyken bu kadar farklı yeteneklere sahip yeni bir robot sınıfının, bu özellikleri bünyesinde barındırması onu robot olmaktan çıkarır aslında. Bu da asla doğru bir tasarım şekli değildir. Çözüm yukarda da dediğimiz gibi temel interface ' i parçalayıp, çalışabilen ve yemek yiyebilen gibi 2 farklı interface yaratmak. Sonra eklenecek olan işçi sınıflarına bu interfaceler 'den uygun olanlarını seçip, onları uygulamak. Kodun revize edilmiş hali aşağıdaki gibidir.

 public interface IWorkable
  {
      void Work();
  }
  public interface IFeedable
  {
      void Eat();
  }
  public class Worker : IWorkable, IFeedable
  {
      public void Work()
      {
          Console.WriteLine("Az is yapar");
          }
      public void Eat()
      {
          Console.WriteLine("Az yemek yer");
      }
  }
  public class SuperWorker : IWorkable, IFeedable
  {
      public void Work()
      {
          Console.WriteLine("Cok is yapar");
      }
      public void Eat()
      {
          Console.WriteLine("Cok yemek yer");
      }
  }
  public class Robot : IWorkable
  {
      public void Work()
      {
          Console.WriteLine("Cok fazla is yapar, yemek yemez");
      }
  }
  public class Manager
  {
      IWorkable worker;
      public void SetWorker(IWorkable w)
      {
          worker = w;
      }
      public void Manage()
      {
          worker.Work();
      }
  }

Interface 'lerin parçalanıp ayrı ayrı ele alınması gerektiğini söyleyen tasarım prensibimiz işte bu kadar arkadaşlar. Aslında şunu söylmekte fayda var diye düşünüyorum. Diğer tüm prensiplerde olduğu gibi bu prensipte de, zor olan şey; prensiplere uygun bir şekilde kod yazmak değil, prensiplere aykırı olan durumları tespit etmektir. Bu da aslında öyle çok zor bir şey değil ve zamanla aşılabilecek bir durumdur. Bu tarz tasarımsal problemler ile karşılaştıkça ve buna kafa yordukça, herhangi bir sınıf hiyerarşisine veya koda şöyle bir bakınca, bir çok eksikliğini ve güzelliğini görebilecek duruma geliyorsunuz zaten.

Last updated

Was this helpful?