Back to Basics: SOLID Principles (Interface Segregation)

Writing clean code is one of the core precepts of software development.

There are various software design approaches to ensure an understandable, flexible, and maintainable code base.

In this post, we will be try understand the fourth SOLID principle and how it can help us become better developers.

Interface Segregation Principle

A client should not be forced to implement an interface that it does not use.

Let's take an example to understand what this means:

class ShapeInterface:
    def area(self):
        pass

class Square(ShapeInterface):
    def area(self):
        """area of square = a^2"""
        pass

class Rectangle(ShapeInterface):
    def area(self):
        """area of rectangle = l*b"""
        pass

The above example is good as it follows all our object-oriented programming principles. Now let's add a volume method for shapes like Sphere or a Cylinder.

class ShapeInterface:
    def area(self):
        pass

    def volume(self):
        pass

class Square(ShapeInterface):
    def area(self):
        """area of square = a^2"""
        pass

    def volume(self):
        raise NotImplemented

class Rectangle(ShapeInterface):
    def area(self):
        """area of rectangle = l*b"""
        pass

    def volume(self):
        raise NotImplemented

class Sphere(ShapeInterface):
    def area(self):
        """area of sphere = 4πr^2"""
        pass

    def volume(self):
        """volume of sphere = (4/3)*πr^3"""
        pass

Since 2D shapes cannot have any volume, the Square and Rectangle class are forced to implement methods of an interface they don't have any use of.

Solution?

ISP says that interfaces should perform only one job (just like the SRP principle) any extra grouping of behavior should be abstracted away to another interface.

To conform to ISP we will segregate the volume method to another interface which will be used by 3D shapes.

class TwoDShapeInterface:
    def area(self):
        pass

class ThreeDShapeInterface(TwoDShapeInterface):
    def volume(self):
        pass

class Square(TwoDShapeInterface):
    def area(self):
        """area of square = a^2"""
        pass

class Rectangle(TwoDShapeInterface):
    def area(self):
        """area of rectangle = l*b"""
        pass

class Sphere(ThreeDShapeInterface):
    def area(self):
        """area of sphere = 4πr^2"""
        pass

    def volume(self):
        """volume of sphere = (4/3)*πr^3"""
        pass

Now we have 2 Interfaces; TwoDShapeInterface and ThreeDShapeInterface. TwoDShapeInterface as the name suggests contains methods that are only required for 2D shapes like square, rectangle, etc. while ThreeDShapeInterface extends TwoDShapeInterface and has 3D shapes related methods like volume calculation for shapes like Sphere.

This post is Part 4 of the series, Back to Basics, each covering one SOLID principle.

14