test13
test13

Reputation: 37

How to apply Interface segregation principle?

I have a public interface that creates a bunch of different specific objects by client, and the only thing in common is that they all need to be serialized as xmls.

Something like this:

public interface IBuildXmlService
{
    XmlObject1 BuildClient1Xml(CustomObjectWithClient1Data data);
    XmlObject2 BuildClient2Xml(CustomObjectWithClient2Data data);
    XmlObject3 BuildClient3Xml(string string1, int int1);
    XmlObject4 BuildClient4Xml(CustomObjectWithClient4Data data);
}

Now this interface started to get big, and I'm definitely sure this is not a good sign. Also every time I inject the interface into a client specific class, that client specific class has access to all the other object creation methods for other clients.

Now the first thing I thought about was to just move the object creation method as a private method in client specific class, but this results in quite some big files.

Then I thought to use the factory method pattern to create a IXmlFactory with a BuildXml method for the object creation part, but this doesn't seem to work since I have different objects to return.

Can anyone give me some advice about what design pattern should I look for?

Upvotes: 0

Views: 306

Answers (1)

StepUp
StepUp

Reputation: 38114

I have a public interface that creates a bunch of different specific objects by client, and the only thing in common is that they all need to be serialized as xmls.

So it can be concluded that there is no common between these objects. Even parameters of these methods are different.

So my suggestion is to separate all methods and create separate interface for each object:

public interface IBuildXmlServiceXmlObject_1 
{
    XmlObject1 BuildClient1Xml(CustomObjectWithClient1Data data);
}

public interface IBuildXmlServiceXmlObject_2
{
    XmlObject2 BuildClient2Xml(CustomObjectWithClient2Data data);
}

public interface IBuildXmlServiceXmlObject_3 
{   
    XmlObject3 BuildClient3Xml(string string1, int int1);
}

public interface IBuildXmlServiceXmlObject_4 
{       
    XmlObject4 BuildClient4Xml(CustomObjectWithClient4Data data);
}

Why is it better to have separate interfaces? Because Interface Segregation Principle is how interface can be consumed. So, whether it is necessary to consume other methods of interface or don’t depend on more than you need.

An example with HDD that uses ISP:

public interface IReadable
{
    string Read();
}

public interface IWriteable
{
    void Write();
}

public class HDD : IReadable, IWriteable
{
    public string Read() { }

    public void Write()  { }
}

By creating one interface for Read() and Write() methods, it would obligate class to implement both methods in class. But some classes only want to read data, others want to write data, and some to do both. E.g. card reader might want to read data. So in this case it is better to create separate interfaces.

So let's look another example with CardReader. CardReader just reads data, it does not write data. So, if we inherit one interface with Read() and Write() methods, then we would violate ISP principle. An example of violation of ISP:

public interface IWriteReadable
{
    string Read();
    void Write();
}

public class CardReader : IWriteReadable
{
    // this is a necessary method
    public string Read() { }

    // here we are obligating to implement unnecessary method of interface
    public void Write() { }
}

So by applying ISP, you only puts methods in interface that are necessary for the client class. If your class/client just wants to read data, then you need to use IReadable interface, not IReadableWriteable.

Upvotes: 1

Related Questions