I is the Interface Segregation Principle: a client should not depend on methods it does not use. Instead of one big ("fat") interface we write several small ones, by role. Every class implements only the roles it can play and every client asks only for the role it needs.
The violation: a fat interface
Machine demands three operations. A multifunction device can do all of them, while an old printer only prints but is forced to write scan and fax. Such a class usually writes raise NotImplementedError and a client crashes when it calls scan().
Machine on the left, three role interfaces on the rightfrom abc import ABC, abstractmethod
class Machine(ABC): # a fat interface
@abstractmethod
def print_doc(self, doc): ...
@abstractmethod
def scan(self): ...
@abstractmethod
def fax(self, doc): ...
class MultiFunction(Machine):
def print_doc(self, doc):
return f"print {doc}"
def scan(self):
return "scan"
def fax(self, doc):
return f"fax {doc}"
class OldPrinter(Machine): # forced to implement what it cannot do
def print_doc(self, doc):
return f"print {doc}"
def scan(self):
raise NotImplementedError("no scanner")