Interface Segregation Principle

Uncle Bob introduced this principle when he collaborated with Xerox. They couldn't cope with the ever-long process of implementing changes to their code. The rule is: “No client should be forced to depend on methods it does not use”. The user of the interface should not be forced to rely on methods he does not use. We should not use “fat interfaces” that declare multiple methods if any of them could be left unused. Better to have a few dedicated small interfaces than one that is too general. It is also in line with the single responsibility principle.
So let's see a badly written code, not following the interface segregation principle. I present to you the Exportable, PHP Interface. An interface that allows you to export something to PDF and export something to CSV. We also have an Invoice and a CreditNote class.
interface Exportable
{
public function getPDF();
public function getCSV();
}
class Invoice implements Exportable
{
public function getPDF() {
// ...
}
public function getCSV() {
// ...
}
}
class CreditNote implements Exportable
{
public function getPDF() {
throw new \NotUsedFeatureException();
}
public function getCSV() {
// ...
}
}
We can download the Invoice in PDF and CSV. We can download a CSV of the CreditNote. But downloading the PDF of the CreditNote was a useless functionality and was not implemented (it’s throwing an exception right now).
We shouldn't force our interface implementations to implement methods they don't use. In the above case, we forced the CreditNote class to do so, it implements the getPDF() method even though it does not need it at all.
So how should it look to be good?
According to the interface segregation principle, we have to separate the interfaces. We divide Exportable and create an interface ExportablePdf and create an interface ExportableCSV.
interface ExportablePdf
{
public function getPDF();
}
interface ExportableCSV
{
public function getCSV();
}
class Invoice implements ExportablePdf, ExportableCSV
{
public function getPDF() {
//
}
public function getCSV() {
//
}
}
class CreditNote implements ExportableCSV
{
public function getCSV() {
//
}
}
This way, CreditNote no longer has to worry about implementing not used getPDF() public function. If necessary in the future, just need to use a separate interface and implement it. As you can see here, specific interfaces are better.
The example of ReadOnlyFile related to the Liskov principle is also a good example of the Interface segregation principle. There, the File class has been doing too many things, it's better to have separate interfaces for each action.
That's interface segregation, easy.
Conclusion
The conclusion here is simple, we can end up with a "fat" class with multitudes of methods specific to a variety of different features. A system may become so coupled at multiple levels that it is no longer possible to make a change in one place without necessitating many additional changes.
