Interface Segregation Principle

SOLID prensipleri yazı dizisinde sırada SOLID'in "I" olan Interface Segregation (ISP) var. Bu prensip bize kısaca şunu söylüyor; "Nesneler asla ihtiyacı olmayan property/metot vs içeren interface'leri implement etmeye zorlanmamalıdır  !".

Terminolojide bu interface'ler "fat" yada "polluted" interfaces diye adlandırılır.  ISP uygulanmadığında bir den fazla sorumluluğu olan nesneler ortaya çıkar ki bu da aslında SOLID'in "S" si olan "Single Responsibility" prensibine aykırı bir şeydir. Bu sınıflar yüklenen çoklu sorumluluklardan dolayı zaman içerisinde yönetilemez hale gelirler ve projemiz patates olur çıkar. Bu tarz case'ler le karşılaşıldığında interface içerisinde bulunan kullanılmaması gereken özellikleri içeren yeni interface'ler tanımlanır ve ihtiyaca göre nesneler tarafından implement edilir. Eğer projeniz bu prensibi ihlal ediyorsa Adapter Design Pattern avantajlarını kullanarak da ilerleyebilirsiniz. İlgili nesne interface'i implement edip hiç kullanmayacağı metotlara sahip olduğunda class'ınız içerisinde "NotImplementedException" yazan metotlar olacaktır ve buda OOP açısından hiç istenen bir şey değildir.

ISP'yi örnek bir case üzerinde anlatmaya çalışalım. Bir tane FileLog ve DbLog yapan işlemleri yapan bir proje geliştireceğiz ve içerisinde ILog adında bir interface tanımlayalım ve bu interface'inde Log(), OpenConn(), CloseConn() gibi metodları olsun.

public interface ILog
{ 
    void Log(string message);

    void OpenConnection();

    void CloseConnection();
}

 

İlk olarak DBLogger sınıfını yazalım

public class DBLogger : ILog
{		
        public void Log(string message)
        {
            //Code to log data to a database
        }

        public void OpenConnection()
        {
            //Opens database connection
        }

        public void CloseConnection()
        {
           //Closes the database connection
        }
}

 

Şimdi de FileLogger class'ını yazalım. 

public class FileLogger : ILog
    {
        public void Log(string message)
        {
            //Code to log to a file           
        }
    }

FileLog işlemi yaparken Db de olduğu gibi bir Connection açıp kapama işlemi yok ve bu metotları FileLogger'da kullanmak istemiyoruz sadece ILog interface'inde tanımlı olan Log(string message) metodunu kullanmak istiyoruz. Projeyi derlediğinizde şöyle bir hata alırsınız "FileLogger class doesn't implement the interface members ILog.OpenConnection() and ILog.OpenConnection()" .  Peki hatayı görüp eksik interface'in eksik üyelerini implement edelim. Bu sefer class'ımız aşağıdaki gibi olacaktır.

public class FileLogger : ILog
    {
        public void Log(string message)
        {
             //Code to log to a file           
        }

        public void CloseConnection()
        {
            throw new NotImplementedException();
        }

        public void OpenConnection()
        {
            throw new NotImplementedException();
        }
    }

E şimdi ne oldu ? Patates ! Hiç ihtiyacımız olmasa da FileLogger class'ına 2 tane gereksiz metot kazandırdık. İşte ISP burada devreye giriyor. Yapmamız gereken şey yeni interface veya interface'ler tanımlayarak FileLogger ve DbLogger class'larının sadece ihtiyacı olan metotları içeren interface'i implemente etmesini sağlamak.

Yeni interface'ler aşağıdaki gibi olacaktır.

    public interface ILog
    {
        void Log(string message);
    }

    public interface IDBLog: ILog
    {
        void OpenConnection();

        void CloseConnection();
    }

    public interface IFileLog: ILog
    {
        void CheckFileSize();

        void GenerateFileName();
    }

 

Bu interface'leri implement eden DbLogger ve FileLogger class'larımızda aşağıdaki gibidir.

 public class FileLogger : IFileLog
    {
        public void CheckFileSize()
        {
            //Code to check log file size
        }

        public void GenerateFileName()
        {
            //Code to generate a new file name
        }
		
        public void Log(string message)
        {
            //Code to log data to the log file
        }
    }

    public class DBLogger : IDBLog
    {
        public void Log(string message)
        {
            //Code to log data to the database
        }

        public void OpenConnection()
        {
            //Code to open database connection
        }

         public void CloseConnection()
         {
            //Code to close database connection
         }
    }

Interface Segregation çok önemli bir prensiptir. Özellikle Adapter Design Pattern ile haşır neşir olan arkadaşlar için dahada fazla öneme sahiptir. İçerisinde 60-70 tane üyesi bulunan interface'ler yazmaktan da çekinin bu gibi durumlarda bir yolunu bulup interface üyelerini ayırıp gruplayıp yeni interface'ler türetmeye çalışmamız daa doğru olacaktır. 

Add comment