c#

interface segregation main purpose and uses of interface c#

A
Desh-Duniya Team Author
| Published September 16, 2019

interface segregation main purpose and uses of interface c#

According to Wikipedia the interface segregation principle (ISP) states that no client should be forced to depend on methods it does not use. For the sake of this post I will use the term “server” to describe a class in an API – a business object for example. “Client” will be used to describe the consumer of a service – it could be a user interface component for example. The client has a dependency on a server at some level, the server knows nothing about a client.

As an example, let’s assume a team responsible for creating the server was tasked with creating a basic email object. Being good programmers, they designed to an interface and came up with the following Interface and implementation.

public interface IMessage
    {

        IList<String> ToAddresses { get; set; }

        string MessageBody { get; set; }

        string Subject { get; set; }

        bool Send();

    }

     public class SmtpMessage:IMessage

    {

        public IList<String> ToAddresses { get; set; }

        public string MessageBody { get; set; }

        public string Subject { get; set; }

         public bool Send()

        {

            //Do the real work here

            return true;

        }

    }

Client Team A, responsible for creating an application that sends an email reminder as a part of their process, creates a client that consumes the server, and everything works. Now assume the server team gets a new requirement, from Client Team B, and now they need to support sending a text message. That’s almost the same as sending an email message so they decide to be polymorphic and use the IMessage interface.

public class SmsMessage : IMessage

    {

        public IList<String> ToAddresses { get; set; }

        public string MessageBody { get; set; }

        public bool Send()

        {

            //Do the real work here

            return true;

        }

        public string Subject

        {

            get

            {

                throw new NotImplementedException();

            }

            set

            {

                throw new NotImplementedException();

            }

        }

    }

Client Team B is happy, things work great and Client Team A is happy because now they can send SMS messages if they want to. Client Team A wants to enhance their system to allow for a list of addresses to be included as a blind copy, so they give the Server team this new requirement. The server team comes up with the following change to the interface and new implementations:

public interface IMessage

    {

        IList<String> ToAddresses { get; set; }

        string MessageBody { get; set; }

        string Subject { get; set; }

        bool Send();

        IList<String> BccAddresses { get; set; }

    }

 

    public class SmtpMessage:IMessage

    {

        public IList<String> ToAddresses { get; set; }

        public IList<String> BccAddresses { get; set; }

        public string MessageBody { get; set; }

        public string Subject { get; set; }

 

        public bool Send()

        {

            //Do the real work here

            return true;

        }

    }

 

    public class SmsMessage : IMessage

    {

        public IList<String> ToAddresses { get; set; }

        public string MessageBody { get; set; }

        public bool Send()

        {

            //Do the real work here

            return true;

        }

        public string Subject

        {

            get

            {

                throw new NotImplementedException();

            }

            set

            {

                throw new NotImplementedException();

            }

        }

        public IList<string> BccAddreses

        {

            get

            {

                throw new NotImplementedException();

            }

            set

            {

                throw new NotImplementedException();

            }

        }

    }

Client Team A gets the new server and things are great, but Client Team B is now broken and must recompile and go through a round of regression testing because a feature was added for another team.

The main goal of the interface segregation principle is to loosen the coupling between servers and their clients. An SMS message supports a list of addresses, a message body, and the notion of sending but Client B was unnecessarily also coupled to the Subject and eventually the BccAddressList property. In short, a change to Any unused property or method or a change to an overly broad interface itself will cause Team B problems. Let’s rework things a little bit and see if we can improve the design.

public interface IMessage

    {

        IList<String> ToAddresses { get; set; }

        string MessageBody { get; set; }

        bool Send();

    }

 

    public interface IEmailMessage:IMessage

    {

        string Subject { get; set; }

        IList<String> BccAddresses { get; set; }

    }

 

    public class SmtpMessage : IEmailMessage

    {

        public IList<String> ToAddresses { get; set; }

        public IList<String> BccAddresses { get; set; }

        public string MessageBody { get; set; }

        public string Subject { get; set; }

        public bool Send()

        {

            //Do the real work here

            return true;

        }

    }

 

    public class SmsMessage : IMessage

    {

        public IList<String> ToAddresses { get; set; }

        public string MessageBody { get; set; }

        public bool Send()

        {

            //Do the real work here

            return true;

        }

    }

With this design we have a nice crisp IMessage definition that will serve Client B very well in that the client does not depend on any methods it does not use. We have created a “wider” interface Called IEmailMessage that inherits from IMessage for Team A to use so Team A can send Email or an SMS text message.

If we want to remove the requirement that a Client understand it needs to set the address list and message body before calling the send method, we could also do this:

public interface IMessage

    {

        bool Send(IList<String> toAddresses, string messageBody);

    }

 

    public interface IEmailMessage:IMessage

    {

        string Subject { get; set; }

        IList<String> BccAddresses { get; set; }

    }

 

    public class SmtpMessage : IEmailMessage

    {

        public IList<String> BccAddresses { get; set; }

        public string Subject { get; set; }

        public bool Send(IList<String> toAddresses, string messageBody)

        {

            //Do the real work here

            return true;

        }

    }

 

    public class SmsMessage : IMessage

    {

        public bool Send(IList<String> toAddresses, string messageBody)

        {

            //Do the real work here

            return true;

        }

    }

Discussion (0)

Please sign in to participate in the discussion.
No comments yet. Be the first to join the conversation!